Relay: a duplicate that differs from the cached copy makes the track malformed (§9.1) - #105
Merged
Merged
Conversation
…rack malformed (§9.1) §9.1: "An endpoint that receives a duplicate Object with a different Forwarding Preference, Subgroup ID, Priority or Payload MUST treat the track as Malformed" (also §2.4.2 items 6 and 7). The relay dropped a copy that lost the dedup claim without looking at it. It now compares the copy with the first one in the cache, on the subgroup and datagram paths, and ends the track (PUBLISH_DONE MALFORMED_TRACK) on a difference in those fields or in Immutable Properties (§12.7, byte for byte; one copy having them and the other not counts). Mutable Properties may differ (§9.1). Payloads are compared only when both copies are Normal: Normal may become End of Group or Track (§9.1), and the reverse is a late Object (§2.1). Decisions made with the user; the limitation is documented: a copy is not compared once the first one left the cache. New: message.ImmutableProperties (zero-alloc). runFanout sets terminalSeen once, which is equivalent and keeps it under gocyclo. Tests whose "duplicates" differed in Payload or Subgroup are corrected: §9.1 now makes them malformed. TestRelay_DuplicateConsistency's seven malformed cases were verified red with the check disabled; its guards fail when all Properties, or Payloads regardless of Status, are compared. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
… copies are Normal Review follow-up. Only a Normal Object has a Payload or Properties (§11.2.1.1, §11.2.1.2), but Immutable Properties were compared whatever the Status, so a legal duplicate ended the track: a Normal copy with Immutable Properties becoming End of Group (§9.1), or the reverse, a late Object (§2.1). Forwarding Preference, Subgroup ID and Priority are still compared across a Status change. Also documents that a copy an announced gap says does not exist is still compared with a cached first copy: §2.1 excuses its arrival, not a different content. Both new guard cases of TestRelay_DuplicateConsistency were verified red before the fix. Co-Authored-By: Claude Opus 5.5 (1M context) <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.
Summary
§9.1: "An endpoint that receives a duplicate Object with a different Forwarding Preference, Subgroup ID, Priority or Payload MUST treat the track as Malformed" (also §2.4.2 items 6 and 7). Until now, when a second publisher's copy of an Object lost the dedup claim (§9.3), the relay dropped it without comparing it to anything.
The relay now compares that copy with the first copy in its cache, on both the subgroup and datagram paths. It ends the track (PUBLISH_DONE MALFORMED_TRACK, §2.4.2) when the copies differ in:
Not treated as malformed:
Decisions (made with you)
Interpretation
A copy that an announced gap says doesn't exist is still compared against a cached first copy. §2.1 excuses its late arrival, not different content.
API
message.ImmutableProperties(raw) ([]byte, bool), which returns the Immutable Properties value exactly as serialized, without allocating.Test changes
TestFanout_UpdatesTrackEntryLargestObjectno longer re-sends Object {4, 1} with different content.runFanoutsetsterminalSeenonce instead of in two branches. It behaves the same and keeps the function under the gocyclo limit.Tests
TestRelay_DuplicateConsistencywere verified red with the check disabled. They include a subgroup copy duplicated by a datagram, and two datagrams.TestImmutableProperties, including a zero-allocation check.-raceandmake bench-quickall pass, with no allocs/op increase.Not in this PR
The rest of the §2.4.2 list is still undetected:
🤖 Generated with Claude Code