Skip to content

Commit

Permalink
Improve reconnect timeout handling (#321)
Browse files Browse the repository at this point in the history
* Improve reconnect timeout handling

Previously multiple attempts could be queued - resulting in more frequent
retries than desired.
  • Loading branch information
davidzhao authored Jul 13, 2022
1 parent 56694b7 commit 607aa81
Show file tree
Hide file tree
Showing 4 changed files with 35 additions and 11 deletions.
5 changes: 5 additions & 0 deletions .changeset/late-mice-explode.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'livekit-client': patch
---

Improve reconnect timeout handling
5 changes: 5 additions & 0 deletions .changeset/smart-lemons-appear.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'livekit-client': patch
---

Customizable reconnect policy
14 changes: 8 additions & 6 deletions src/room/DefaultReconnectPolicy.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
import { ReconnectContext, ReconnectPolicy } from './ReconnectPolicy';

const maxRetryDelay = 7000;

const DEFAULT_RETRY_DELAYS_IN_MS = [
0,
300,
2 * 2 * 300,
3 * 3 * 300,
4 * 4 * 300,
5 * 5 * 300,
6 * 6 * 300,
7 * 7 * 300,
8 * 8 * 300,
9 * 9 * 300,
maxRetryDelay,
maxRetryDelay,
maxRetryDelay,
maxRetryDelay,
maxRetryDelay,
];

class DefaultReconnectPolicy implements ReconnectPolicy {
Expand All @@ -21,7 +23,7 @@ class DefaultReconnectPolicy implements ReconnectPolicy {
}

public nextRetryDelayInMs(context: ReconnectContext): number | null {
if (context.retryCount === this._retryDelays.length) return null;
if (context.retryCount >= this._retryDelays.length) return null;

const retryDelay = this._retryDelays[context.retryCount];
if (context.retryCount <= 1) return retryDelay;
Expand Down
22 changes: 17 additions & 5 deletions src/room/RTCEngine.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { EventEmitter } from 'events';
import type TypedEventEmitter from 'typed-emitter';
import { SignalClient, SignalOptions } from '../api/SignalClient';
import log from '../logger';
import { RoomOptions } from '../options';
import {
ClientConfigSetting,
ClientConfiguration,
Expand All @@ -19,13 +20,12 @@ import {
SignalTarget,
TrackPublishedResponse,
} from '../proto/livekit_rtc';
import DefaultReconnectPolicy from './DefaultReconnectPolicy';
import { ConnectionError, TrackInvalidError, UnexpectedConnectionState } from './errors';
import { EngineEvent } from './events';
import PCTransport from './PCTransport';
import { isFireFox, isWeb, sleep } from './utils';
import { RoomOptions } from '../options';
import { ReconnectContext, ReconnectPolicy } from './ReconnectPolicy';
import DefaultReconnectPolicy from './DefaultReconnectPolicy';
import { isFireFox, isWeb, sleep } from './utils';

const lossyDataChannel = '_lossy';
const reliableDataChannel = '_reliable';
Expand Down Expand Up @@ -99,6 +99,8 @@ export default class RTCEngine extends (EventEmitter as new () => TypedEventEmit

private reconnectPolicy: ReconnectPolicy;

private reconnectTimeout?: ReturnType<typeof setTimeout>;

constructor(private options: RoomOptions) {
super();
this.client = new SignalClient();
Expand Down Expand Up @@ -474,7 +476,10 @@ export default class RTCEngine extends (EventEmitter as new () => TypedEventEmit

log.debug(`reconnecting in ${delay}ms`);

setTimeout(async () => {
if (this.reconnectTimeout) {
clearTimeout(this.reconnectTimeout);
}
this.reconnectTimeout = setTimeout(async () => {
if (this._isClosed) {
return;
}
Expand All @@ -501,6 +506,9 @@ export default class RTCEngine extends (EventEmitter as new () => TypedEventEmit
}
this.reconnectAttempts = 0;
this.fullReconnectOnNext = false;
if (this.reconnectTimeout) {
clearTimeout(this.reconnectTimeout);
}
} catch (e) {
this.reconnectAttempts += 1;
let reconnectRequired = false;
Expand Down Expand Up @@ -597,7 +605,11 @@ export default class RTCEngine extends (EventEmitter as new () => TypedEventEmit
try {
await this.client.reconnect(this.url, this.token);
} catch (e) {
throw new SignalReconnectError(e);
let message = '';
if (e instanceof Error) {
message = e.message;
}
throw new SignalReconnectError(message);
}
this.emit(EngineEvent.SignalResumed);

Expand Down

0 comments on commit 607aa81

Please sign in to comment.