feat(moq-net): cost-based cache-aware routing (moq-lite-06 WIP) + route-cost I-D#2179
Draft
kixelated wants to merge 5 commits into
Draft
feat(moq-net): cost-based cache-aware routing (moq-lite-06 WIP) + route-cost I-D#2179kixelated wants to merge 5 commits into
kixelated wants to merge 5 commits into
Conversation
… routing
Replace hop count as the routing metric with an accumulated route cost.
The hop chain stays immutable per announcement (loop detection); cost is
the one dynamic routing input:
- ANNOUNCE_BROADCAST (lite-06) carries a cost: a publisher-set base
forwarded unchanged plus a per-link transit accumulated hop by hop.
Absent (older versions, plain publishes) it derives from the hop
count, so default routing orders exactly as before.
- A relay actively carrying a broadcast advertises zero transit
(marginal cost: its upstream path is already paid for), steering
peers onto already-hot routes instead of opening duplicate upstream
pulls.
- ANNOUNCE_UPDATE mutates a live announcement's cost in place, so a
hot/cold flip doesn't ride an Ended+Active pair (which aborts
in-flight subscriptions downstream). Increases hold down 30s and
decreases forward within a 1s tick (dynamic metrics must be coarse
and damped); receivers re-rank after a deterministic per-node jitter
so mutually-preferring peers don't swap simultaneously.
- Links are priced by the dialing side: a connect_api peer entry may be
{host, cost} (0 = free same-datacenter link), declared in SETUP so
the acceptor prices the link identically. Default cost 1 per link.
- Lite06Wip is negotiated via the moq-lite-06-wip ALPN but excluded
from the default version sets; endpoints opt in explicitly
(Versions::with_preferred) until lite-06 ships.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Post-merge fixups after pulling origin/dev: - dev replaced BroadcastState.tracks (HashMap) with the amortized-GC WeakCache; adapt Consumer::is_active to a new WeakCache::has_live() query (the old code iterated .values()). - Add drafts/draft-lcurley-moq-route-cost.md: the IETF I-D for the cost-based routing this branch implements, written as a moqt extension that composes with (and generalizes) draft-lcurley-moq-relay-hops -- base + transit cost, per-link costs in SETUP, the marginal-cost reset for actively-forwarded broadcasts, and in-place cost updates. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
There was a problem hiding this comment.
Sorry @kixelated, you have reached your weekly rate limit of 500000 diff characters.
Please try again later or upgrade to continue using Sourcery
Route cost is a strict generalization of relay-hops path selection (it replaces the hop count with an additive weight and defaults back to hop count when absent), and rides the same HOP_PATH machinery, so it belongs in one draft rather than a separate overlapping one. - Delete draft-lcurley-moq-route-cost.md. - Extend draft-lcurley-moq-relay-hops.md: RELAY_HOPS Setup Option now optionally carries a Link Cost; new Route Cost + ROUTE_COST Parameter sections (base + transit, marginal-cost reset, relay forwarding rule, cost updates + damping); Path Selection made cost-primary with hop count as the fallback; Security + IANA (ROUTE_COST 0x40B59) updated. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
API feedback: the Cost cell bolted onto an otherwise-immutable Info was arbitrary — the hop list is announcement metadata too, and the criterion for tearing anything down was never "which field changed" but "did the data source change". An announcement rides a session, so a route update never changes which peer the media comes from; teardown belongs to the data plane (producer dies -> resubscribe), not to metadata. - broadcast::Info now holds one shared, mutable Route (hops + base + transit) replacing the immutable hops field and the Cost cell. Route exposes hops()/contains()/base()/transit()/cost()/set()/set_cost(). - ANNOUNCE_UPDATE is gone from the wire: a repeat Active already carries hops + cost, and the receiver now applies it IN PLACE on the same broadcast — no producer replacement, no aborted subscriptions. The lite-06 wire delta shrinks to the two cost varints on Active. - subscriber: restart_announce (publish-new + retire-old, which tore down in-flight tracks one hop below every route change) is replaced by update_announce (Route::set + damped refresh). A repeat announce whose chain now loops through us retires the broadcast as before. - publisher: the cost tick generalizes to a route tick (lite-05+): it re-announces in place when hops, cost, or activity diverge from what the peer last saw, including lifting/imposing exclude_hop suppression that an in-place hop update can toggle. Hop changes and cost decreases forward promptly; pure cost increases keep the 30s hold-down. - origin restarts now happen ONLY where the active consumer actually swaps (that relay re-announces; downstream applies it in place), so a route change no longer cascades teardowns across the mesh. - e2e: the route-cost test now also proves swap continuity — a cheaper broadcast replaces the active one at the server and the client's in-flight subscription keeps receiving frames from the original producer while its broadcast handle shows the new hops, with no re-announce events. - I-D: Cost Updates becomes Route Updates — re-advertisement is the update mechanism, applied in place; updates MUST NOT interrupt existing subscriptions; the lightweight cost-only message is dropped. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
kixelated
marked this pull request as draft
July 18, 2026 12:20
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.
What
Replaces hop count as the cluster routing metric with an accumulated route cost, carried on announcements in a new (WIP, opt-in) moq-lite-06 version, specced as an extension of the relay-hops I-D (
drafts/draft-lcurley-moq-relay-hops.md).The core model: a broadcast's announcement metadata is one shared, mutable
Route(hop chain + cost). A repeat ANNOUNCE replaces it in place — same broadcast, same subscriptions, new route. Teardown belongs to the data plane (a producer dying), never to metadata: an announcement rides a session, so a route update can't change which peer the media comes from, only the advertised path/cost beyond it. Origin-level restarts happen only where the active consumer actually swaps; downstream they arrive as in-place updates, so route changes no longer cascade teardowns across the mesh.Why
Routing today is blind to what a link actually costs and to which candidate already carries the media. In a CDN deployment two relays in one datacenter each pull the same broadcast over a metered backbone (the via-sibling route is +1 hop, so shortest-hop routing never picks it), and cross-region ties break by hash rather than toward the peer already streaming it. The parallels are classic: OSPF-style per-link costs, a Babel-style damped dynamic metric, and marginal-cost advertisement for the cache signal.
How
broadcast::Info.route: Route— hops +base+transitin one kio cell shared by every clone.origin::Producer::refresh_broadcastre-ranks a path after a route mutation and restarts only if the winner changed.ANNOUNCE_BROADCASTgains two cost varints (baseforwarded unchanged,transitaccumulated per link). No new message: a repeat Active is the update, applied in place by the receiver. Old versions derive cost from the hop count, so ordering is bit-identical to the current(hops.len(), fnv)key.exclude_hopsuppression that an in-place hop update can toggle. Hop changes and cost decreases forward within a 1s tick; pure cost increases hold down 30s; receivers re-rank after a deterministic per-node jitter so mutually-preferring peers don't swap simultaneously.cluster.connect_apientries may be{host, cost}(0 = free same-DC link), declared in SETUP so both ends price the link identically.moq-lite-06-wipALPN, excluded fromVersions::all()/ALPNS; opt in viaVersions::with_preferred. Transport accept dispatch recognizes any parseable moq ALPN (is_moq_alpn).draft-lcurley-moq-relay-hops: optional Link Cost on the RELAY_HOPS setup option, Route Cost + ROUTE_COST parameter sections, and a Route Updates section — re-advertisement applied in place, MUST NOT interrupt existing subscriptions.Safety
exclude_hop) runs before ranking; a repeat announce whose chain now loops through the receiver retires the broadcast.Tests
Wire round-trips (cost on Active, version gating); model (cost-beats-hops, base cost, refresh promotes/demotes,
is_activelifecycle); real-QUIC e2e: base-cost propagation, link-cost addition, hot flip in place, and route-swap continuity — a cheaper broadcast replaces the active one at the server while the client's in-flight subscription keeps receiving frames from the original producer, its broadcast handle showing the new hops, with zero re-announce events. Full workspace suite green; clippy/fmt/doc clean; the I-D renders end-to-end.Public API (moq-net)
broadcast::Route(new),broadcast::Info { route, origin },Consumer::is_active,origin::Producer::refresh_broadcast,Client::with_link_cost,Setup.link_cost,Versions::with_preferred,is_moq_alpn,lite::RouteCost,Version::Lite06Wip. No separate Cost type, no ANNOUNCE_UPDATE message, nowith_cost_basebuilder.🤖 Generated with Claude Code