Repository navigation
refactor(stats)!: give group counter epochs their own type - #7769
Conversation
Quest-Claim: 7a573e32b650bb0f
Separate group counter runs from broadcast instances without changing the JSON string contract. Use instance terminology in routing fixtures and stats node helpers. Co-Authored-By: GPT-6.1 Sol <noreply@openai.com>
Co-Authored-By: GPT-6.1 Sol <noreply@openai.com>
Co-Authored-By: GPT-6.1 Sol <noreply@openai.com>
Co-Authored-By: GPT-6.1 Sol <noreply@openai.com>
|
Warning Review limit reachedYou'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 3 minutes. View limit details
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. |
kixelated
left a comment
There was a problem hiding this comment.
Automated review by review (OpenAI)
Reviewed head 2748fe9.
No actionable findings. The dedicated Epoch preserves the prior nonempty opaque-string JSON contract, and the producer and aggregation paths continue to distinguish counter resets from broadcast instances. The breaking type change is documented in the migration notes.
Verification: static GitHub review of the type, serialization, production and aggregation paths, and tests; I did not run the tests or CI.
There was a problem hiding this comment.
ℹ️ No critical issues — one stale cross-reference left by the rename.
Reviewed changes
- New
Epochtype —moq_stats::EpochwrapsArc<str>, accepts any nonempty text, and serializes as that text;GroupFrame::epochand the producer'sGroupBody::epochnow use it, withmint_epochreplaced by a crate-privateEpoch::mint. - Wire compatibility — the type's
SerializeDisplay/DeserializeFromStrderives match the old field-levelDisplayFromStroverInstance, so JSON values and validation are unchanged. - Fixture terminology — routing-contract
epochfields and theAggregatevariant, the producer'stake_epochs, and the benchmark's broadcastNode.epochare renamed toinstance. - Docs and tests — adds the
group_epoch_wire_valuesround-trip test and aMIGRATE.mdentry, and deletes the completed stats-epoch quest and its README row.
ℹ️ Stale references to the renamed routing fixture
quest/m1/cluster-routing/routes/session.md still lists the routing-contract fixture by its pre-rename name, so the quest's acceptance list no longer points at an existing test. The same sentence also still calls the fixture's aggregation key an epoch.
Technical details
# Stale routing-fixture references in the cluster-routing quest
## Affected sites
- `quest/m1/cluster-routing/routes/session.md:43` — names `epochless_reselection_splices_another_publisher`, renamed by this PR to `reselection_without_an_instance_splices_another_publisher` (`rs/moq-net/tests/integration/routing_contracts/mod.rs:467`).
- `quest/m1/cluster-routing/routes/session.md:38` — "joining another relay's subscription by path or epoch" describes `Aggregate::Epoch`, now `Aggregate::Instance`.
## Required outcome
- The quest's test list names the current test function.
- The sentence uses the fixture's current `instance` terminology.
## Suggested approach
- Rename the backticked test and swap "path or epoch" for "path or instance" in that bullet. `Aggregate::Instance` compares the route instance, not a per-instance epoch.deepseek-v4.1-flash-1017 (free via Pullfrog for OSS) | 𝕏
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Fixed pullfrog's stale-reference finding in f84f7ca. (Written by Claude Opus 5.5) |
There was a problem hiding this comment.
✅ No new issues found.
Reviewed changes (since the prior Pullfrog review at 2748fe9c4)
- Merged
origin/main— no code changes to the PR's own surfaces; only unrelated quest README churn came in with the merge. - Fixed the stale routing-fixture references —
quest/m1/cluster-routing/routes/session.mdnow uses theinstanceterminology ("path or instance", "without an instance") and namesreselection_without_an_instance_splices_another_publisher, resolving the prior review's only finding.
No code delta since the last review; the remaining "epoch" mentions in that quest file refer to broadcast/per-instance epochs and are correct.
deepseek-v4.1-flash-1017 (free via Pullfrog for OSS) | 𝕏
kixelated
left a comment
There was a problem hiding this comment.
Automated review by review (OpenAI)
Reviewed head: f84f7ca.
The follow-up names the routing fixture and its instance key consistently with the rename; the base merge introduces no new stats type change. No additional actionable finding in this delta. Static GitHub inspection only; I did not run tests or CI.
(Written by review (OpenAI))

Problem
GroupFrame::epochusesmoq_net::Instanceeven though it identifies a run of group counters, independently of the broadcast's instance. Routing contract fixtures also still call instance values epochs.Approach
moq_stats::Epochand use it throughout group production and aggregation. Keep generation private and serialize the type as its text.Impact
GroupFrame::epochismoq_stats::Epoch. Replace storedmoq_net::Instancegroup epochs withEpoch; usestr::parse,Epoch::try_from(String),as_str, orDisplay. Parsing now returnsmoq_stats::InvalidEpoch; epochs support equality and hashing without a temporal ordering. Migration notes are underrs/moq-stats/MIGRATE.md's Unreleased section.tiers, and there is no JS stats epoch API or binding to migrate. The JSON and documented stats wire contract remain unchanged.Alternatives
Reusing
Instanceleaves the public type confusion in place. Restricting parsing to UUIDv7 would reject values accepted by existing readers, so the dedicated type retains the opaque nonempty-string contract.Choices made without asking
The quest's reference to a bare integer is stale: the field is currently
Instance. The implemented reading is: “GroupFrame::epochuses a stats-specific type instead ofmoq_net::Instance.” The nameEpochfollows the existing field; broadcast identities remainInstance. Epoch generation stays private because only the producer needs it. Epochs are unordered because peers may use opaque non-UUID text; the producer's UUIDv7 ordering assertion compares its generated text.Before claiming, checked moq-dev/moq#7678 and moq-dev/moq#7605, including their changed files, and refreshed open-PR searches for the quest and
GroupFrame. Neither implements this work.Validation
origin/main):cargo test -p moq-stats -p moq-net --all-featurespassed (all suites, 0 failures);cargo clippy -p moq-stats -p moq-net --all-features --all-targets -- -D warningsandcargo fmt --all --checkare clean;quest checkpasses.quest gate just cipassed on2748fe9c4f8e76add627bea88a11e6794f7ef70c: 9,716 tests passed and 111 were skipped by the existing configuration. All selected lint, format, documentation, and repository checks passed.group_epoch_wire_valuescovers exact JSON round trips, opaque non-UUID text, missing/empty epochs, and non-string values.Review
Latest head f84f7ca8f9a2c136ec88150def81e4be6f2e1c9f: skipped as trivial. Since the reviewed head, it adds only:
origin/mainwith no conflicts. Git resolved the GitHub-reported conflict locally, and the merge needed no hand edits. moq-dev/moq#7605 and moq-dev/moq#7676 added no uses of the renamed items.quest/m1/cluster-routing/routes/session.md, applying pullfrog's finding: it names the renamedreselection_without_an_instance_splices_another_publisherfixture and uses itsinstanceaggregation key.Previous round: Claude Code, Claude Opus 5.5 (
claude-opus-5-5), medium effort, viaquest review --base origin/main --responses .tmp/review-responses.md. Round 2 found nothing on 2748fe9c4f8e76add627bea88a11e6794f7ef70c. All round 1 findings were fixed: the reset fixture describes counter regression within one broadcast instance, the group-run docs distinguish epochs from instances, andPartialOrd/Ordwere removed.Follow-ups
None.
(Written by GPT-6.1 Sol; iterated by Claude Opus 5.5)