Skip to content

fix(net): a flight asks upstream with its rider's priority - #8818

Open
kixelated wants to merge 3 commits into
mainfrom
quest/m1/flight-priority
Open

kixelated wants to merge 3 commits into
mainfrom
quest/m1/flight-priority

Conversation

@kixelated

@kixelated kixelated commented Nov 15, 2026 •

Copy link
Copy Markdown
Collaborator

Finishes quest/m1/flight-priority.md: a flight's upstream fill now asks with its rider's priority and budget, so a late joiner's replay isn't ranked below all live traffic on a congested upstream link.

Changes

  • group::Expiry, the per-reader policy a handed-out group already carries, gains asking(), which returns what that reader asks fills with:
    • GroupExpiry (a subscriber's group) reads the subscription's priority, delay.max, and order.
    • FetchExpiry (a fetched group) now keeps the fetch's priority next to its max_delay.
  • group::Consumer::asking() returns its expiry's asking. A group with no expiry, such as a raw consume(), falls back to priority 0 and no budget, which was the old behavior.
  • track::board asks for the flight with the reader's asking. Order stays Ascending, as in a one-group fetch fill, since a flight holds one group.
  • A rider that boarded a flight already asked under a tighter budget no longer fails with that budget's Old. It flies again with its own budget, the same retry Fetching::poll_answer makes. The budget comparison is now a shared looser() helper.
  • fill::Asking is widened to pub(in crate::model) and re-exported from track.
  • Deletes the quest file.

Choices made unattended

  • I read the asking from the group's Expiry, not from a new field on group::Consumer. The expiry already carries the subscriber's Subscription or the fetch's budget, and the consumer has a size assert. A front's logical reader gets its preferences through the copy track's subscription, which the front mirrors.
  • The flight records the asking when it is boarded. A preference update that lands during the short wait before upstream accepts doesn't reach that join. Later updates don't need to either: once the flight is accepted, the rider reads a copy rather than a fill. Plumbing Join::update through Boarding::poll would cost a lock on the subscription on every poll during boarding.

Validation

  • New test a_flight_asks_with_its_riders_priority (in rs/moq-net/src/model/track.rs) uses the public track API. A subscriber with priority 5, delay.max 10s, and descending order sees its flight fill with priority 5, max_delay 10s, and ascending order. A fetch with priority -3 sees priority -3 and its budget.
  • New test a_looser_rider_asks_again_after_old: a 1s rider and a 10s rider share a flight, and the request is rejected with Old under 1s. The tight rider fails. The loose rider asks a new flight at 10s and reads it.
  • Mutation check: with the retry disabled, the new test fails.
  • Mutation check: putting the hardcoded priority: 0, max_delay: None back makes the test fail (left: 0, right: 5).
  • cargo test -p moq-net --features async --lib flight: all 15 flight tests pass, and so does the new retry test. just check passed (check rs, test rs, and the rest).

Public API / Wire

Public API: none. Everything is crate-private. Wire: none, though a relay's upstream flight SUBSCRIBE/FETCH now carries the rider's priority and budget, not 0 and none.

Caused by

  • moq-dev/moq#7944: added track::board with a hardcoded priority: 0, max_delay: None (found by reviewer: the feature review quest)

Follow-ups

None.

Models

Size: XS
Implementer: Claude Code, claude-opus-5-5, unknown effort (arm B)

🤖 Generated with Claude Code

(Written by Opus 5.5)

Review

Rewritten by quest review after each round.

  • Head: af63265

  • Base: origin/main at 250a13a

  • Risk: high, Bounded upstream FETCH requests change wire behavior relied on by downstream readers and relays; incorrect budget handling can interrupt delivery, though reverting restores prior behavior.

  • Classified: medium by default

  • Reviewer: Codex, gpt-6.1-sol, medium effort

  • Session: 01a1df38-f214-79a1-b7cd-1e3fc6c5dddc, round 2

  • Score: 10/10, The incremental change fixes the shared-flight budget refusal and adds a focused regression test, with no new issues found by code inspection.

  • Raised the risk to high: Bounded upstream FETCH requests change wire behavior relied on by downstream readers and relays; incorrect budget handling can interrupt delivery, though reverting restores prior behavior.

  • Rounds: 2; first round 1 (medium 1); findings 1 (medium 1): fixed 1, refuted 0, open 0

  • Findings: none

  • The last round's findings, at 9073568:

    • Fixed: medium, rs/moq-net/src/model/track.rs:3864: Recover shared flights rejected under another rider's budget; Boarding retains the rider's asking and fills handle, retries Old refusals recorded under a tighter budget, and the new regression test covers a tolerant rider recovering through a second flight.

kixelated and others added 2 commits November 15, 2026 04:26
track::board hardcoded priority 0 and no budget for a flight's fill, so a late
joiner's replay ranked below all live traffic upstream. The group's expiry, the
subscriber's or fetch's per-reader policy, now reports what the reader asks fills
with, and board asks with it (oldest first, since a flight holds one group).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@kixelated kixelated changed the title A flight asks upstream with its riders' priority fix(net): a flight asks upstream with its rider's priority Nov 15, 2026
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@kixelated
kixelated marked this pull request as ready for review November 15, 2026 12:56
@coderabbitai

coderabbitai Bot commented Nov 15, 2026

Copy link
Copy Markdown
Contributor

Warning

Review limit reached

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

Next included review available in 30 minutes.

Check out review usage here.

View limit details

Limit details: You’ve used all 4 included reviews currently available.

Learn how review limits work.

Review configuration:

Run configuration

  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: Organization UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 57aab666-72d7-41b3-92e2-a140ce9496ff
Commits

Reviewing files that changed from the base of the PR and between fabfe5e and af63265.

Files selected for processing: 4

  • quest/m1/flight-priority.md
  • rs/moq-net/src/model/group.rs
  • rs/moq-net/src/model/track.rs
  • rs/moq-net/src/model/track/fill.rs
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

Share

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ No new issues found.

Reviewed changes

I reviewed how a flight's upstream fill now carries its rider's priority and budget, and the new path that lets a rider retry after an Old refusal.

  • Rider's asking on flights: track::board builds the flight's fill::Asking from reader.asking() instead of hardcoding priority: 0, max_delay: None. It still forces Order::Ascending because a flight holds one group.
  • Expiry::asking: GroupExpiry reads the live subscription. FetchExpiry now stores the fetch's priority and passes it through for_track. A consumer with no expiry falls back to the old defaults.
  • Retry for a looser rider: Boarding now keeps fills and asking. If the flight it boarded was refused Old under a tighter budget, it asks again with its own budget, the same way Fetching::poll_answer does. That budget comparison now lives in a shared looser() helper.
  • Retry terminates: fly skips any pending flight whose outcome already resolved the key, so a retry always joins or creates a flight that hasn't answered yet. The recursion goes at most one level deep, and each later retry needs a new refusal under a tighter budget.
  • No JS counterpart needed: js/net has no flight or board mechanism.

Pullfrog  | View workflow run | Using claude-opus-5-5 | 𝕏

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant