slice-4 (dev-a): MediaThread + session_map rewire (Task 6 + 7) #12
Reference in New Issue
Block a user
Delete Branch "slice-4-dev-a-reflex"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
What lands
MediaThread— dedicatedstd::thread::spawnreplacing the tokiospawn_poll_task. OwnsHashMap<ChannelId, RtcSession>exclusively; axum access viaMediaCmdcommand channel (AcceptOffer/Delete/Shutdown). The Connected spawn constructs (advisory_tx, advisory_rx) pair, clones Sender to spawn_tap_engine AND LocalVadReflex::new, hands Receiver to Reflex::new. Composition: LocalVadReflex<Reflex>. This retires the P2 hot-path drift from the 2026-07-03 adversarial review (ARCHITECTURE.md mandates dedicated timing threads, not the shared tokio pool).session_map.rsrewire to MediaCmd command-channel pattern (drops the old Arc<Mutex> axial access). Routes + main + lib updated to use the thread handle.Seam gate (§8.5 #6 invariant)
loop_driver.rs+rtc_session.rsbyte-identical to slice-3 — verified viagit diff 78435f7..HEAD -- crates/rutster-media/src/loop_driver.rs crates/rutster-media/src/rtc_session.rs(empty). The rewire is scoped to session_map.rs + media_thread.rs + binary-side wiring only.DCO
All commits signed off per AGENTS.md.
Merge
ARCHITECTURE.md mandate ("never the shared tokio pool") finally landed. One std::thread owns all RtcSessions exclusively; axum routes via command channel (Register/AcceptOffer/Delete/Shutdown). The Reflex<TapAudioPipe> wrapper is wired here on Connected via RtcSession::set_pipe. loop_driver + rtc_session untouched (seam holds). Signed-off-by: Aaron D. Lee <himself@adlee.work>Code review
Found 3 issues:
main.rs:52callsmedia_thread.shutdown()from inside#[tokio::main] async fn main, butshutdown()usesblocking_send/blocking_recv(media_thread.rs:118-121), which panic with "Cannot block the current thread from within a runtime" when called from an async context. Ctrl-C/SIGTERM will panic instead of exiting cleanly. The PR's ownapi_integration.rswraps the identical call intokio::task::spawn_blockingto avoid exactly this —main.rsneeds the same treatment.session_map::drain_function_callswas the only consumer ofTapConn.rx_function_call. The new tick loop drains onlyflush_rx, sofunction_callevents from the brain queue in the bounded mpsc until full, then drop —HangupToolis now unreachable dead code and the brain can no longer end a call (a shipped slice-3 feature). Not listed in the slice-4 spec §1.2 out-of-scope table;realtime_integration.rs:19-23frames it as a test-coverage gap, but it is a functional regression in the binary.Stringwith substring sniffing (AGENTS.md says "Cold path (signaling, setup, request handlers):thiserror-derived error enums,?propagation, converted to HTTP status codes at the axum boundary"):MediaCmdreply channels carryResult<_, String>,RtcSessionErroris stringified at the channel boundary, androutes.rs:121picks 404-vs-400 viae.contains("not found"). An SDP-reject message that happens to contain "not found" returns 404 instead of 400. Suggest a smallMediaCmdErrorenum (NotFound/Rtc(RtcSessionError)) on the reply channels.Observation below the confidence bar, for awareness:
MediaCmd::Deleterunsblock_on(timeout(750ms, join))inline in the command-drain step of the single media thread, so one hangup with a slow brain stalls polling for every other live session for up to 750ms. Invisible at 1-session scale; worth a note or a deferred-join pattern before slice-5 concurrency.🤖 Generated with Claude Code
- If this code review was useful, please react with 👍. Otherwise, react with 👎.