feat(nests): proactive JWT refresh + reconnect for speaker path
Mirror the listener's ReconnectingNestsListener for the publish side. moq-auth issues 600 s bearer tokens; without proactive refresh, a user holding the stage past 10 minutes silently drops when the relay tears down the WebTransport session and stays off the air until they manually re-tap Talk. The new wrapper recycles the session at 540 s so the relay never sees an expired token, and re-issues publishing onto each fresh session with the user's mute intent replayed on the new handle. VM swap is a one-line change to DefaultNestsSpeakerConnector. The caller-owned BroadcastHandle is now the wrapper's stable handle that survives every refresh. Six unit tests cover happy path, refresh-without-failure-state, mute replay across recycle, close idempotence, first-attempt-failure exception propagation, and post-close startBroadcasting guard. https://claude.ai/code/session_01HXf3zG3F2ev2ASeQju7Y5S
This commit is contained in:
+11
-2
@@ -36,8 +36,8 @@ import com.vitorpamplona.nestsclient.audio.AudioPlayer
|
||||
import com.vitorpamplona.nestsclient.audio.NestPlayer
|
||||
import com.vitorpamplona.nestsclient.audio.OpusDecoder
|
||||
import com.vitorpamplona.nestsclient.audio.OpusEncoder
|
||||
import com.vitorpamplona.nestsclient.connectNestsSpeaker
|
||||
import com.vitorpamplona.nestsclient.connectReconnectingNestsListener
|
||||
import com.vitorpamplona.nestsclient.connectReconnectingNestsSpeaker
|
||||
import com.vitorpamplona.nestsclient.moq.SubscribeHandle
|
||||
import com.vitorpamplona.nestsclient.transport.WebTransportFactory
|
||||
import com.vitorpamplona.quartz.nip01Core.signers.NostrSigner
|
||||
@@ -1132,9 +1132,18 @@ fun interface NestsSpeakerConnector {
|
||||
): NestsSpeaker
|
||||
}
|
||||
|
||||
/**
|
||||
* Production speaker factory — wraps each session in
|
||||
* [connectReconnectingNestsSpeaker] so transport drops auto-retry
|
||||
* with exponential backoff AND the moq-auth 600 s JWT TTL is
|
||||
* proactively refreshed (default 540 s recycle window). The
|
||||
* returned [BroadcastHandle] survives every refresh — the wrapper
|
||||
* re-issues publishing onto each fresh session and replays the
|
||||
* user's mute state on the new handle.
|
||||
*/
|
||||
private val DefaultNestsSpeakerConnector =
|
||||
NestsSpeakerConnector { httpClient, transport, scope, room, signer, pubkey, capF, encF ->
|
||||
connectNestsSpeaker(
|
||||
connectReconnectingNestsSpeaker(
|
||||
httpClient = httpClient,
|
||||
transport = transport,
|
||||
scope = scope,
|
||||
|
||||
Reference in New Issue
Block a user