Skip to main content

Connection Lifecycle

Understanding the connection state machine and how to handle state transitions.


Connection States

StateDescription
disconnectedInitial state, not connected
connectingWebSocket/WebRTC handshake in progress
connectedFully connected, ready for conversation
reconnectingConnection lost, attempting recovery
failedConnection failed after max retries
closedExplicitly closed by user

Connection Flow


Reconnection

Automatic reconnection is enabled by default with exponential backoff.

Configuration

const client = new LLMRTCWebClient({
signallingUrl: 'ws://localhost:8787',
reconnection: {
enabled: true, // Enable auto-reconnect (default: true)
maxRetries: 5, // Max retry attempts (default: 5)
baseDelayMs: 1000, // Initial delay (default: 1000)
maxDelayMs: 30000, // Max delay (default: 30000)
jitterFactor: 0.3 // Randomization factor (default: 0.3)
}
});

Backoff Formula

delay = min(baseDelayMs * 2^attempt, maxDelayMs) * (1 ± jitterFactor)

Example with defaults:

  • Attempt 1: ~1s
  • Attempt 2: ~2s
  • Attempt 3: ~4s
  • Attempt 4: ~8s
  • Attempt 5: ~16s

Session Recovery

During reconnection, the client attempts to recover the previous session:


Client Methods

start()

Initiate connection:

const client = new LLMRTCWebClient({ signallingUrl: 'ws://localhost:8787' });
await client.start();
// State: connecting → connected

close()

Clean shutdown:

client.close();
// State: → closed

state

Get current state:

if (client.state === 'connected') {
// Ready for conversation
}

currentSessionId

Get session ID (for manual persistence):

const sessionId = client.currentSessionId;
localStorage.setItem('sessionId', sessionId);

Handling State Changes

const client = new LLMRTCWebClient({ signallingUrl: 'ws://localhost:8787' });

client.on('stateChange', (state) => {
console.log('State:', state);

switch (state) {
case 'connecting':
showStatus('Connecting...');
break;

case 'connected':
showStatus('Connected');
enableMicrophone();
break;

case 'reconnecting':
showStatus('Reconnecting...');
disableMicrophone();
break;

case 'failed':
showStatus('Connection failed');
showRetryButton();
break;

case 'closed':
showStatus('Disconnected');
break;
}
});

client.on('reconnecting', (attempt, maxAttempts) => {
showStatus(`Reconnecting (${attempt}/${maxAttempts})...`);
});

Best Practices

Show Connection Status

Always display connection state to users:

function ConnectionBadge({ state }: { state: ConnectionState }) {
const colors = {
disconnected: 'gray',
connecting: 'yellow',
connected: 'green',
reconnecting: 'orange',
failed: 'red',
closed: 'gray'
};

return <Badge color={colors[state]}>{state}</Badge>;
}

Queue Input During Reconnection

Don't drop user interactions during reconnection:

client.on('stateChange', (state) => {
if (state === 'connected') {
// Ready for interaction
enableMicrophone();
} else if (state === 'reconnecting') {
// Disable input during reconnection
disableMicrophone();
}
});

Persist Session for Page Refresh

// On connect
client.on('stateChange', (state) => {
if (state === 'connected') {
localStorage.setItem('sessionId', client.currentSessionId);
}
});

// On page load - session restoration happens automatically
// The client will attempt to reconnect with the previous session
await client.start();