Draft-20 backlog: documentation cleanup and relay refusal codes - #117
Merged
Merged
Conversation
…code and draft-20 STATUS.md: - drop the Limitations entry saying duplicate Objects are not compared (the relay compares them, as the Malformed tracks entry describes); - LOC property IDs are those draft-ietf-moq-loc-04 requests from IANA; PropAudioLevel is 0x0C, not 0x0A; - "Handles the application reads itself": `CheckPeerParams` checks parameter scope, not roles; name the handles with no broker, and note that a bare `NewRequestBroker` checks only what it is configured to; - "Inbound GOAWAY": a request-stream GOAWAY is checked (§10.4) and otherwise ignored, with no re-issue; - row 10.2.15 FILL_PARAMETERS is DONE (Range Filters are inherited, §5.1.3), and notes that SUBSCRIBER_PRIORITY inside it has no effect; row 10.2.21 points at the Group Order draft gap; - the package summary no longer lists relative/absolute Joining FETCH, removed in draft-20; - remove the fixed items from the Documentation backlog. pkg/moqt/session/namespace.go: NAMESPACE / NAMESPACE_DONE answer only a SUBSCRIBE_NAMESPACE (§10.17, §10.18), so they are not follow-ups on a PUBLISH_NAMESPACE stream. That stream carries the announcer's REQUEST_UPDATE and GOAWAY. A publication is withdrawn, or its acceptance revoked, by cancelling the request (§6.2, §3.3.3), not by a FIN (§3.3.2). The IncomingNamespacePublication doc now names the broker settings a reader needs (PeerMessages, UpdateScope, HandleUpdates). Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Comment-only: no behaviour or test changes. Each citation and quote was checked against the draft-ietf-moq-transport-20 text. - session/datagram.go: PADDING datagrams are §11.5.2, not §11.3. - message/subgroup.go: an unknown stream type also closes the session (§3.4); it is not ignorable GREASE. - message/datagram.go: drop the stale "Figure 24" ranges and a quote absent from -20, and restate the §11.3.1 invalid Type Flags list. - session/datastream_in.go: an omitted FETCH GROUP_ORDER means Ascending (§10.2.8); a fill fetch stream inherits the subscription's order (§10.2.15). - message/grease.go: quote §14 accurately, and drop a wrong §1.4.3 cite. - message/types.go: §10 names no error code for an unknown message type. - relay/handler_subscribe.go: a Next Object upstream (§5.1.2) cannot serve downstream ranges that start before Largest Object. - session/options.go: Setup Options are §1.4.3 Key-Value-Pairs, so delta encoding fixes their order (not §10.2). - relay/cache/cache.go: in-group Object ID order is §10.13, not §11.4.3. - relay/handler_fanout.go: §9.7 says nothing about draining; the reason is the cache (§9.1). - relay/handler_datagram.go: §5.1.4 does not define a datagram as Subgroup 0 (§2.2: it belongs to no Subgroup); mark it relay policy. - relay/handler_forward.go: "no PUBLISH_DONE after REQUEST_ERROR" is §5.1/§5.1.1, not §3.3.3. - relay/relaynet/relaynet.go: the ALPN comment referred to draft-19. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…se the documentation backlog The citation pass (9a2c992) made explicit that the relay filters a datagram as Subgroup 0 under SUBGROUP_FILTER: §2.2 says a Datagram Object belongs to no Subgroup, and §5.1.4 does not cover it. This records it among the Limitations' interpretations. The Documentation backlog is done. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
An upstream that answered the relay's SUBSCRIBE with GOING_AWAY, as an upstream relay draining does before its GOAWAY reaches this one, was passed on as INTERNAL_ERROR. The relay answers a draining publisher it knows about with GOING_AWAY itself, so the subscriber's answer depended on timing. upstreamRejection now passes GOING_AWAY through with its Retry Interval, alongside DOES_NOT_EXIST, TIMEOUT, EXCESSIVE_LOAD and UNSUPPORTED_EXTENSION. awaitsPublisher counts it as "no publisher yet", so a RENDEZVOUS_TIMEOUT hold continues (§10.2.6). TestSubscribe_UpstreamRejects_PropagatesRejection's GOING_AWAY row, which pinned the old mapping, now expects GOING_AWAY with the Retry Interval. TestRendezvous_UpstreamGoingAwayKeepsHold is new. Both fail before this change. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…es does not matter When every SUBSCRIBE candidate only said the track has no publisher yet, the last to answer set the refusal code. So a draining local publisher plus a remote DOES_NOT_EXIST gave DOES_NOT_EXIST, and the reverse gave GOING_AWAY. candidateErrRank now orders the candidates' errors, and the highest is kept whatever the order: 1. a Track Properties refusal (§2.5.1); 2. any other refusal, which ends a RENDEZVOUS_TIMEOUT hold; 3. then the most actionable "no publisher yet" answer: GOING_AWAY (retry, §10.6.2), then TIMEOUT, then DOES_NOT_EXIST. The ranking is the maintainer's choice. It carries over the earlier reading that GOING_AWAY outranks §10.2.6's DOES_NOT_EXIST for a publisher that is known but draining. A relay skipped for draining ranks through the same function. TestSubscribe_NoPublisherYetRanking covers each pair in both orders. The three orders where the higher-ranked answer comes first failed before this change. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…blished subscription (§10.15) The relay "treats [TRACK_STATUS] identically as if it had received a SUBSCRIBE" (§10.15), but without an Established subscription it answered without asking upstream. It sent an empty TRACK_STATUS_OK for any track under an advertised namespace, and an OK from a leftover entry whose publisher had left. SUBSCRIBE would go upstream in both cases, and might fail. §10.15 lets such a relay "forward TRACK_STATUS to one or more publishers"; the maintainer chose to. trackStatusUpstream asks every candidate SUBSCRIBE would try, concurrently: local publishers of a covering namespace, then Discovery relays, skipping draining ones (§10.4). The answers combine as the relay's SUBSCRIBE_OK would: - Track Properties: the entry's, else the first answer's (§9.6); - LARGEST_OBJECT: the largest of all answers and the entry's (§10.2.17). With no OK, the refusal is the one SUBSCRIBE would give (candidateErrRank, upstreamRejection), or DOES_NOT_EXIST with no candidate. Bounds, also the maintainer's choice: - a forwarding TRACK_STATUS counts against MaxSubscriptionsPerSession (§13.1); - the forwarding is bounded at 5s, and a candidate that times out counts as TIMEOUT (§13.6); - all of it ends on the requester's STOP_SENDING. Relay policy, as for SUBSCRIBE and stitch FETCH: the requester's own session is not asked while a TRACK_STATUS for the track to it is in flight (a loop, §6.2). The registry's in-flight counter is now keyed by request type (BeginRequest / RequestPending). TestTrackStatus_ReplyEmptyPropertiesForKnownNamespace pinned the old empty OK and is removed. TestRelay_TrackStatusRequestUpdateClosesSession's publisher now answers the forwarded request. New tests in track_status_forward_test.go, each red before the change, or under a mutant removing its behaviour: forwarding with and without INCLUDE_PROPERTIES, refusals passed on, a leftover entry, a Discovery remote, the loop guard, every candidate asked (the largest of two; one refusing), an unknown Mandatory Track Property, a draining candidate, a silent one timing out, the requester's cancel, and the subscription cap. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…, Retry Interval included Follow-ups to 33dd402 and 38f0a53. The maintainer decided the first three: - An upstream GOING_AWAY with Retry Interval 0 ("SHOULD NOT be retried", §10.6.2) gets the relay's own jittered ~1s. Relay policy: the 0 is taken to speak for the upstream's own draining hop. - preferCandidateErr replaces rank-only comparison, for SUBSCRIBE and forwarded TRACK_STATUS alike. Of equal rank, the answer allowing the soonest retry wins, and 0 only when every answer says so. Of equal rank and retry, a specific code beats INTERNAL_ERROR, then the lower code wins. The jittered interval compares at its top. - A candidate whose request failed at the transport, with no answer (a reset, a FIN, its session ending), counts as "no publisher yet", with DOES_NOT_EXIST, the code it is answered with. It no longer masks another candidate's GOING_AWAY or TIMEOUT, and a RENDEZVOUS_TIMEOUT hold goes on and asks it again on the next look, never twice in one. Not a request the relay could not open for want of stream credit: that publisher is there, so the hold ends as before (the answer there, DOES_NOT_EXIST with no retry, is on the STATUS.md backlog). - An unknown Mandatory Track Property outranks Track Properties that do not parse, so a subscriber gets §2.5.1's UNSUPPORTED_EXTENSION whatever the order. Tests in session_upstream_test.go, each red before the change or under a mutant removing its behaviour: UpstreamGoingAwayWithoutRetry, TiedRefusalsSoonestRetry, OtherRefusalTieIsOrderFree, TransportFailureIsNoPublisherYet, UnsupportedMandatoryPropertyOutranksMalformed, and TestRendezvous_NoStreamCreditEndsHold / _TransportFailureAskedAgain. 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.
This PR clears two items from the draft-20 backlog: documentation cleanup and relay refusal-code fixes. There is one commit per item. Each was reviewed by moqt-reviewer, and each code change has tests that were seen failing first, either before the fix or under a mutant that removes the behaviour.
Documentation
e22125dSTATUS.md and the namespace handle docs now match the code and draft-20:PropAudioLevelis 0x0C, not 0x0A.NamespacePublication/IncomingNamespacePublicationdocs: NAMESPACE / NAMESPACE_DONE answer only a SUBSCRIBE_NAMESPACE (§10.17, §10.18). A namespace is withdrawn by cancelling the request, not by a FIN (§6.2, §3.3.2). The docs now also name the broker settings a reader needs.9a2c992corrects 13 stale§citations in code comments, each checked against the draft text: padding, GREASE, datagram flags, fetch ordering, caching, draining, and relaynet ALPN. Three of the old review's suggested corrections were themselves wrong and were left as they were.d12096brecords one interpretation: a datagram is filtered as Subgroup 0 under SUBGROUP_FILTER (§2.2, §5.1.4).Relay
33dd402When an upstream answers a SUBSCRIBE with GOING_AWAY, the subscriber now gets GOING_AWAY with its Retry Interval, instead of INTERNAL_ERROR. It also counts as "no publisher yet" for RENDEZVOUS_TIMEOUT.38f0a53,dbaaa73A SUBSCRIBE's refusal no longer depends on the order candidates answer in:5e61d8aTRACK_STATUS is forwarded upstream when the track has no Established subscription (§10.15 MAY):MaxSubscriptionsPerSession(§13.1) and is bounded at 5s (§13.6).Decisions and interpretations
TestTrackStatus_ReplyEmptyPropertiesForKnownNamespacepinned that and is removed.TestSubscribe_UpstreamRejects_PropagatesRejection's GOING_AWAY row changes from INTERNAL_ERROR to GOING_AWAY.Known gaps (added to STATUS.md)
Verification
go test ./...andgolangci-lint runpass.go test -race ./pkg/relay/...passes.🤖 Generated with Claude Code