Repository navigation
streaming: let a new handle snapshot a stream that was recreated - #93
Merged
Merged
Conversation
A stream that is destroyed and later used again lives in a new generation, stored under a generation-scoped key such as "<key>:generation:2". A new, unbound Stream handle still carries the generation-1 key until its first operation binds it. Snapshot's script compared that key with the stream's current key even for an unbound handle, so every Snapshot of a recreated stream from a new handle returned ErrStreamDestroyed, and callers that read through fresh handles saw an empty stream while writes kept succeeding. The snapshot script now checks the generation and key only for a bound handle, exactly as the replay and publish scripts already do. A handle still bound to the destroyed generation is still rejected. The new test destroys a stream, creates it again, and reads it from a new handle.
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.
Problem
streaming.Stream.SnapshotreturnedErrStreamDestroyedfor any stream that had been destroyed and then created again, when the caller read through a new handle. Writes to that stream kept succeeding, so a caller saw a stream whose sequence numbers advanced while every snapshot came back empty.Where it showed up: Chorus deletes a channel's stream when the channel's last member expires. A channel used again afterwards lives in stream generation 2. Chorus reads each channel through a new handle, and treats
ErrStreamDestroyedas "nothing retained". So once the channel was recreated,read,watchand the dashboard all showed zero messages.Cause
A recreated stream stores its events under a generation-scoped key, such as
<key>:generation:2. A new handle is unbound: it has no generation yet and still carries the generation-1 key until its first operation binds it.Snapshot's Lua script compared the handle's key with the stream's current key even when the handle was unbound. The publish (
AddOnce) and replay scripts already check the generation and key only for a bound handle; the snapshot script was the one exception.Change
The snapshot script now uses the same condition as replay: it checks the generation and the physical key only when the handle is bound. A handle still bound to a destroyed generation is still rejected.
TestSnapshotReadsRecreatedStreamFromNewHandlecovers the case:ErrStreamDestroyed.Without the fix, step 2 fails with the exact error seen in production.
The full race suite and
go vetpass. The change has no wire, key or format change, so mixed versions are safe.