feat(audio-rooms): NestsReconnectPolicy + Reconnecting state (T4 #2 foundation)
Lays the foundation for the moq-lite reconnect-with-backoff path:
NestsReconnectPolicy — exponential backoff settings.
(initial=1s, multiplier=2, max=30s) by
default, mirroring kixelated/moq's JS
reference (`delay: { initial: 1000,
multiplier: 2, max: 30000 }`).
maxAttempts defaults to Int.MAX_VALUE
since a long-running room should keep
trying as long as the user hasn't left;
the Composable's onDispose is the cancel
signal.
NoRetry sentinel for first-shot-or-fail
tests / single-room demos.
delayForAttempt(n) — 1-indexed; doubles per attempt; clamps at
maxDelayMs. n<1 returns 0.
isExhausted(n) — n >= maxAttempts (next retry forbidden).
init { require(...) } — ctor guards reject zero/negative initial,
multiplier <= 1, max < initial, attempts < 1.
NestsListenerState.Reconnecting / NestsSpeakerState.Reconnecting
— new state variants with (attempt, delayMs). UI consumes via
the existing NestsListenerState → ConnectionUiState mapper which
surfaces Reconnecting under OpeningTransport for the v1 chip;
a future commit can add a dedicated "Attempt N in Mms" UI.
Tests:
* First attempt = initialDelayMs
* Doubling via attempt index until maxDelayMs ceiling
* Non-standard multiplier still respects ceiling
* Zero/negative attempt → 0 delay
* isExhausted at the boundary
* NoRetry exhausts after attempt 1
* Constructor rejects invalid inputs
The orchestration layer (mint-fresh-JWT → reopen WT → re-issue
SubscribeHandles + the speaker-side equivalent) is the heavier
follow-up. Deliberately split because:
1. The state + policy can ship and be consumed by callers ready
to handle Reconnecting today — no behaviour change for those
who don't.
2. The full session-resurrection path needs `MutableSharedFlow`
buffering per SubscribeHandle so app code's `Flow<MoqObject>`
doesn't notice the swap. Substantial refactor; better as its
own commit with its own tests.
This commit is contained in:
+9
@@ -906,6 +906,15 @@ private fun NestsListenerState.toUiState(previous: ConnectionUiState): Connectio
|
||||
ConnectionUiState.Connected
|
||||
}
|
||||
|
||||
is NestsListenerState.Reconnecting -> {
|
||||
// Reconnect is conceptually a "we're connecting again";
|
||||
// surface it under the same UI bucket as the initial
|
||||
// OpeningTransport step so the existing chip/spinner
|
||||
// works without UI changes. A future commit can add a
|
||||
// dedicated UI state for "Attempt N in Mms".
|
||||
ConnectionUiState.Connecting(step = ConnectionUiState.Step.OpeningTransport)
|
||||
}
|
||||
|
||||
is NestsListenerState.Failed -> {
|
||||
ConnectionUiState.Failed(reason)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user