Fix the drunk fix

This should finally be correct fsp src-to-dst array syncing now..
There's a few edge cases but mostly we need to be sure we sync both
back-filled history diffs and avoid current step lag/leads. Use
a polling routine and the more stringent task re-spawn system to get
this right.
fsp_drunken_alignment
Tyler Goodlet 2021-10-04 16:34:54 -04:00
parent 086aaf1d16
commit 3dd82c8d31
1 changed files with 62 additions and 32 deletions

View File

@ -148,24 +148,27 @@ async def fsp_compute(
# import time # import time
# last = time.time() # last = time.time()
# rt stream try:
async for processed in out_stream: # rt stream
async for processed in out_stream:
log.debug(f"{func_name}: {processed}") log.debug(f"{func_name}: {processed}")
index = src.index index = src.index
dst.array[-1][func_name] = processed dst.array[-1][func_name] = processed
# NOTE: for now we aren't streaming this to the consumer # NOTE: for now we aren't streaming this to the consumer
# stream latest array index entry which basically just acts # stream latest array index entry which basically just acts
# as trigger msg to tell the consumer to read from shm # as trigger msg to tell the consumer to read from shm
if attach_stream: if attach_stream:
await stream.send(index) await stream.send(index)
# period = time.time() - last # period = time.time() - last
# hz = 1/period if period else float('nan') # hz = 1/period if period else float('nan')
# if hz > 60: # if hz > 60:
# log.info(f'FSP quote too fast: {hz}') # log.info(f'FSP quote too fast: {hz}')
# last = time.time() # last = time.time()
finally:
tracker.complete.set()
@tractor.context @tractor.context
@ -217,7 +220,7 @@ async def cascade(
profiler(f'{func_name}: feed up') profiler(f'{func_name}: feed up')
assert src.token == feed.shm.token assert src.token == feed.shm.token
last_len = new_len = len(src.array) # last_len = new_len = len(src.array)
async with ( async with (
ctx.open_stream() as stream, ctx.open_stream() as stream,
@ -249,9 +252,16 @@ async def cascade(
await ctx.started(index) await ctx.started(index)
profiler(f'{func_name}: fsp up') profiler(f'{func_name}: fsp up')
async def resync(tracker: TaskTracker) -> tuple[TaskTracker, int]:
# TODO: adopt an incremental update engine/approach
# where possible here eventually!
log.warning(f're-syncing fsp {func_name} to source')
tracker.cs.cancel()
await tracker.complete.wait()
return await n.start(fsp_target)
# Increment the underlying shared memory buffer on every # Increment the underlying shared memory buffer on every
# "increment" msg received from the underlying data feed. # "increment" msg received from the underlying data feed.
async with feed.index_stream() as stream: async with feed.index_stream() as stream:
profiler(f'{func_name}: sample stream up') profiler(f'{func_name}: sample stream up')
@ -263,23 +273,44 @@ async def cascade(
# array has been updated such that we compute # array has been updated such that we compute
# new history from the (prepended) source. # new history from the (prepended) source.
diff = src.index - dst.index diff = src.index - dst.index
new_len = len(src.array)
# XXX: ok no idea why this works but "drunk fix" # new_len = len(src.array)
# says it don't matter.
async def poll_and_sync_to_step(tracker):
diff = src.index - dst.index
while True:
if diff in (0, 1):
break
tracker, index = await resync(tracker)
diff = src.index - dst.index
# log.info(
# '\n'.join((
# f'history index after sync: {index}',
# f'diff after sync: {diff}',
# ))
# )
return tracker, diff
# log.debug(f'diff {diff}')
if ( if (
new_len > last_len + 1 or # the source is likely backfilling and we must
abs(diff) > 1 # sync history calculations
): abs(len(src.array) - len(dst.array)) > 0 or
# TODO: adopt an incremental update engine/approach
# where possible here eventually!
log.warning(f're-syncing fsp {func_name} to source')
tracker.cs.cancel()
await tracker.complete.wait()
tracker, index = await n.start(fsp_target)
# skip adding a new bar since we should be fully aligned. # we aren't step synced to the source and may be
continue # leading/lagging by a step
diff > 1 or
diff < 0
):
tracker, diff = await poll_and_sync_to_step(tracker)
# skip adding a last bar since we should be
# source alinged
if diff == 0:
continue
# read out last shm row, copy and write new row # read out last shm row, copy and write new row
array = dst.array array = dst.array
@ -292,4 +323,3 @@ async def cascade(
last = array[-1:].copy() last = array[-1:].copy()
dst.push(last) dst.push(last)
last_len = new_len