Repository navigation
fix(moq-net): the over-limit PUBLISH refusal invites a retry - #8084
Conversation
Quest-Claim: a9d75b2ff282646b
EXCESSIVE_LOAD may pass once the peer unlists a track, so the refusal carries RETRY_INITIAL through the shared retry_interval rule instead of 0. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
No actionable comments were generated in the recent review. WalkthroughThe retry interval policy now assigns the initial interval to every Merge Risk:
|
kixelated
left a comment
There was a problem hiding this comment.
Automated review by review (OpenAI)
Reviewed head daaa13009c0ddf047c2d57ca9f6345076f894f7a. No actionable correctness findings. The overload refusal now uses the shared 1-second retry interval; the other Offer::Refuse codes retain zero. The new test checks the decoded interval across drafts 18, 20, and 22.
Direction: proceed through normal CI/maintainer review. Verification: GitHub-only static review of the changed paths, error mapping, request encoding, and test harness; I did not run tests or interop checks. The current Check workflow is still in progress.
There was a problem hiding this comment.
ℹ️ No critical issues — one question about where the invited retry lands.
Reviewed changes
- Over-limit refusals invite a retry.
request::retry_intervalnow treatsEXCESSIVE_LOADas a may-pass refusal whatever the error, returningRETRY_INITIAL(1000 ms), andServePublishderives the refusal's interval from the wire code (from_code) instead of hard-coding 0. The otherServePublishrefusals (duplicate, listing cancelled, not supported, malformed properties) still resolve to 0. - Coverage. New
an_over_limit_publish_invites_a_retrydecodes the refusal on drafts 18, 20, and 22; the existing rule test still passes. - Quest finished. Deletes
quest/m1/retry-interval-overload.mdand itsm1Requiredline, with no leftover references.
I verified the draft-18 §10.6.2 wording (non-zero Retry Interval = retryable, and EXCESSIVE_LOAD SHOULD carry it), ran ietf::subscriber (257 tests) and ietf::error (16) plus the new test with --features async, and confirmed js/net has no counterpart to update (it refuses every PUBLISH and has no excessive_load condition).
deepseek-v4.1-flash-1017 (free via Pullfrog for OSS) | 𝕏
| retry_interval: 0, | ||
| // The rule judges the refusal as the peer reads it. | ||
| retry_interval: request::retry_interval( | ||
| &request::from_code(code, request::Kind::Publish, self.version), |
There was a problem hiding this comment.
The invited retry does not reach a listener: this same arm still calls listings.fail(&key.0, err) (tracks.rs:490), which cancels the covering listing, so a retried PUBLISH for the namespace falls into the "listing cancelled" arm at tracks.rs:464 and is answered UNINTERESTED with interval 0. I measured it with a one-slot announces cap: the first offer gets EXCESSIVE_LOAD/1000 and the retry UNINTERESTED/0. Since the refused track is never inserted into entries, dropping that fail would let the retry land once a slot frees, and would stop one transient load refusal from dropping every other track under the namespace and aborting its readers.
Technical details
# The over-limit refusal cancels the listing it just asked the peer to retry on
## Affected sites
- `rs/moq-net/src/ietf/subscriber/tracks.rs:490` — `listings.fail(&key.0, err)` runs on the over-limit arm (`Error::TooManyRequests` from `announces.acquire()`).
- `rs/moq-net/src/ietf/subscriber/tracks.rs:464` — `Offer::Refuse(UNINTERESTED, "listing cancelled")` answers any offer under a request whose `live` is `None`, which `fail` just set.
- `rs/moq-net/src/ietf/subscriber/tracks.rs:528` — the interval the peer is now told to come back after.
## Observed
With `subscriber.announces = Slots::new(1)`, a listing on `bcast`, one accepted track: the second `PUBLISH` is refused `0x9`/1000; retrying that same `PUBLISH` is refused `0x20`/0 because `Listings::fail` cancelled the request and `covering` now returns `None`.
## Required outcome
A retried over-limit `PUBLISH` should reach the listing that is still standing, so it is either accepted once a slot frees or refused `EXCESSIVE_LOAD` again with the interval. Not failing the listing also stops the over-limit arm from dropping the other tracks the listing holds (via `release()`) and aborting its readers.
## Suggested approach
Drop the `listings.fail` call from the over-limit arm (`Err(_) => ...`) and keep only the `Offer::Refuse`. The property and listing-cancelled arms keep `fail` because the peer sends nothing more for those.|
quest land watch: the merge queue removed this pull request at daaa130 because it conflicts with The land fixer works on it in the background, and the watcher re-enqueues it at the back of the queue once it is fixed or judged flaky, or hands it back here with what it needs. (written by quest land watch) |
|
Your OpenRouter API key was rejected. Issue a new key with the provider, then update the copy Pullfrog uses, in Pullfrog or in this repo's GitHub Actions secrets. The provider's responsePullfrog provider settings → · GitHub Actions secrets →
|
|
No code change was needed: the failed suite was Pullfrog's own agent run, not the PR's CI.
No commit was pushed because there was nothing to fix. Task list (5/5 completed)
|

Finishes
quest/m1/retry-interval-overload.md.Summary
The moq-transport refusal of a PUBLISH over the listed-track limit (
EXCESSIVE_LOAD, "too many listed tracks") now carries the may-pass retry interval (RETRY_INITIAL, 1 s) instead of 0, as draft-18 section 10.6.2 says it SHOULD.request::retry_interval(the rule from moq-dev/moq#7993) treatsEXCESSIVE_LOADas a refusal that may pass, whatever the error.ServePublish's refusals ask that rule with the error as the peer reads the code (from_code), instead of hard-coding 0. The other refusals there (duplicate, UNINTERESTED, unsupported) still read 0.an_over_limit_publish_invites_a_retrydecodes the refusal on draft-18, -20 and -22.Choices made without asking
from_code) soOffer::Refusestays unchanged, which keeps the diff intracks.rssmall next to the parallelretry-interval-forwardwork.Notes
model::track::test::pool_debt_sheds_a_flight_without_its_cached_groupfailed once in a fullcargo test -p moq-netrun and passed on rerun; it sits in an untouched module.Review
mechanical fix by quest land watch:
merged main at f85fa6ed16a9b08cf1f66141294561a3ec9abbf9 with the quest merge driver(head 6aebc64)Codex, gpt-6.1-sol, medium effort, round 1 on head
daaa13009c0ddf047c2d57ca9f6345076f894f7a: no findings.🤖 Generated with Claude Code
(Written by Claude Opus 5.5)