A running command is not re-stamped every tick

The "kept existing capture stream" branch wrote the running command back
with the current time on every tick, which made a running command the
newest forever: no request sent tonight could outrank the July start until
this was cut. The spawn transition keeps the command's stamp too. The
teardown map records the audio result: 860 frames and 2,756 audio packets
in 29 s, nothing expired, on a producer host at 93% CPU.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
Meta Vens 2026-09-11 01:33:05 +02:00
commit 3cea88417d
2 changed files with 52 additions and 9 deletions

View file

@ -1256,9 +1256,17 @@ fn start_capture_stream_command(
.find(|session| session.stream_id == command_stream_key)
{
if capture_stream_commands_start_equivalent(&session.command, &command) {
// The same running command comes through here every tick. Writing
// it back with a fresh stamp made a running command the newest
// forever, so no request could ever outrank it: a July start kept
// winning against every request sent tonight until this was cut.
if session.command_id == command.command_id && command.state == "running" {
return Ok(());
}
eprintln!(
"Muninn serve kept existing capture stream {} bitrate_kbps={} latency_budget_ms={}.",
"Muninn serve kept existing capture stream {} for command {} bitrate_kbps={} latency_budget_ms={}.",
command.stream_id,
command.command_id,
command_rudp_video_bitrate_kbps(&command),
command_rudp_latency_budget_ms(&command)
);
@ -1268,7 +1276,6 @@ fn start_capture_stream_command(
"Muninn serve kept existing activation child from command {}.",
session.command_id
),
updated_at: timestamp()?,
..command.clone()
};
node.put(&running.command_id, &running)?;
@ -1293,10 +1300,10 @@ fn start_capture_stream_command(
command_rudp_latency_budget_ms(&command)
);
let child = spawn_capture_stream_activation(options, &command)?;
// State changes; the stamp is the command's ordinal and stays.
let running = MuninnCaptureStreamCommandRecord {
state: "running".to_string(),
detail: "Muninn serve spawned the local activation child.".to_string(),
updated_at: timestamp()?,
..command.clone()
};
node.put(&running.command_id, &running)?;

View file

@ -558,12 +558,48 @@ had ever written, and a reaped command's rewritten stamp let a July command
supersede the request that had stopped it and respawn with a Focusrite that no
longer exists. Terminal commands no longer compete.
Open: **audio.** The loopback capture opens the requested endpoint (Realtek
and LG both selected cleanly) and then emits nothing; the producer never
queues an audio payload (`pending_audio=0` throughout). Sound played from an
SSH session does not reach the interactive session's endpoints, so the test
needs someone at Raven playing audio. Until then the audio leg is unproven,
not failed.
### Audio, same night (23:25Z)
The "emits nothing" above was the wrong endpoint: Raven's sound goes out
through `Realtek HD Audio 2nd output`, not `Speakers (Realtek(R) Audio)`.
Running the capture script by hand for three seconds against each endpoint
settled it (1.1 MB from the second output, zero from the other two). With the
right source the producer queued audio at once, and the video leg collapsed:
7 frames in 9 s, thousands of repair requests, twice the bytes on the wire.
Two causes, both fixed at their owners:
1. **CultNet readers stopped at acknowledgements** (CultLib `47b9fc4`). Both
RUDP socket readers returned `None` after consuming a packet that carried no
frame or event: an ACK, a ping, an incomplete fragment. The producer's mux
loop reads once per payload sent, so it consumed one incoming datagram per
outgoing one. Video-only sat exactly at that edge (the receiver was acking
every unreliable frame, uselessly); reliable audio's ACKs pushed it over,
every unacknowledged fragment was resent, and the resends starved the sends.
Readers now return `None` only when the socket is empty, and unreliable
frames are not acknowledged.
2. **The command engine resurrected dead commands** (`0b8d738`, `bc43e1b`, and
the one after). A translated request carried the consumer's RFC 3339 stamp, which sorts
below every `unix-` stamp; and superseding or reaping a command re-stamped
it with the current time, so a July start outranked the stop that ended it
and respawned with a Focusrite that no longer exists. Stamps are Muninn's
own and terminal transitions keep the command's stamp. The last of it: the
"kept existing capture stream" branch re-stamped the running command every
tick, so a running command was always the newest and no request could ever
outrank it; a running command is now left alone until something changes.
Also cut on the way: the 5 ms reliable resend delay (now 30 ms; a receiver
polling every 2 ms answers in 3-6 ms), and the activation child now runs
above normal priority so a game on the same host does not starve the mux loop
(`98b4f0b`).
| run (12,000 kbps, display 0 + Realtek 2nd output) | seconds | frames | audio packets | expired | wire overhead |
|---|---|---|---|---|---|
| before the reader fix | 9 | 7 | 121 | 89 | 50% |
| readers fixed | 19 | 564 | 1,801 | 0 | 3% |
| readers fixed, stamps fixed, final build `bc43e1b`+ | 29 | 860 | 2,756 | 0 | 3% |
Raven was at 93% CPU with a game running for every row.
## State at end of the 2026-09-09/10 pass