@100mslive/hms-video-store 0.12.20-alpha.3 → 0.12.20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs.js +9 -9
- package/dist/index.cjs.js.map +3 -3
- package/dist/index.js +9 -9
- package/dist/index.js.map +3 -3
- package/dist/interfaces/room.d.ts +0 -1
- package/dist/media/tracks/HMSRemoteVideoTrack.d.ts +1 -2
- package/dist/schema/room.d.ts +0 -1
- package/dist/sdk/models/HMSRoom.d.ts +0 -1
- package/dist/signal/init/models.d.ts +1 -2
- package/dist/transport/RetryScheduler.d.ts +3 -2
- package/dist/utils/constants.d.ts +3 -2
- package/package.json +2 -2
- package/src/connection/subscribe/subscribeConnection.ts +2 -5
- package/src/device-manager/DeviceManager.ts +1 -1
- package/src/interfaces/room.ts +0 -1
- package/src/media/tracks/HMSLocalAudioTrack.ts +2 -2
- package/src/media/tracks/HMSLocalVideoTrack.ts +11 -2
- package/src/media/tracks/HMSRemoteVideoTrack.ts +2 -7
- package/src/media/tracks/RemoteVideoTrack.test.ts +1 -61
- package/src/notification-manager/managers/onDemandTrackManager.ts +1 -6
- package/src/reactive-store/adapter.ts +0 -1
- package/src/schema/room.ts +0 -1
- package/src/sdk/models/HMSRoom.ts +0 -1
- package/src/signal/init/models.ts +0 -1
- package/src/transport/RetryScheduler.ts +21 -24
- package/src/transport/index.ts +4 -1
- package/src/utils/constants.ts +3 -2
|
@@ -9,8 +9,7 @@ export declare class HMSRemoteVideoTrack extends HMSVideoTrack {
|
|
|
9
9
|
private history;
|
|
10
10
|
private preferredLayer;
|
|
11
11
|
private bizTrackId;
|
|
12
|
-
|
|
13
|
-
constructor(stream: HMSRemoteStream, track: MediaStreamTrack, source?: string, disableNoneLayerRequest?: boolean);
|
|
12
|
+
constructor(stream: HMSRemoteStream, track: MediaStreamTrack, source?: string);
|
|
14
13
|
setTrackId(trackId: string): void;
|
|
15
14
|
get trackId(): string;
|
|
16
15
|
get degraded(): boolean;
|
package/dist/schema/room.d.ts
CHANGED
|
@@ -15,7 +15,6 @@ export default class Room implements HMSRoom {
|
|
|
15
15
|
large_room_optimization?: boolean;
|
|
16
16
|
transcriptions?: HMSTranscriptionInfo[];
|
|
17
17
|
isEffectsEnabled?: boolean;
|
|
18
|
-
disableNoneLayerRequest?: boolean;
|
|
19
18
|
isVBEnabled?: boolean;
|
|
20
19
|
effectsKey?: string;
|
|
21
20
|
isHipaaEnabled?: boolean;
|
|
@@ -55,6 +55,5 @@ export declare enum InitFlags {
|
|
|
55
55
|
FLAG_VB_ENABLED = "vb",
|
|
56
56
|
FLAG_HIPAA_ENABLED = "hipaa",
|
|
57
57
|
FLAG_NOISE_CANCELLATION = "noiseCancellation",
|
|
58
|
-
FLAG_SCALE_SCREENSHARE_BASED_ON_PIXELS = "scaleScreenshareBasedOnPixels"
|
|
59
|
-
FLAG_DISABLE_NONE_LAYER_REQUEST = "disableNoneLayerRequest"
|
|
58
|
+
FLAG_SCALE_SCREENSHARE_BASED_ON_PIXELS = "scaleScreenshareBasedOnPixels"
|
|
60
59
|
}
|
|
@@ -18,7 +18,7 @@ interface ScheduleTaskParams {
|
|
|
18
18
|
error: HMSException;
|
|
19
19
|
task: RetryTask;
|
|
20
20
|
originalState: TransportState;
|
|
21
|
-
|
|
21
|
+
maxFailedRetries?: number;
|
|
22
22
|
changeState?: boolean;
|
|
23
23
|
}
|
|
24
24
|
export declare class RetryScheduler {
|
|
@@ -28,10 +28,11 @@ export declare class RetryScheduler {
|
|
|
28
28
|
private inProgress;
|
|
29
29
|
private retryTaskIds;
|
|
30
30
|
constructor(onStateChange: (state: TransportState, error?: HMSException) => Promise<void>, sendEvent: (error: HMSException, category: TFC) => void);
|
|
31
|
-
schedule({ category, error, task, originalState,
|
|
31
|
+
schedule({ category, error, task, originalState, maxFailedRetries, changeState, }: ScheduleTaskParams): Promise<void>;
|
|
32
32
|
reset(): void;
|
|
33
33
|
isTaskInProgress(category: TFC): boolean;
|
|
34
34
|
private scheduleTask;
|
|
35
|
+
private getBaseDelayForTask;
|
|
35
36
|
private getDelayForRetryCount;
|
|
36
37
|
private setTimeoutPromise;
|
|
37
38
|
}
|
|
@@ -2,12 +2,13 @@ export declare const RENEGOTIATION_CALLBACK_ID = "renegotiation-callback-id";
|
|
|
2
2
|
export declare const API_DATA_CHANNEL = "ion-sfu";
|
|
3
3
|
export declare const ANALYTICS_BUFFER_SIZE = 100;
|
|
4
4
|
/**
|
|
5
|
-
* Maximum
|
|
5
|
+
* Maximum number of retries that transport-layer will try
|
|
6
6
|
* before giving up on the connection and returning a failure
|
|
7
7
|
*
|
|
8
8
|
* Refer https://100ms.atlassian.net/browse/HMS-2369
|
|
9
9
|
*/
|
|
10
|
-
export declare const
|
|
10
|
+
export declare const MAX_TRANSPORT_RETRIES = 5;
|
|
11
|
+
export declare const MAX_TRANSPORT_RETRY_DELAY = 60;
|
|
11
12
|
export declare const DEFAULT_SIGNAL_PING_TIMEOUT = 12000;
|
|
12
13
|
export declare const DEFAULT_SIGNAL_PING_INTERVAL = 3000;
|
|
13
14
|
export declare const PONG_RESPONSE_TIMES_SIZE = 5;
|
package/package.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "0.12.20
|
|
2
|
+
"version": "0.12.20",
|
|
3
3
|
"license": "MIT",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
@@ -73,5 +73,5 @@
|
|
|
73
73
|
"conferencing",
|
|
74
74
|
"100ms"
|
|
75
75
|
],
|
|
76
|
-
"gitHead": "
|
|
76
|
+
"gitHead": "da50781c2357d6201da1c94dcfef574a0081e2dc"
|
|
77
77
|
}
|
|
@@ -98,11 +98,8 @@ export default class HMSSubscribeConnection extends HMSConnection {
|
|
|
98
98
|
});
|
|
99
99
|
|
|
100
100
|
const remote = this.remoteStreams.get(streamId)!;
|
|
101
|
-
const
|
|
102
|
-
const
|
|
103
|
-
const track = isAudioTrack
|
|
104
|
-
? new TrackCls(remote, e.track)
|
|
105
|
-
: new TrackCls(remote, e.track, undefined, this.isFlagEnabled(InitFlags.FLAG_DISABLE_NONE_LAYER_REQUEST));
|
|
101
|
+
const TrackCls = e.track.kind === 'audio' ? HMSRemoteAudioTrack : HMSRemoteVideoTrack;
|
|
102
|
+
const track = new TrackCls(remote, e.track);
|
|
106
103
|
// reset the simulcast layer to none when new video tracks are added, UI will subscribe when required
|
|
107
104
|
if (e.track.kind === 'video') {
|
|
108
105
|
remote.setVideoLayerLocally(HMSSimulcastLayer.NONE, 'addTrack', 'subscribeConnection');
|
|
@@ -259,7 +259,7 @@ export class DeviceManager implements HMSDeviceManager {
|
|
|
259
259
|
if (defaultDevice) {
|
|
260
260
|
// Selecting a non-default device so that the deviceId comparision does not give
|
|
261
261
|
// false positives when device is removed, because the other available device
|
|
262
|
-
//
|
|
262
|
+
// get's the deviceId as default once this device is removed
|
|
263
263
|
const nextDevice = this.audioInput.find(device => {
|
|
264
264
|
return device.deviceId !== 'default' && defaultDevice.label.includes(device.label);
|
|
265
265
|
});
|
package/src/interfaces/room.ts
CHANGED
|
@@ -184,8 +184,8 @@ export class HMSLocalAudioTrack extends HMSAudioTrack {
|
|
|
184
184
|
return;
|
|
185
185
|
}
|
|
186
186
|
|
|
187
|
-
// Replace silent empty track
|
|
188
|
-
if (value &&
|
|
187
|
+
// Replace silent empty track with an actual audio track, if enabled.
|
|
188
|
+
if (value && isEmptyTrack(this.nativeTrack)) {
|
|
189
189
|
await this.replaceTrackWith(this.settings);
|
|
190
190
|
}
|
|
191
191
|
await super.setEnabled(value);
|
|
@@ -566,7 +566,12 @@ export class HMSLocalVideoTrack extends HMSVideoTrack {
|
|
|
566
566
|
if (document.visibilityState === 'hidden') {
|
|
567
567
|
this.enabledStateBeforeBackground = this.enabled;
|
|
568
568
|
if (this.enabled) {
|
|
569
|
-
await this.
|
|
569
|
+
const track = await this.replaceTrackWithBlank();
|
|
570
|
+
await this.replaceSender(track, this.enabled);
|
|
571
|
+
this.nativeTrack?.stop();
|
|
572
|
+
this.nativeTrack = track;
|
|
573
|
+
} else {
|
|
574
|
+
await this.replaceSender(this.nativeTrack, false);
|
|
570
575
|
}
|
|
571
576
|
// started interruption event
|
|
572
577
|
this.eventBus.analytics.publish(
|
|
@@ -576,9 +581,12 @@ export class HMSLocalVideoTrack extends HMSVideoTrack {
|
|
|
576
581
|
}),
|
|
577
582
|
);
|
|
578
583
|
} else {
|
|
579
|
-
HMSLogger.d(this.TAG, 'visibility
|
|
584
|
+
HMSLogger.d(this.TAG, 'visibility visibile, restoring track state', this.enabledStateBeforeBackground);
|
|
580
585
|
if (this.enabledStateBeforeBackground) {
|
|
581
586
|
await this.setEnabled(true);
|
|
587
|
+
} else {
|
|
588
|
+
this.nativeTrack.enabled = this.enabledStateBeforeBackground;
|
|
589
|
+
await this.replaceSender(this.nativeTrack, this.enabledStateBeforeBackground);
|
|
582
590
|
}
|
|
583
591
|
// ended interruption event
|
|
584
592
|
this.eventBus.analytics.publish(
|
|
@@ -588,5 +596,6 @@ export class HMSLocalVideoTrack extends HMSVideoTrack {
|
|
|
588
596
|
}),
|
|
589
597
|
);
|
|
590
598
|
}
|
|
599
|
+
this.eventBus.localVideoEnabled.publish({ enabled: this.nativeTrack.enabled, track: this });
|
|
591
600
|
};
|
|
592
601
|
}
|
|
@@ -18,11 +18,9 @@ export class HMSRemoteVideoTrack extends HMSVideoTrack {
|
|
|
18
18
|
private history = new TrackHistory();
|
|
19
19
|
private preferredLayer: HMSPreferredSimulcastLayer = HMSSimulcastLayer.HIGH;
|
|
20
20
|
private bizTrackId!: string;
|
|
21
|
-
private disableNoneLayerRequest = false;
|
|
22
21
|
|
|
23
|
-
constructor(stream: HMSRemoteStream, track: MediaStreamTrack, source?: string
|
|
22
|
+
constructor(stream: HMSRemoteStream, track: MediaStreamTrack, source?: string) {
|
|
24
23
|
super(stream, track, source);
|
|
25
|
-
this.disableNoneLayerRequest = !!disableNoneLayerRequest;
|
|
26
24
|
this.setVideoHandler(new VideoElementManager(this));
|
|
27
25
|
}
|
|
28
26
|
|
|
@@ -172,10 +170,7 @@ export class HMSRemoteVideoTrack extends HMSVideoTrack {
|
|
|
172
170
|
}
|
|
173
171
|
|
|
174
172
|
private async updateLayer(source: string) {
|
|
175
|
-
const newLayer =
|
|
176
|
-
(this.degraded || !this.enabled || !this.hasSinks()) && !this.disableNoneLayerRequest
|
|
177
|
-
? HMSSimulcastLayer.NONE
|
|
178
|
-
: this.preferredLayer;
|
|
173
|
+
const newLayer = this.degraded || !this.enabled || !this.hasSinks() ? HMSSimulcastLayer.NONE : this.preferredLayer;
|
|
179
174
|
if (!this.shouldSendVideoLayer(newLayer, source)) {
|
|
180
175
|
return;
|
|
181
176
|
}
|
|
@@ -19,7 +19,7 @@ describe('remoteVideoTrack', () => {
|
|
|
19
19
|
const connection = { sendOverApiDataChannelWithResponse } as unknown as HMSSubscribeConnection;
|
|
20
20
|
stream = new HMSRemoteStream(nativeStream, connection);
|
|
21
21
|
nativeTrack = { id: trackId, kind: 'video', enabled: true } as MediaStreamTrack;
|
|
22
|
-
track = new HMSRemoteVideoTrack(stream, nativeTrack, 'regular'
|
|
22
|
+
track = new HMSRemoteVideoTrack(stream, nativeTrack, 'regular');
|
|
23
23
|
window.MediaStream = jest.fn().mockImplementation(() => ({
|
|
24
24
|
addTrack: jest.fn(),
|
|
25
25
|
// Add any method you want to mock
|
|
@@ -156,63 +156,3 @@ describe('remoteVideoTrack', () => {
|
|
|
156
156
|
expectLayersSent([HMSSimulcastLayer.HIGH, HMSSimulcastLayer.NONE]);
|
|
157
157
|
});
|
|
158
158
|
});
|
|
159
|
-
|
|
160
|
-
describe('HMSRemoteVideoTrack with disableNoneLayerRequest', () => {
|
|
161
|
-
let stream: HMSRemoteStream;
|
|
162
|
-
let sendOverApiDataChannelWithResponse: jest.Mock;
|
|
163
|
-
let track: HMSRemoteVideoTrack;
|
|
164
|
-
let nativeTrack: MediaStreamTrack;
|
|
165
|
-
let videoElement: HTMLVideoElement;
|
|
166
|
-
const trackId = 'test-track-id';
|
|
167
|
-
|
|
168
|
-
beforeEach(() => {
|
|
169
|
-
videoElement = document.createElement('video');
|
|
170
|
-
sendOverApiDataChannelWithResponse = jest.fn();
|
|
171
|
-
const connection = { sendOverApiDataChannelWithResponse } as unknown as HMSSubscribeConnection;
|
|
172
|
-
const nativeStream = new MediaStream();
|
|
173
|
-
stream = new HMSRemoteStream(nativeStream, connection);
|
|
174
|
-
nativeTrack = { id: trackId, kind: 'video', enabled: true } as MediaStreamTrack;
|
|
175
|
-
track = new HMSRemoteVideoTrack(stream, nativeTrack, 'regular', true); // disableNoneLayerRequest flag is set
|
|
176
|
-
track.setTrackId(trackId);
|
|
177
|
-
|
|
178
|
-
window.MediaStream = jest.fn().mockImplementation(() => ({
|
|
179
|
-
addTrack: jest.fn(),
|
|
180
|
-
}));
|
|
181
|
-
});
|
|
182
|
-
|
|
183
|
-
const expectLayersSent = (layers: HMSSimulcastLayer[]) => {
|
|
184
|
-
const allCalls = sendOverApiDataChannelWithResponse.mock.calls;
|
|
185
|
-
expect(allCalls.length).toBe(layers.length);
|
|
186
|
-
for (let i = 0; i < allCalls.length; i++) {
|
|
187
|
-
const data = allCalls[i][0];
|
|
188
|
-
expect(data.params.max_spatial_layer).toBe(layers[i]);
|
|
189
|
-
}
|
|
190
|
-
};
|
|
191
|
-
|
|
192
|
-
const sfuDegrades = () => {
|
|
193
|
-
track.setLayerFromServer({
|
|
194
|
-
subscriber_degraded: true,
|
|
195
|
-
expected_layer: HMSSimulcastLayer.HIGH,
|
|
196
|
-
current_layer: HMSSimulcastLayer.NONE,
|
|
197
|
-
publisher_degraded: false,
|
|
198
|
-
track_id: trackId,
|
|
199
|
-
});
|
|
200
|
-
};
|
|
201
|
-
|
|
202
|
-
test('disableNoneLayerRequest - degradation', async () => {
|
|
203
|
-
await track.addSink(videoElement);
|
|
204
|
-
expectLayersSent([HMSSimulcastLayer.HIGH]);
|
|
205
|
-
|
|
206
|
-
sfuDegrades();
|
|
207
|
-
expectLayersSent([HMSSimulcastLayer.HIGH]);
|
|
208
|
-
});
|
|
209
|
-
|
|
210
|
-
test('disableNoneLayerRequest - mute and removeSink', async () => {
|
|
211
|
-
await track.addSink(videoElement);
|
|
212
|
-
track.setEnabled(false);
|
|
213
|
-
expectLayersSent([HMSSimulcastLayer.HIGH]);
|
|
214
|
-
|
|
215
|
-
await track.removeSink(videoElement);
|
|
216
|
-
expectLayersSent([HMSSimulcastLayer.HIGH]);
|
|
217
|
-
});
|
|
218
|
-
});
|
|
@@ -67,12 +67,7 @@ export class OnDemandTrackManager extends TrackManager {
|
|
|
67
67
|
const remoteStream = new HMSRemoteStream(new MediaStream(), this.transport.getSubscribeConnection()!);
|
|
68
68
|
const emptyTrack = LocalTrackManager.getEmptyVideoTrack();
|
|
69
69
|
emptyTrack.enabled = !trackInfo.mute;
|
|
70
|
-
const track = new HMSRemoteVideoTrack(
|
|
71
|
-
remoteStream,
|
|
72
|
-
emptyTrack,
|
|
73
|
-
trackInfo.source,
|
|
74
|
-
this.store.getRoom()?.disableNoneLayerRequest,
|
|
75
|
-
);
|
|
70
|
+
const track = new HMSRemoteVideoTrack(remoteStream, emptyTrack, trackInfo.source);
|
|
76
71
|
track.setTrackId(trackInfo.track_id);
|
|
77
72
|
track.peerId = hmsPeer.peerId;
|
|
78
73
|
track.logIdentifier = hmsPeer.name;
|
|
@@ -159,7 +159,6 @@ export class SDKToHMS {
|
|
|
159
159
|
peerCount: sdkRoom.peerCount,
|
|
160
160
|
isLargeRoom: sdkRoom.large_room_optimization,
|
|
161
161
|
isEffectsEnabled: sdkRoom.isEffectsEnabled,
|
|
162
|
-
disableNoneLayerRequest: sdkRoom.disableNoneLayerRequest,
|
|
163
162
|
isVBEnabled: sdkRoom.isVBEnabled,
|
|
164
163
|
effectsKey: sdkRoom.effectsKey,
|
|
165
164
|
isHipaaEnabled: sdkRoom.isHipaaEnabled,
|
package/src/schema/room.ts
CHANGED
|
@@ -16,7 +16,6 @@ export default class Room implements HMSRoom {
|
|
|
16
16
|
large_room_optimization?: boolean;
|
|
17
17
|
transcriptions?: HMSTranscriptionInfo[] = [];
|
|
18
18
|
isEffectsEnabled?: boolean;
|
|
19
|
-
disableNoneLayerRequest?: boolean;
|
|
20
19
|
isVBEnabled?: boolean;
|
|
21
20
|
effectsKey?: string;
|
|
22
21
|
isHipaaEnabled?: boolean;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Dependencies as TFCDependencies, TransportFailureCategory as TFC } from './models/TransportFailureCategory';
|
|
2
2
|
import { TransportState } from './models/TransportState';
|
|
3
3
|
import { HMSException } from '../error/HMSException';
|
|
4
|
-
import {
|
|
4
|
+
import { MAX_TRANSPORT_RETRIES, MAX_TRANSPORT_RETRY_DELAY } from '../utils/constants';
|
|
5
5
|
import HMSLogger from '../utils/logger';
|
|
6
6
|
import { PromiseWithCallbacks } from '../utils/promise';
|
|
7
7
|
|
|
@@ -23,7 +23,7 @@ interface ScheduleTaskParams {
|
|
|
23
23
|
error: HMSException;
|
|
24
24
|
task: RetryTask;
|
|
25
25
|
originalState: TransportState;
|
|
26
|
-
|
|
26
|
+
maxFailedRetries?: number;
|
|
27
27
|
changeState?: boolean;
|
|
28
28
|
}
|
|
29
29
|
|
|
@@ -42,10 +42,10 @@ export class RetryScheduler {
|
|
|
42
42
|
error,
|
|
43
43
|
task,
|
|
44
44
|
originalState,
|
|
45
|
-
|
|
45
|
+
maxFailedRetries = MAX_TRANSPORT_RETRIES,
|
|
46
46
|
changeState = true,
|
|
47
47
|
}: ScheduleTaskParams) {
|
|
48
|
-
await this.scheduleTask({ category, error, changeState, task, originalState,
|
|
48
|
+
await this.scheduleTask({ category, error, changeState, task, originalState, maxFailedRetries });
|
|
49
49
|
}
|
|
50
50
|
|
|
51
51
|
reset() {
|
|
@@ -65,10 +65,9 @@ export class RetryScheduler {
|
|
|
65
65
|
changeState,
|
|
66
66
|
task,
|
|
67
67
|
originalState,
|
|
68
|
-
|
|
69
|
-
maxRetryTime = MAX_TRANSPORT_RETRY_TIME,
|
|
68
|
+
maxFailedRetries = MAX_TRANSPORT_RETRIES,
|
|
70
69
|
failedRetryCount = 0,
|
|
71
|
-
}: ScheduleTaskParams & {
|
|
70
|
+
}: ScheduleTaskParams & { failedRetryCount?: number }): Promise<void> {
|
|
72
71
|
HMSLogger.d(this.TAG, 'schedule: ', { category: TFC[category], error });
|
|
73
72
|
|
|
74
73
|
// First schedule call
|
|
@@ -114,9 +113,8 @@ export class RetryScheduler {
|
|
|
114
113
|
}
|
|
115
114
|
}
|
|
116
115
|
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
error.description += `. [${TFC[category]}] Could not recover after ${timeElapsedSinceError} milliseconds`;
|
|
116
|
+
if (failedRetryCount >= maxFailedRetries || hasFailedDependency) {
|
|
117
|
+
error.description += `. [${TFC[category]}] Could not recover after ${failedRetryCount} tries`;
|
|
120
118
|
|
|
121
119
|
if (hasFailedDependency) {
|
|
122
120
|
error.description += ` Could not recover all of it's required dependencies - [${(dependencies as Array<TFC>)
|
|
@@ -146,7 +144,7 @@ export class RetryScheduler {
|
|
|
146
144
|
this.onStateChange(TransportState.Reconnecting, error);
|
|
147
145
|
}
|
|
148
146
|
|
|
149
|
-
const delay = this.getDelayForRetryCount(category);
|
|
147
|
+
const delay = this.getDelayForRetryCount(category, failedRetryCount);
|
|
150
148
|
|
|
151
149
|
HMSLogger.d(
|
|
152
150
|
this.TAG,
|
|
@@ -173,10 +171,7 @@ export class RetryScheduler {
|
|
|
173
171
|
if (changeState && this.inProgress.size === 0) {
|
|
174
172
|
this.onStateChange(originalState);
|
|
175
173
|
}
|
|
176
|
-
HMSLogger.d(
|
|
177
|
-
this.TAG,
|
|
178
|
-
`schedule: [${TFC[category]}] [failedRetryCount=${failedRetryCount}] Recovered ♻️ after ${timeElapsedSinceError}ms`,
|
|
179
|
-
);
|
|
174
|
+
HMSLogger.d(this.TAG, `schedule: [${TFC[category]}] [failedRetryCount=${failedRetryCount}] Recovered ♻️`);
|
|
180
175
|
} else {
|
|
181
176
|
await this.scheduleTask({
|
|
182
177
|
category,
|
|
@@ -184,23 +179,25 @@ export class RetryScheduler {
|
|
|
184
179
|
changeState,
|
|
185
180
|
task,
|
|
186
181
|
originalState,
|
|
187
|
-
|
|
188
|
-
failedAt,
|
|
182
|
+
maxFailedRetries,
|
|
189
183
|
failedRetryCount: failedRetryCount + 1,
|
|
190
184
|
});
|
|
191
185
|
}
|
|
192
186
|
}
|
|
193
187
|
|
|
194
|
-
private
|
|
195
|
-
const jitter = category === TFC.JoinWSMessageFailed ? Math.random() * 2 : Math.random();
|
|
196
|
-
let delaySeconds = 0;
|
|
188
|
+
private getBaseDelayForTask(category: TFC, n: number) {
|
|
197
189
|
if (category === TFC.JoinWSMessageFailed) {
|
|
198
190
|
// linear backoff(2 + jitter for every retry)
|
|
199
|
-
|
|
200
|
-
} else if (category === TFC.SignalDisconnect) {
|
|
201
|
-
delaySeconds = 1;
|
|
191
|
+
return 2;
|
|
202
192
|
}
|
|
203
|
-
|
|
193
|
+
// exponential backoff
|
|
194
|
+
return Math.pow(2, n);
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
private getDelayForRetryCount(category: TFC, n: number) {
|
|
198
|
+
const delay = this.getBaseDelayForTask(category, n);
|
|
199
|
+
const jitter = category === TFC.JoinWSMessageFailed ? Math.random() * 2 : Math.random();
|
|
200
|
+
return Math.round(Math.min(delay + jitter, MAX_TRANSPORT_RETRY_DELAY) * 1000);
|
|
204
201
|
}
|
|
205
202
|
|
|
206
203
|
private async setTimeoutPromise<T>(task: () => Promise<T>, delay: number): Promise<T> {
|
package/src/transport/index.ts
CHANGED
|
@@ -36,6 +36,7 @@ import { ISignalEventsObserver } from '../signal/ISignalEventsObserver';
|
|
|
36
36
|
import JsonRpcSignal from '../signal/jsonrpc';
|
|
37
37
|
import {
|
|
38
38
|
ICE_DISCONNECTION_TIMEOUT,
|
|
39
|
+
MAX_TRANSPORT_RETRIES,
|
|
39
40
|
PROTOCOL_SPEC,
|
|
40
41
|
PROTOCOL_VERSION,
|
|
41
42
|
PUBLISH_STATS_PUSH_INTERVAL,
|
|
@@ -351,6 +352,7 @@ export default class HMSTransport {
|
|
|
351
352
|
error,
|
|
352
353
|
task,
|
|
353
354
|
originalState: this.state,
|
|
355
|
+
maxFailedRetries: MAX_TRANSPORT_RETRIES,
|
|
354
356
|
changeState: false,
|
|
355
357
|
});
|
|
356
358
|
} else {
|
|
@@ -921,6 +923,7 @@ export default class HMSTransport {
|
|
|
921
923
|
error: hmsError,
|
|
922
924
|
task,
|
|
923
925
|
originalState: TransportState.Joined,
|
|
926
|
+
maxFailedRetries: 3,
|
|
924
927
|
changeState: false,
|
|
925
928
|
});
|
|
926
929
|
} else {
|
|
@@ -1084,6 +1087,7 @@ export default class HMSTransport {
|
|
|
1084
1087
|
error,
|
|
1085
1088
|
task: this.retrySubscribeIceFailedTask,
|
|
1086
1089
|
originalState: TransportState.Joined,
|
|
1090
|
+
maxFailedRetries: 1,
|
|
1087
1091
|
});
|
|
1088
1092
|
}
|
|
1089
1093
|
}
|
|
@@ -1105,7 +1109,6 @@ export default class HMSTransport {
|
|
|
1105
1109
|
if (room) {
|
|
1106
1110
|
room.effectsKey = this.initConfig.config.vb?.effectsKey;
|
|
1107
1111
|
room.isEffectsEnabled = this.isFlagEnabled(InitFlags.FLAG_EFFECTS_SDK_ENABLED);
|
|
1108
|
-
room.disableNoneLayerRequest = this.isFlagEnabled(InitFlags.FLAG_DISABLE_NONE_LAYER_REQUEST);
|
|
1109
1112
|
room.isVBEnabled = this.isFlagEnabled(InitFlags.FLAG_VB_ENABLED);
|
|
1110
1113
|
room.isHipaaEnabled = this.isFlagEnabled(InitFlags.FLAG_HIPAA_ENABLED);
|
|
1111
1114
|
room.isNoiseCancellationEnabled = this.isFlagEnabled(InitFlags.FLAG_NOISE_CANCELLATION);
|
package/src/utils/constants.ts
CHANGED
|
@@ -3,12 +3,13 @@ export const API_DATA_CHANNEL = 'ion-sfu';
|
|
|
3
3
|
export const ANALYTICS_BUFFER_SIZE = 100;
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
|
-
* Maximum
|
|
6
|
+
* Maximum number of retries that transport-layer will try
|
|
7
7
|
* before giving up on the connection and returning a failure
|
|
8
8
|
*
|
|
9
9
|
* Refer https://100ms.atlassian.net/browse/HMS-2369
|
|
10
10
|
*/
|
|
11
|
-
export const
|
|
11
|
+
export const MAX_TRANSPORT_RETRIES = 5;
|
|
12
|
+
export const MAX_TRANSPORT_RETRY_DELAY = 60;
|
|
12
13
|
|
|
13
14
|
export const DEFAULT_SIGNAL_PING_TIMEOUT = 12_000;
|
|
14
15
|
export const DEFAULT_SIGNAL_PING_INTERVAL = 3_000;
|