You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
(index): continuation scan loops forever when the stored and stat mtimes round to different milliseconds #891
Found in the review of #890 (pre-existing on main), CONFIRMED by a local probe (Node 22, Windows).
What happens.scanContinuationFile (session-cache.js ~98-110) can loop forever on a transcript larger than one 1 MiB continuation chunk.
Why. Two rounding rules disagree on the millisecond:
scanCachedContinuation (session-cache.js ~180-181) stores index.mtime by rounding the BigInt mtimeNs.
scanContinuationIndex (session-continuations.js ~36-37) reuses the saved cursor only if index.mtime === stat.mtime.toISOString(). stat.mtime comes from the floating-point mtimeMs, whose precision step is about 244 ns at current dates.
When the sub-millisecond part sits just under .5 ms, the two land on different milliseconds. The cursor is then never reused. Each pass restarts from offset 0 with the same 1 MiB budget, bytes < size stays true, and the do…while never exits; it re-reads 1 MiB per setImmediate until the file changes.
Probe. Same fixture as the D2 test, mtime set to an exact tick with SetLastWriteTimeUtc:
mtimeNs …499900 (bigint rounding .000Z, stat.mtime.001Z): prepareContinuationRefresh still not done after 4 s, after 1926 opens of the file.
…499800: done after 8 opens.
Impact.
A finished session's transcript never changes, so the loop never ends.
In the writer worker (ADR 0004), cacheTail queues every later computation behind it, so the index stops updating.
Roughly 1 in 10⁴ multi-chunk files hit it, at random.
Fix. Compare stamps (mtimeNs, or the same BigInt-derived value) instead of ISO dates, or derive both values with the same rounding. Red first: a test with an mtime on the ns boundary that hangs before the fix and finishes after.
Activity
docs(index): do not call the D2 timeout a scheduling flake; point to #…
(changelog): describe both #891 symptoms
(index): stop the continuation scan looping on a millisecond rounding…