Repository navigation
feat(json)!: roll snapshot and window groups on joiner demand - #6054
Conversation
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…efresh Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…n joiner demand in JS Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…s, and migrations Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
# Conflicts: # rs/moq-mux/MIGRATE.md
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Checks run locally on db915ce:
This is a draft until the open decisions in the description are settled. (Written by Claude Opus 5.5) |
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info
WalkthroughThe change replaces numeric snapshot-delta and window-operation ratios with boolean Priority: ➖ Normal Merge Risk: ⚪ Minimal · up to
|
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
Keep both Unreleased MIGRATE.md entries (JSON deltas and #5929 ranges) in dart, go, kt, py, swift, moq-c and moq-ffi. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 9582c85f65
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Without the ratio rollover, 41 updates never left the first group. Run past MAX_DELTA_FRAMES plus a restatement, assert three keyframes, and decode each group with a cold joiner so an encoder that keeps its DEFLATE window across a boundary fails. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Ports the data consumer timestamp tests from #5677 onto the deltas flag. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 407a7177f9
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
An update or edit may carry a timestamp older than its group's first frame, but a new group may not start before that frame. A refresh restated at the last update's timestamp, so it could rewind and be refused with TimestampMismatch, and JS swallowed the error after publishing an empty newest group. Refreshes now restate at the newest timestamp written, in Rust and JS, and a failed JS refresh aborts the track instead of stranding latest-value subscribers. @moq/net's Timestamp gains isBefore, the exact cross-scale ordering the track already used for group starts. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Merging.
Unrelated to this PR: (Written by Claude Opus 5.5) |
The merged #5677 test assigned compression after Config::default(), which clippy denies once the ratio argument is gone. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
# Conflicts: # quest/m1/refresh/README.md
|
Merging.
(Written by Claude Opus 5.5) |
# Conflicts: # dart/moq/MIGRATE.md # go/wrapper/MIGRATE.md # kt/moq/MIGRATE.md # py/moq-rs/MIGRATE.md # rs/moq-c/MIGRATE.md # rs/moq-ffi/MIGRATE.md # swift/MIGRATE.md
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Re-merging after the queue removed
(Written by Claude Opus 5.5) |
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Re-merging after the queue removed
Re-enabling auto-merge on (Written by Claude Opus 5.5) |
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A rejected update left its value as the encoder baseline, so a joiner's refresh restated a value that never reached the wire: an oversized one failed again (aborting the JS track, ending Rust refresh loops), and an untimed one on a timed track got published anyway. The next mutate or modify also carried the rejected edit into every later owner's publish. The snapshot encoder now stages each frame's value and applies it on commit, as the window encoder already does, so value() and snapshot() always reflect the last value that reached the wire. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
#6274 made window consumers return each event's frame timestamp, so the refresh test reads .value and checks the restated header's timestamp. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Merged Accepted behavior change from 5465196: a snapshot Checks: clippy @codex review (Written by Claude Opus 5.5) |
|
Codex Review: Didn't find any major issues. Another round soon, please! Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Merged main (31e220a). Only the (Written by Claude Opus 5.5) |
#6054 landed and deleted quest/m1/refresh/json.md. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Completes quest
quest/m1/refresh/json.md.Snapshot and window groups no longer roll on a byte budget. A group runs until a joiner wants a fresh one, judged by the track's
refreshratio (Demand::wantedpassing the largest group), and the producer then restates the value or window in a new group at the timestamp of the last committed update. The frame and byte caps stay. This work does not depend on the relay PR moq-dev/moq#6030: a local join already moveswanted.Changes
snapshot::Config::delta_ratioandwindow::ProducerConfig::op_ratiobecomedeltas: boolandops: bool(defaulttrue). NewEncoder::snapshot()for both modes. Producers gainrefresh().awaitandpoll_refresh(waiter), which the owner drives because the producer has no runtime. The demand watch is a privatecrate::refresh::Refresh.deltaRatioandopRatiobecomedeltasandops.Encoder.snapshot()is added for both modes. Producers watchtrack.demand().wantedthemselves and stop onfinish().json::Config::with_deltas, plusjson::Snapshot::refreshandpoll_refresh. The catalog producer usesdeltas = false. The timeline track carriesrefresh(8)and answers a refresh before each edit.MoqJsonSnapshotConfig.deltas. Each snapshot producer runs a refresh task (viaffi::spawn) until finish or drop. Bindings gain no refresh API.moq_json_snapshot_config.deltas. With deltas on, the track getsrefresh = 8and a refresh task that stops when the entry is removed.Deltas *bool), kt and dart (regenerated) follow, along with MIGRATE.md entries and the moq-json and@moq/jsondoc pages.encoder.reset().ops: false.deltas: false.Tests
Encoder::snapshot(), timestamp reuse, and a compressed refresh window.json_snapshot_refreshes_for_a_joiner, where an idle bound producer re-emits once a joiner crosses the ratio. It fails without the driver task.Public API / wire impact
@moq/json, moq-mux, moq-ffi, moq-c and every binding. MIGRATE.md entries are added.@moq/net:Timestamp.isBefore, exact ordering across scales, which a refresh uses to restate at the newest timestamp written.refreshon a track also makes IETF advertisedynamic_groups.Decisions (confirmed)
The maintainer confirmed these five, taking the recommended course; the alternatives stay listed.
reset(), notEncoder::snapshot(). The stats tracks share a sequence allocator, so they cannot usesnapshot::Producer. A wanted group past the largest makes that tick's frame a snapshot, so a refresh costs one frame instead of a restatement plus a delta. Chosen:encoder.reset(). Alternative: restate withEncoder::snapshot()in a new group, then send the tick's delta.refreshfield only when a caller asks. Alternative: add arefreshfield tomoq_json_snapshot_confignow.Deltas *bool. A nil pointer means on, which keeps the existing pointer-default pattern. Chosen:*bool, so the name matches the other bindings. Alternative: a zero-valueDisableDeltas bool.Encoder::value,Encoder::snapshot()and the nextmodify/mutatestart from the last value actually written. Before, a rejected update stayed as the baseline: a refresh restated a value that never reached the wire, and the next edit carried the rejected change along. Accepted by the maintainer as a behavior change; the moq-json and@moq/jsonMIGRATE.md entries say to retry a refused edit yourself.This is a breaking API change across many packages, so it was held for the maintainer's confirmation.
Follow-ups
(Written by Claude Opus 5.5)
🤖 Generated with Claude Code