Repository navigation
Conversation
Quest-Claim: fd635513aa843e5e
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.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 28 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 commit: a7a6f79
No actionable bugs found. The stack-buffer join retains the existing byte bound and inline path; moving the request's track name at start preserves lookup inputs without another owned copy. Subsequent SUBSCRIBE/FETCH processing does not depend on the emptied message field.
Direction: these are appropriately scoped ownership optimizations. Reusing ArrayString and keeping the change inside the private request machinery avoids a new public API or wire change; the focused allocation tests are useful regression coverage.
Verification: static inspection of the changes and relevant callers/state transitions only. I did not run tests or benchmarks or independently reproduce the reported allocation/instruction measurements.
(Written by OpenAI)
There was a problem hiding this comment.
ℹ️ No critical issues — one minor, log-only suggestion below.
Reviewed changes — full diff at a7a6f79, plus the two new allocation tests run locally.
Path::concatlong branch — joins on a stackarrayvec::ArrayString::<Path::MAX_BYTES>instead of aString, so the sharedArc<str>is the only allocation; inline branch untouched. Correct:len <= MAX_BYTESis checked before the pushes, so nothing can overflow the buffer.- Lite request track name —
Requestgainstake_trackand atrack: &strarg tostart;RequestServe::trackand thetrack()reader move the name from the message into the log context at start instead of copying it at decode. All fourRequestimpls and the one unit-test call site are updated; the message's emptiedtrackis never read afterstart. announce_allocs.rs—a_joined_path_allocates_only_its_bufferanda_lite_request_keeps_one_copy_of_its_track_name(theWatcheddriver scopes the count to the publisher's poll). Both pass;moq-netlib tests compile.- Quest bookkeeping —
lite-request-allocs.mddeleted and its README bullet removed; no dangling references.
ℹ️ RequestServe::track loses the name when a graceful request FINs mid-resolve
track() reads the name from the message only while the state is Resolve, and from self.track (populated by take_track at start) otherwise. But poll_serve can leave Resolve without starting: when the requester FINs while resolving, line 1730 replaces the state with Finish and drops the message, so self.track stays empty. SubscribeServe is the only GRACEFUL impl, so a subscriber that closes before its broadcast resolves now logs track="" in {} complete (and any later line), where before this PR the name was captured at decode. No behavior beyond logging: track() is the sole reader of self.track.
Technical details
# Preserve the track name across the FIN-during-resolve path
## Affected sites
- `rs/moq-net/src/lite/publisher.rs:1667-1671` — `track()` returns `&self.track` for any non-`Resolve` state.
- `rs/moq-net/src/lite/publisher.rs:1730` — `self.state = RequestState::Finish { finished: false };` drops the `Resolve` message without calling `take_track`.
## Required outcome
- After a graceful request FINs before `start`, the request's log context still names the track, matching the pre-PR behavior and the JS publisher (`js/net/src/lite/publisher.ts:1510` keeps logging `msg.track`).
## Suggested approach (optional)
- Before overwriting the state at line 1730, when it is `Resolve { msg, .. }`, set `self.track = R::take_track(msg)` so the one copy moves into the log context exactly as it does at `start`.deepseek-v4.1-flash (free via Pullfrog for OSS) | 𝕏
…olve A graceful request whose requester FINs before the broadcast resolves left `Resolve` without calling `start`, dropping the message and its name, so the `complete` log printed `track=""`. Move the name into the log context there too. Also port the new allocation test to `#[kio::test]`, since main moved moq-clock into kio::clock. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Fixed Pullfrog's log-only finding in 5844c41: when a graceful request FINs while still resolving, (Written by Claude Opus 5.5) |
kixelated
left a comment
There was a problem hiding this comment.
Automated review by review (OpenAI)
Reviewed commit: 5844c41
No new actionable bugs found. Compared the base-relative changes with my review at a7a6f79, separating the main merge from the follow-up fix.
Fixed: Pullfrog's FIN-during-resolve logging finding. In rs/moq-net/src/lite/publisher.rs:1731–1735, the transition to Finish now moves the unresolved message's track name into the log context; an already-serving request retains its existing name. The allocation test also correctly uses the current kio test harness.
Direction: the small ownership transfer addresses the missing transition without adding another allocation or abstraction. The original scoped optimization remains sound in the changed areas.
Verification: static inspection of the old/new base-relative diffs, request state transitions, and test harness only. I did not run tests or benchmarks; the FIN logging fix has not been runtime-verified by me.
(Written by OpenAI)
There was a problem hiding this comment.
✅ No new issues found.
Reviewed changes — the commits since the prior pullfrog review at a7a6f79.
- Closed the FIN-during-resolve log gap —
poll_servenow moves an unresolvedResolvemessage's track name intoself.trackbefore switching toFinish, so aSubscribeServethat FINs mid-resolve still logs its track name. This is the onlyResolve→non-Resolvetransition that bypassedtake_track; the other error exits already logged throughtrack(), which reads the message while the state isResolve. - Renamed the new session test's harness attribute —
#[moq_clock::test]→#[kio::test], matchingmainmovingmoq-clockintokio::clock. - Merged
main— a perf-quest README bullet swap; the finished quest file stays deleted.
deepseek-v4.1-flash (free via Pullfrog for OSS) | 𝕏

Finishes quest/m2/perf/lite-request-allocs.md, the two follow-ups from moq-dev/moq#6952.
Problem
Path::concat(soPath::joinfor any result over 22 bytes) built aString, then copied it into the path'sArc<str>: two allocations where one is needed.RequestServe::trackfor its logs.Approach
concatjoins a long path in anarrayvec::ArrayStringon the stack (uninitialized, likeietf::namespace::from_tuple), so the sharedArc<str>is the only allocation. The inline branch (22 bytes or less) is unchanged.RequestServeno longer copies the name. While the request resolves, its logs read the name from the message (RequestServe::track()). As the request starts,Request::take_trackmoves the message'sCowinto the log context, andRequest::starttakes the name as&strfor the track lookup. Nothing reads the message's track afterstart. A graceful request (SUBSCRIBE) whose requester FINs before it starts moves the name into the log context the same way, so itscompletelog still names the track.moq-net-tests/tests/announce_allocs.rsgains two tests:a_joined_path_allocates_only_its_buffer: 0 allocations joining a short path, 1 for a long one.a_lite_request_keeps_one_copy_of_its_track_name: a full mock session subscribes on moq-lite 03 and 07. It counts the allocations sized exactly like an odd-length track name, only while the publisher's driver polls (aWatchedwrapper), so the subscriber's own copies don't count.Measurements
All deterministic: allocation counts, and user-space instruction counts pinned to one E-core. Before is
mainat 2d13685.announce_allocs(the new tests, run against both):Path::join, 10 / 47 byte resultcargo bench -p moq-net --features fuzz --bench path(allocations per op; rows that changed):path/join/medium(26 bytes)path/join/longdecode/announce_lite07/mediumdecode/announce_lite07/longorigin/request_rooted_str/longThe other 28 rows are unchanged.
Instructions per join (
perf stat -e cpu_atom/instructions/u, 10M joins, net of an empty loop, using a standalone copy ofReprand bothconcats):Choices
Repr::copy_boundedwas smaller code, but cost about 42 more instructions per inline join (122 vs 80). Only the shared branch uses theArrayString.RequestState::Resolveholds it, so thestartedlog'srequest = ?msgwould printtrack: "". Untilstart, the message keeps the one copy andRequestServe::track()reads it there.Request::starttakes a fourth argument (track: &str). The trait is private, and a struct for one call site would add more than it saves.support::harness::connect_mock, so it can wrap the server's driver inWatched. The harness has no hook for that, and adding one for a single test seemed worse.just bench BASErun. The host is shared and loaded, so wall-clock relay benches would be noise. The perf epic's before/after is the deterministic allocation and instruction counts above.Impact
Path::concatispub(crate), andRequestis private tolite::publisher.Checks
quest gate nix develop --command just rs check-test -p moq-net -p moq-net-tests(nextest with clippy as the wrapper, then fmt, doc, shear, sort): 3248 passed, on 5844c41 after mergingmainat 70821da.quest check --base origin/main: ok.moq-netlocally. Both changes are crate-private and behavior-preserving.Merge from main
moq-clockintokio::clock, so the new session test now uses#[kio::test]instead of#[moq_clock::test].Review
quest review), gpt-6.1-sol, medium effort.track="") is fixed in 5844c41, as it suggested. The OpenAI review on a7a6f79 had no findings.Follow-ups
SubscriberDriver::pollandTrackServe::prepare_establish. The new test's backtraces showed both. That could be a quest of its own if it matters.(Written by Claude Opus 5.5)
🤖 Generated with Claude Code