Repository navigation
fix(relay): deliver tracks whose group sequences do not start at 1 - #515
Merged
Merged
Conversation
The group ring stored a group at its arrival count but looked it up by its sequence, so a group was found only when the two were equal. A track whose first group reached the relay with another sequence, or whose sequences had a gap, was never delivered. The funnel publishes such tracks: it answers a subscription with the latest record under that record's sequence. The ring is now addressed by arrival order, with its own type; a group keeps the sequence its publisher gave it. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RJgd6G5k5aezW5cs8JCY5g
A relay-chain test sends sequences that start past 1 and have gaps through two relays. The ring test covers out-of-order arrival and releases the references it takes. The funnel tests share their relay setup. The fell-behind log names its values as ring positions. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RJgd6G5k5aezW5cs8JCY5g
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.
Found through foalk-inc/foalk#608.
The bug
The relay never delivered a track whose groups were not numbered 1, 2, 3, … as they reached it. The subscription got no answer and no group.
groupRingstores a group at its arrival count (pos.Add(1) % size) andhead()returns that count. The egress loop walks 1 …head()and callsgetwith each.gettook that number as a sequence and requiredcache.seq == seq, so a group was found only when its sequence equalled its arrival count.That check came with 2b1fc9a (pooled caches, 2026-06-15) as a guard against reading a slot the ring had reused. Until then
getreturned whatever the slot held and any sequence worked. The guard needed the slot's position to compare against; the cache had no such field, and the argument was already named and typed as a sequence.Publishers that break the assumption:
seqis 3. Every track with more than one record was unreachable through the relay. The existing integration test records once before subscribing, the one case where the two numbers agree.The fix
The ring is addressed by arrival order alone.
groupCachegainspos, set inreserve, andgetcheckscache.pos == pos, which keeps the reuse guard.get,headandearliestAvailableuse aringPositiontype so a sequence cannot be passed where a position is meant. A group still leaves the relay under the sequence its publisher gave it (OpenGroupAt(cache.seq)), unchanged.Groups that arrive out of sequence order leave in the order they arrived, and a new subscriber starts at the group that arrived last. That is how the ring behaved before 2b1fc9a; the type's comment now says so.
The fell-behind debug log names its values
requested_position,earliest_positionandlatest_position, since they are ring positions.Tests
TestGroupRing_Get_SequencesNotStartingAtOneOrDense: sequences starting past 1, with gaps, a single late one, wrapping the ring, and out of order.TestRelayChain_KeepsPublisherSequences(integration): through two relays, a subscriber receives sequences that start past 1, have gaps, or both.TestFunnel_RelaySubscriberJoinsAfterSeveralRecords(integration): three records, then a subscriber through the relay receives group 3, then group 4. It timed out before the fix. The setup it shares withTestFunnel_PublishesThroughTheRelayis nowstartFunnelBehindRelayandsubscribeChatAsViewer.go test ./internal/relay/,go test -tags=integration ./internal/integration/, the new relay-chain test andgolangci-lint run ./...pass locally.Not in this change
The relay does not forward dropped-group reports, so a subscriber of a track with gaps learns of the track's end late. That is #516.
🤖 Generated with Claude Code
https://claude.ai/code/session_01RJgd6G5k5aezW5cs8JCY5g