Skip to content

fix(stream): start EARLIEST on an empty log at its first row - #100

Merged
nhobin219 merged 1 commit into
mainfrom
earliest-on-empty
Oct 4, 2026
Merged

nhobin219 merged 1 commit into
mainfrom
earliest-on-empty

Conversation

@nhobin219

Copy link
Copy Markdown
Owner

Fixes the CI failure on main (run 37230675435): test_keyed_table_examples timed out with "offset 3 not applied in 10s (at None)".

Cause. EARLIEST on a log that held nothing was refused with empty, and the examples fell back to subscribing from now. A row committed between the refusal and the second subscribe was in neither, so the view never saw it.

Fix. EARLIEST on an empty log starts at the log's first row, and that holds for an evicted log that has run dry too. _resolve reads the frontier before its awaits, so a row committed while it resolves is at or above the frontier, and the replay to the frontier at attach (I2) carries it. The examples' fallback is removed. Live._connect keeps its fallback for an older broker, which still refuses with empty.

  • test_EARLIEST_on_a_log_that_holds_nothing_starts_at_its_first_row
  • test_a_row_committed_while_EARLIEST_resolves_is_not_lost holds earliest open while 3 rows commit. Both tests fail against the old refusal, and the race test also fails against a live-only start.
  • Two refusal tests that used EARLIEST on an empty log to provoke a refusal now use an offset ahead of the log.
  • The refusal docs are updated: four why values in README, SPEC and API, plus a CHANGELOG entry under Unreleased.

🤖 Generated with Claude Code

https://claude.ai/code/session_01FsSDkeb5rVAxA1FSmKKfQi

The server refused EARLIEST on a log holding nothing as empty, and a
client that then subscribed "from now", as the refusal advised, missed
any row committed between the refusal and the second subscribe: in
neither the replay nor the live queue. The keyed-table example failed
intermittently in CI on exactly this, and Stream.live had the same race
at open.

EARLIEST with nothing to replay now starts at the frontier read before
the subscriber joins: an empty replay, or one carrying whatever committed
in between. Clients keep understanding empty from an older server, with
a message that names the race; the examples drop their fallback.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FsSDkeb5rVAxA1FSmKKfQi
@nhobin219
nhobin219 merged commit b19c19e into main Oct 4, 2026
6 checks passed
@nhobin219 nhobin219 mentioned this pull request Oct 4, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant