refactor(moq-net): unify stats counters on Gauge/Usage, drop the guard zoo#1876
Merged
Conversation
…he guard zoo
The lifecycle counters were six loose atomics bumped by six near-identical RAII
guards, each re-deriving the subtle "load closed (Acquire) before open (Relaxed)"
snapshot ordering. Replace that with one `Gauge { open, closed }` primitive (the
single place that ordering now lives) and one generic `Guard` RAII token.
`Counters` is now three `Arc<Gauge>` (announced/subscriptions/broadcasts) plus the
shared `Arc<Usage>` payload counters; `SessionCounters` is just a `Gauge`.
Collapse the publisher/subscriber guard pairs into side-parameterized
`BroadcastGuard` (announced) and `TrackGuard` (subscriptions + a `Meter` over the
payload counters), each delegating its close to the embedded `Guard` instead of a
hand-written `Drop`. Six `Drop` impls and four guard types become two.
Finish the payload migration: the lite-publisher fetch path now bumps the shared
`Usage` through a `Meter` (fetch reads random-access frames the model doesn't
auto-meter), so `TrackGuard` carries no payload methods at all. Every payload
count now flows through `Usage`/`Meter`; the guards are pure lifecycle.
No behaviour change: same counters, same emitted wire format. The two
source-level ordering tests collapse into one that pins `Gauge::snapshot`.
moq-net 390 lib + moq-native 62 e2e pass; clippy clean.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
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.
Stacked on #1873 (base
stats-in-model; retarget todevonce that merges).Follow-up cleanup to the stats aggregator, applying the "just counters" shape from #1873 to the half it didn't touch. No behaviour change — same counters, same emitted
.statswire format.1. One
Gaugeprimitive for every lifecycle counterThe lifecycle counters were six loose
AtomicU64s, and every guard'sDropre-derived the subtle "loadclosed(Acquire) beforeopen(Relaxed)" snapshot ordering by hand. Now there's oneGauge { open, closed }withopen()(RAII) /snapshot(), and the ordering lives in exactly one place (Gauge::snapshot).Countersbecomes threeArc<Gauge>(announced/subscriptions/broadcasts) plus the sharedArc<Usage>from #1873;SessionCountersis just aGauge.2. Collapse the guard zoo
One generic
GuardRAII token does the close-on-drop. The publisher/subscriber guard pairs collapse into side-parameterized types:PublisherStats+SubscriberStats→BroadcastGuard(announced)PublisherTrack+SubscriberTrack→TrackGuard(subscriptions + aMeterover the payload counters)Each delegates its close to the embedded
Guard— six hand-writtenDropimpls and four guard types become two. (SessionStatsand the refcountingSessionBroadcasts/BroadcastSubscriptionkeep their roles but now bump aGauge.)3. Finish the payload migration
TrackGuardno longer carriesframe()/bytes()/group()— the only remaining caller was the lite-publisher fetch path, which now bumps the sharedUsagethrough aMeter(fetch reads random-access frames the model doesn't auto-meter). So every payload count flows throughUsage/Meter, and the guards are pure lifecycle.Net
stats.rs is ~120 lines shorter; the tricky memory ordering is centralized and pinned by one source-level test (the two old ordering tests merge into one).
Testing
moq-net390 lib +moq-native62 e2e pass (lite 01–03 + IETF 14–18, fetch, compression); clippy clean on changed files. (moq-relay/workspace still blocked locally by the pre-existingiroh-relay requires rustc 1.91.)🤖 Generated with Claude Code