diagnostic: snapshot listener-side flow control too, not just speaker
The previous round of fc-* lines exclusively reported the speaker's QUIC
connection state. That hid the real story for the residual stream loss:
each Opus frame the relay forwards arrives as a fresh peer-initiated
uni stream on the LISTENER side, so the listener's peerInitiatedUni
counter and advertisedMaxStreamsUni evolution are what matter — the
speaker's view is stable at peerInitiatedUni=1 for the whole run
(only the WT control stream is relay-initiated on that side).
Changes:
- MoqLiteSession.transport changed from `private` to `internal val`
so test code can downcast.
- MoqLiteNestsListener exposes an `internal val transport` getter
that returns the underlying WebTransportSession via the session's
new internal accessor.
- SendTraceScenario.run takes a new optional
`listenerFlowControlSnapshots: List<suspend () -> QuicFlowControlSnapshot>`.
When supplied, it emits `fc-listener[idx]-pre / -post-pump /
-post-grace` lines in the same shape as the speaker side.
- Refactored the three checkpoint emit sites into a shared
`logFcSnapshot(scope, label, snap, includeRcvBuf)` helper so the
speaker and listener lines print identical column layouts.
- withProdSpeakerAndListeners + withHarnessSpeakerAndListeners cast
each listener to MoqLiteNestsListener (the only impl in the tree)
and downcast its WebTransportSession to QuicWebTransportSession,
yielding a per-listener snapshot supplier list to the scenario
block.
What the next sweep tells us: for each cliffed scenario, fc-listener[0]
should now show whether the listener is the bottleneck (e.g.
peerInitiatedUni stuck below the relay's intent, or udpDatagrams not
matching the relay's send count) or whether the relay just stopped
forwarding (peerInitiatedUni climbs but matches the partial received
count).
All :quic and :nestsClient JVM tests pass.
This commit is contained in:
+10
@@ -65,6 +65,16 @@ class MoqLiteNestsListener internal constructor(
|
||||
) : NestsListener {
|
||||
override val state: StateFlow<NestsListenerState> = mutableState.asStateFlow()
|
||||
|
||||
/**
|
||||
* `internal` accessor for diagnostics: a test downcasts the
|
||||
* returned [WebTransportSession] to a platform-specific type
|
||||
* (e.g. `QuicWebTransportSession`) to read flow-control counters
|
||||
* from the underlying QUIC connection. Not part of the public
|
||||
* [com.vitorpamplona.nestsclient.NestsListener] surface.
|
||||
*/
|
||||
internal val transport
|
||||
get() = session.transport
|
||||
|
||||
override suspend fun subscribeSpeaker(speakerPubkeyHex: String): SubscribeHandle = wrapSubscription(broadcast = speakerPubkeyHex, track = AUDIO_TRACK)
|
||||
|
||||
override suspend fun subscribeCatalog(speakerPubkeyHex: String): SubscribeHandle = wrapSubscription(broadcast = speakerPubkeyHex, track = CATALOG_TRACK)
|
||||
|
||||
+8
-1
@@ -65,7 +65,14 @@ import kotlinx.coroutines.sync.withLock
|
||||
* layout.
|
||||
*/
|
||||
class MoqLiteSession internal constructor(
|
||||
private val transport: WebTransportSession,
|
||||
/**
|
||||
* `internal` (not `private`) so test code in the same module can
|
||||
* downcast to a platform [WebTransportSession] (typically
|
||||
* `QuicWebTransportSession`) and read diagnostic flow-control
|
||||
* counters from the underlying QUIC connection. Production code
|
||||
* paths inside this file continue to use `transport` as before.
|
||||
*/
|
||||
internal val transport: WebTransportSession,
|
||||
private val scope: CoroutineScope,
|
||||
) {
|
||||
private val state = Mutex()
|
||||
|
||||
Reference in New Issue
Block a user