Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 13 additions & 6 deletions doc/bin/relay/cluster.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,19 @@ relayed from what the peer just withdrew, rather than falling back to them one
by one. During reconnect, another session from that peer can still advertise
the broadcast; an old session's withdrawal does not invalidate that route.

A relay two hops from the publisher's still holds routes relayed through others.
So a change of a broadcast's best route waits 300 ms before it is announced,
while a new broadcast and a removed one go out at once. By then the withdrawal
has usually removed the other stale routes too, and the relay sends one
retraction instead of advertising each stale path in turn. Requests still
follow the current best route immediately; only the announcement waits.
A relay two hops away hears only that its neighbor withdrew, and may still hold
paths relayed from the same announcement through neighbors the withdrawal has
not reached yet. So when the route a relay advertised to its cluster peers is
withdrawn and another takes over, the relay withdraws the broadcast from its
peers at once and advertises the replacement one second later, if the
replacement still stands; anything it hears for that broadcast in the meantime
waits too. A stale path is withdrawn within that second and never spreads, so an
ended broadcast is retracted once per link instead of hunting through the mesh.
New broadcasts, retractions, and a better route while the advertised one still
stands go out at once. The cost is a genuine failover: a peer left with no other path sees the broadcast return
about a second after a link fails. Requests and subscriptions follow the
current best route immediately; only the announcement waits. Clients are never
held down.

Failover routes must carry copies of the same broadcast. For each track, the
relay requires matching timescale, retention window, publisher priority, and
Expand Down
1 change: 0 additions & 1 deletion quest/m0/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,6 @@ Published API or wire breaks still land on dev; each quest's Plan says so.
- [quest check everywhere](/quest/m0/quest-check-everywhere.md) - `quest check` guards `main`, `dev`, and the line branches on push and PR, not only PRs into `main`
- [noq reassembly cap](/quest/m0/noq-reassembly-cap.md) - noq carries quinn's stream reassembly cap and the connection receive window is finite by default
- [qmux reset race](/quest/m0/qmux-reset-race.md) - qmux handles RESET_STREAM under one lock instead of panicking
- [Path hunting](/quest/m0/path-hunting.md) - a withdrawn path is retracted about once per relay instead of hunting stale alternatives, with a hold-down on route updates and no wire change
- [Shared fronts](/quest/m0/shared-fronts.md) - viewer sessions share a front, so fronts scale with peers, not viewers
- [Frame alloc budget](/quest/m0/frame-alloc-budget.md) - frame buffers pre-allocate within a per-session budget and otherwise grow with bytes received
- [Handshake deadline](/quest/m0/handshake-deadline.md) - an unfinished handshake or slow HTTP header times out
Expand Down
49 changes: 0 additions & 49 deletions quest/m0/path-hunting.md

This file was deleted.

6 changes: 3 additions & 3 deletions quest/m1/cluster-routing/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,9 @@ link-state and existence-split design planned earlier that day:
path vector with hop lists stays loop-free, path hunting is confined to the
cores, liveness flooding (the simulator's dominant link-state cost) is never
paid, and failure detection sets the outage window either way. The parked
implementation is #4631. If stale paths remain on the tiered layout, the
fix is [Path hunting](/quest/m0/path-hunting.md), promoted to m0: a hold-down
on route updates, with no wire change.
implementation is #4631. Stale paths on any layout are held down: a relay
advertises a withdrawn route's replacement to its peers only after 1 s,
with no wire change.
- The line lands on `main`: its children are additive. The two breaking
changes left it for `dev` on their own:
[Remove `--hop`](/quest/m1/hop-removal.md) and
Expand Down
1 change: 0 additions & 1 deletion rs/moq-net/src/driver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,6 @@ impl<S: crate::transport::poll::Session> Driver<S> {
/// Panics if `now` is earlier than the previous poll or construction time.
pub fn poll(&mut self, now: Instant, waiter: &kio::Waiter) -> Result<Option<Instant>, Error> {
self.clock.advance(now);
self.clock.register_driver(waiter);
match self.state.poll(waiter) {
Poll::Ready(Ok(())) => Err(Error::Closed),
Poll::Ready(Err(err)) => Err(err),
Expand Down
14 changes: 2 additions & 12 deletions rs/moq-net/src/ietf/publisher.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5147,12 +5147,7 @@ mod tests {
async fn a_repricing_is_a_request_update() {
const VERSION: Version = Version::Draft19;

// Forward the update at once: the hold is not what this checks.
let origin = crate::origin::Config {
update_hold: Duration::ZERO,
..crate::origin::Config::new(crate::Hop::new(1).unwrap())
}
.produce();
let origin = crate::origin::Config::new(crate::Hop::new(1).unwrap()).produce();
let _cold = origin
.announce("cam", crate::origin::Route::default().with_cost(4))
.unwrap();
Expand Down Expand Up @@ -5219,12 +5214,7 @@ mod tests {
async fn a_publisher_change_is_a_request_update() {
const VERSION: Version = Version::Draft19;

// Forward the update at once: the hold is not what this checks.
let origin = crate::origin::Config {
update_hold: Duration::ZERO,
..crate::origin::Config::new(crate::Hop::new(1).unwrap())
}
.produce();
let origin = crate::origin::Config::new(crate::Hop::new(1).unwrap()).produce();
let publisher_a = crate::Hops::try_from(vec![crate::Hop::new(7).unwrap()]).unwrap();
let publisher_b = crate::Hops::try_from(vec![crate::Hop::new(8).unwrap()]).unwrap();
let _from_a = origin
Expand Down
Loading
Loading