Repository navigation
feature(Stream): Replay missed bars on reconnect, add --since and --replay - #31
Merged
Merged
Conversation
…eplay Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011HGNUuQYbp3ZUdqW8UY5Kf
almostintuitive
marked this pull request as ready for review
November 12, 2026 12:51
szemyd
added a commit
that referenced
this pull request
Nov 13, 2026
…and retry refused follow-ups (#33) This PR is stacked on #31 and merges into its branch. It fixes review findings checked against the server in dream-faster/unravel-router#1149 and dream-faster/unravel-router#1199. ## What changes - **A drop during a catch-up resumes where the replay got to.** The live rows held during a replay arrive before `replayed`, so `lastBar` runs ahead of a replay that is still catching up. A reconnect used to resume from it and skip the rest of the gap. `replayFrom` now tracks each unfinished replay's bar, advanced by each replay frame's `time`, and a reconnect resumes from there first. - **An empty truncated replay** (`to` null) is asked for again from `from`. If it comes back empty again from the same bar, that bar is larger than the server's cap. Stderr then says so instead of "more to come", and the stream stops asking. `StreamReplay.FollowedUp` tells the CLI whether a follow-up was sent. - **A refused follow-up is sent again.** A follow-up refused with `limit_exceeded` is sent again after a jittered pause, up to `streamBusyRetries` times, then the stream warns. Running out of the 50 follow-ups also warns now, instead of stopping without a word. - **Docs:** the `streamMessageLimit` comment is updated (replayed bars now come in small frames), and so is the README's replay paragraph. ## Tests `go test -run 'TestStream_' ./...` passes. New tests: - an empty truncated replay is asked for again from `from`, then given up with a message; - a drop during a catch-up resumes from where the replay got to; - a refused follow-up is sent again, with no warning. `go vet` and `gofmt` are clean. The full `go test ./...` has the same 8 failures as this PR's base branch: they are the `*_live_test.go` suites, which need `APERIODIC_API_KEY` and network access. https://claude.ai/code/session_01MoDcuxddwYnzAPetT7cR5r --- _Generated by [Claude Code](https://claude.ai/code/session_01MoDcuxddwYnzAPetT7cR5r)_ Co-authored-by: Claude <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The live feed now keeps recent bars and replays them to a subscribe that carries
since(dream-faster/unravel-router#1111). This uses that inaperiodic stream, so a reconnect no longer leaves a gap.What changes
--replay=falseturns it off). A reconnect asks for each channel's bars since the newest one received. If none was received, it asks from one bar before the previous subscribe. Replayed rows print first, marked"replay":true, then the live rows.--sincereplays from a time of your choosing on the first connect: an RFC 3339 time or how long ago (30m). It needs a 1m or longer interval, the only ones the server keeps.limit_exceededwhile many clients replay at once. The CLI sends it again after a 1 to 2 s random pause, and after 5 tries subscribes without the replay.replayis left out when false.--countstill counts only live rows.since. Production answersreplayedwithunavailable: trueuntil replay is turned on there.Tests
go test -run 'TestStream_' ./...passes, with seven new tests:--sincereplays before the live rows, including a 2 MiB frame;--replay=falsesends nosince;--sinceis refused below 1m or when unparseable;sinceis sent at 15s.The
*_live_test.gosuites needAPERIODIC_API_KEYand were not run here.Generated by Claude Code