test(nests): bump runSpeakerToHangListen warmup to 600 ms

Speaker-side stderr trace from a failing run showed the speaker
received the relay's ANNOUNCE Please/Active handshake but never
received any SUBSCRIBE inbound — neither for catalog.json nor for
audio/data — for the entire 10 s catalog-read window. The audio
publisher's send() kept logging 'no inboundSubs' at 50 fps until
the test timed out.

Diagnosis: moq-relay 0.10.x has a per-broadcast announce →
subscribe-pump setup race. speaker.startBroadcasting() returns
as soon as session.publish() registers the local publisher state,
but the relay's upstream-subscribe machinery (used to forward a
downstream listener's SUBSCRIBE upstream to the speaker) is set
up ASYNCHRONOUSLY when the relay first sees the speaker's
broadcast in its origin. Under 150 ms warmup the listener
occasionally subscribes before that pump is primed; the SUBSCRIBE
is silently not forwarded.

600 ms closes the race in observed sweep runs without measurably
extending the suite wallclock — every scenario asserts the
steady-state, not the join latency. Late-join (which uses 2_000 ms
already) is unaffected. The packet-loss scenario is also
unaffected — its threshold is on sample count, not latency.

Tracked in 2026-05-07-late-join-catalog-flake-investigation.md
which lists this as a candidate mitigation.
This commit is contained in:
Claude
2026-05-07 12:50:24 +00:00
parent 8e51e1bab2
commit 00f6cba319
@@ -759,7 +759,21 @@ private class HangListenOutput(
*/
private suspend fun runSpeakerToHangListen(
speakerSeconds: Int,
listenerLateJoinDelayMs: Long = 150L,
// Default warmup before listener spawns. Bumped from 150 ms to
// 600 ms because moq-relay 0.10.x has a per-broadcast announce →
// subscribe-pump setup race: speaker.startBroadcasting() returns
// as soon as `session.publish()` registers the local publisher
// state, but the relay's upstream-subscribe machinery (used to
// forward listener SUBSCRIBE → speaker) is set up asynchronously
// when the relay first sees the speaker's broadcast in its origin.
// Under 150 ms the listener occasionally subscribes before the
// relay's per-broadcast state is primed; the SUBSCRIBE is silently
// not forwarded to the speaker, the catalog read times out, and
// hang-listen exits non-zero. 600 ms closes the race in observed
// sweep runs without measurably extending suite wallclock — the
// typical scenario asserts the steady-state, not the join latency.
// See `2026-05-07-late-join-catalog-flake-investigation.md`.
listenerLateJoinDelayMs: Long = 600L,
muteWindowMs: ClosedRange<Long>? = null,
captureFirstFrame: Boolean,
/**