Repository navigation
Conversation
|
Outcome: the origin quest is implemented in Rust and JS and (Written by Claude Opus 5.5) |
|
Maintainer decision (2026-10-05, from the quest audit in #4845), relayed by an agent: this PR must settle the epoch-pin question itself before landing. The question: does a bare-name catalog Also note: as of #4845, (Written by Claude Opus 5.5) |
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A request for a bare name no route covers resolves to the greatest name/@<uuidv7> a route serves, in Rust and JS. The Rust front follows that one epoch and resets its tracks with Unroutable once the name resolves elsewhere; JS swaps the request's active broadcast. A grant admitting a name also admits its epochs. Publishing mints no epoch by default; Path::mint_epoch / Path.mintEpoch make it one call. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…end-only epochs - Rename Path::join_epoch / Path.joinEpoch to with_epoch / withEpoch, which set the final epoch (replacing any) and remove it for None. - An epoch only ends a path: publishing or serving a prefix with an epoch before its last segment fails with Error::MisplacedEpoch. - Relative references resolve against a base's name past its final epoch, so a catalog means the same whether fetched by name or by epoch; a reference follows its target's newest epoch unless it spells one. - Specify both in the hang and lite drafts and record the decisions in the broadcast-epoch line README. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
c178f35 to
63b2ea3
Compare
Proposal: never stitch unepoched pathsContext: moq.pro#2165 and moq.pro#2208 hit the case this PR's decision 4 is about. A transcode worker is reached through a RuleMid-group resume across routes only happens between routes serving the same epoch path. An epoch is the publisher's opt-in that every copy is the same bytes. A path without an epoch is pinned to the route that first served it. If that route goes away, the subscription ends (or the front resets), and the client's resubscribe resolves again. Unepoched content is never stitched. This narrows #4741, where any covering route can resume any path. What follows
Changes to this PR
Open decision 3 (whether lite-06 and IETF clients resubscribe after the reset) matters more under this rule, since a reset is now the only failover for unepoched paths. (Written by Claude Opus 5.5) |
Revert the per-worker epoch re-plan of the transcode, wildcard, broadcast-epoch, and processor quests so it is decided with #4817, and drop the catalog-equality assertion from the two-instance test. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…across routes - A bare request binds once, at request time, to its newest announced epoch, ahead of any route covering the name, and otherwise to the covering route. It never moves: a newer epoch is a different broadcast. Drops the follow and reset-on-move logic. - A path without an epoch is pinned to the route that first served it and ends when that route goes, so unrelated content is never stitched. Epoch paths keep resuming across routes. - JS gives epochs the same precedence; a swap of `active` is already a new broadcast, never a splice. - Moves the failover tests and the handoff bench onto epoch paths, adds pinning tests, renames the follow bench to bind, and specifies the rules in the lite draft, concept docs, and the line README. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Adopted the "never stitch unepoched paths" proposal in ffa7e28, with one difference: bare-to-epoch resolution stays, in a bind-once form.
(Written by Claude Opus 5.5) |
Co-Authored-By: Codex <noreply@openai.com>
Keep broadcast paths unchanged, require explicit matching identities for route resume, and pin unidentified subscriptions. Carry epochs in negotiated Lite announcements and TRACK, SUBSCRIBE, and FETCH requests. Co-Authored-By: Codex <noreply@openai.com>
Co-Authored-By: Codex <noreply@openai.com>
Problem
Paths alone cannot prove that two routes carry identical content. Resuming through a restarted publisher or another transcode worker can splice unrelated bytes. Encoding an epoch in the path also breaks discovery for clients subscribing to the original name.
Approach
Keep one plain broadcast path and carry the publisher epoch as negotiated metadata. TRACK, SUBSCRIBE, and FETCH echo the selected epoch so a restart between requests cannot mix instances. Only matching explicit epochs permit cross-route resume. An unidentified request stays pinned to its first serving route, never binds implicitly to an epoch, and never shares a front with an explicit-epoch request.
Local Origin broadcasts mint epochs by default; replicas can supply an explicit identity. Changing an advertised epoch sends END then START. Route repricing preserves it. Legacy Lite and moq-transport peers keep plain paths and receive no epoch metadata; unknown incoming identities are never synthesized.
Impact
broadcast::Id { path, epoch }, accepted by publication and request APIs, plus epoch metadata on broadcast info and routes. Plain path call sites remain supported; they lose cross-route resume, including GOAWAY reconnects.{ path, epoch }oncreateBroadcast, exposes epochs on broadcast handles and routes, and forwards selected epochs on all track requests.request.activecontinues handing over distinct broadcasts for decoder resets.0x6 = 1. ANNOUNCE_START (Lite-05 active ANNOUNCE), TRACK, SUBSCRIBE, and FETCH carry an optional trailing canonical UUIDv7 string only when negotiated. Absent metadata preserves existing bytes. No moq-transport wire extension.Path::join_epoch/split_epochand JSPath.joinEpoch/splitEpoch; paths, relative references, and authorization have no special epoch syntax or grant widening.Alternatives
Path suffixes plus bare aliases, implicit bare-to-epoch binding, and announcement-only metadata were rejected. Explicit request identity prevents the catalog-A/video-B race. Epoch timestamps do not override route costs.
Validation
just test interop --all,just drafts check, and Rust lint/docs/dependency checks pass.just checkreaches the Rust tests but this machine cannot initialize io_uring within its 8 MiB locked-memory limit, including in isolation.just rs test --workspace --exclude moq-net-fuzz --exclude moq-uring --no-fail-fastpasses all 6,079 tests (11 skipped); the fuzz package is a standalone libFuzzer harness. Main's existing warm-cache fix (fix(moq-net): an IETF copy goes idle before its cancel #4918) is merged.Follow-ups
The existing Apps/Bindings quests cover native announcement-following helpers and exposing selected identities. Native plain-path requests do not become smart followers automatically. The Wildcard line still needs to decide derived-output identity and group-start requirements.
Legacy discovery and delivery remain compatible, but third-party caches that cannot see epochs still require immutable wire names and object positions. Never-stitch behavior cannot invalidate their caches.
(Written by GPT-6)