@observertc/observer-js 0.30.6-beta → 0.40.1-beta
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/lib/ObservedCall.d.ts +6 -12
- package/lib/ObservedCall.d.ts.map +1 -1
- package/lib/ObservedCall.js +24 -104
- package/lib/ObservedClient.d.ts +16 -32
- package/lib/ObservedClient.d.ts.map +1 -1
- package/lib/ObservedClient.js +381 -521
- package/lib/ObservedDataChannel.d.ts +68 -0
- package/lib/ObservedDataChannel.d.ts.map +1 -0
- package/lib/ObservedDataChannel.js +110 -0
- package/lib/ObservedInboundTrack.d.ts +3 -9
- package/lib/ObservedInboundTrack.d.ts.map +1 -1
- package/lib/ObservedInboundTrack.js +75 -157
- package/lib/ObservedOutboundTrack.d.ts +9 -9
- package/lib/ObservedOutboundTrack.d.ts.map +1 -1
- package/lib/ObservedOutboundTrack.js +77 -133
- package/lib/ObservedPeerConnection.d.ts +21 -15
- package/lib/ObservedPeerConnection.d.ts.map +1 -1
- package/lib/ObservedPeerConnection.js +85 -171
- package/lib/ObservedSfu.d.ts +5 -7
- package/lib/ObservedSfu.d.ts.map +1 -1
- package/lib/ObservedSfu.js +10 -74
- package/lib/Observer.d.ts +5 -6
- package/lib/Observer.d.ts.map +1 -1
- package/lib/Observer.js +28 -31
- package/lib/common/types.d.ts +0 -55
- package/lib/common/types.d.ts.map +1 -1
- package/lib/index.d.ts +5 -7
- package/lib/index.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/ObservedCall.ts +27 -87
- package/src/ObservedClient.ts +451 -586
- package/src/ObservedDataChannel.ts +186 -0
- package/src/ObservedInboundTrack.ts +18 -72
- package/src/ObservedOutboundTrack.ts +36 -60
- package/src/ObservedPeerConnection.ts +79 -112
- package/src/ObservedSfu.ts +11 -46
- package/src/Observer.ts +11 -16
- package/src/common/types.ts +0 -69
- package/src/index.ts +5 -7
- package/lib/models/Models.d.ts +0 -642
- package/lib/models/Models.d.ts.map +0 -1
- package/lib/models/Models.js +0 -481
- package/lib/models/samples_pb.d.ts +0 -2452
- package/lib/models/samples_pb.d.ts.map +0 -1
- package/lib/models/samples_pb.js +0 -1495
- package/lib/storages/ObserverStorage.d.ts +0 -87
- package/lib/storages/ObserverStorage.d.ts.map +0 -1
- package/lib/storages/ObserverStorage.js +0 -2
- package/lib/storages/SimpleStorage.d.ts +0 -19
- package/lib/storages/SimpleStorage.d.ts.map +0 -1
- package/lib/storages/SimpleStorage.js +0 -106
- package/lib/storages/StorageProvider.d.ts +0 -16
- package/lib/storages/StorageProvider.d.ts.map +0 -1
- package/lib/storages/StorageProvider.js +0 -29
- package/src/models/Models.ts +0 -1103
- package/src/models/samples_pb.ts +0 -4061
- package/src/storages/ObserverStorage.ts +0 -99
- package/src/storages/SimpleStorage.ts +0 -120
- package/src/storages/StorageProvider.ts +0 -42
|
@@ -1,13 +1,11 @@
|
|
|
1
1
|
import { EventEmitter } from 'events';
|
|
2
|
-
import * as Models from './models/Models';
|
|
3
|
-
import { StorageProvider } from './storages/StorageProvider';
|
|
4
2
|
import { PeerConnectionTransport } from '@observertc/sample-schemas-js';
|
|
5
3
|
import { ObservedClient } from './ObservedClient';
|
|
6
|
-
import { ObservedInboundTrack,
|
|
7
|
-
import { ObservedOutboundTrack,
|
|
4
|
+
import { ObservedInboundTrack, ObservedInboundTrackModel } from './ObservedInboundTrack';
|
|
5
|
+
import { ObservedOutboundTrack, ObservedOutboundTrackModel } from './ObservedOutboundTrack';
|
|
8
6
|
import { PeerConnectionTransportReport } from '@observertc/report-schemas-js';
|
|
9
|
-
import { createSingleExecutor } from './common/SingleExecutor';
|
|
10
7
|
import { ObservedICE } from './ObservedICE';
|
|
8
|
+
import { ObservedDataChannel } from './ObservedDataChannel';
|
|
11
9
|
|
|
12
10
|
export type ObservedPeerConnectionEvents = {
|
|
13
11
|
update: [],
|
|
@@ -18,8 +16,9 @@ export type ObservedPeerConnectionEvents = {
|
|
|
18
16
|
newoutboundvideotrack: [ObservedOutboundTrack<'video'>],
|
|
19
17
|
};
|
|
20
18
|
|
|
21
|
-
export type
|
|
19
|
+
export type ObservedPeerConnectionModel = {
|
|
22
20
|
peerConnectionId: string;
|
|
21
|
+
label?: string;
|
|
23
22
|
};
|
|
24
23
|
|
|
25
24
|
export type ObservedPeerConnectionStats = Omit<PeerConnectionTransport, 'transportId' | 'label'>;
|
|
@@ -32,27 +31,7 @@ export declare interface ObservedPeerConnection {
|
|
|
32
31
|
}
|
|
33
32
|
|
|
34
33
|
export class ObservedPeerConnection extends EventEmitter {
|
|
35
|
-
public
|
|
36
|
-
config: ObservedPeerConnectionConfig,
|
|
37
|
-
client: ObservedClient,
|
|
38
|
-
storageProvider: StorageProvider,
|
|
39
|
-
): Promise<ObservedPeerConnection> {
|
|
40
|
-
const model = new Models.PeerConnection({
|
|
41
|
-
roomId: client.roomId,
|
|
42
|
-
serviceId: client.serviceId,
|
|
43
|
-
callId: client.callId,
|
|
44
|
-
clientId: client.clientId,
|
|
45
|
-
peerConnectionId: config.peerConnectionId,
|
|
46
|
-
});
|
|
47
|
-
|
|
48
|
-
const alreadyInserted = await storageProvider.peerConnectionStorage.insert(config.peerConnectionId, model);
|
|
49
|
-
|
|
50
|
-
if (alreadyInserted) throw new Error(`PeerConnection with id ${config.peerConnectionId} already exists`);
|
|
51
|
-
|
|
52
|
-
return new ObservedPeerConnection(model, client, storageProvider);
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
public created = Date.now();
|
|
34
|
+
public readonly created = Date.now();
|
|
56
35
|
|
|
57
36
|
public totalInboundPacketsLost = 0;
|
|
58
37
|
public totalInboundPacketsReceived = 0;
|
|
@@ -99,20 +78,43 @@ export class ObservedPeerConnection extends EventEmitter {
|
|
|
99
78
|
private readonly _inboundVideoTracks = new Map<string, ObservedInboundTrack<'video'>>();
|
|
100
79
|
private readonly _outboundAudioTracks = new Map<string, ObservedOutboundTrack<'audio'>>();
|
|
101
80
|
private readonly _outboundVideoTracks = new Map<string, ObservedOutboundTrack<'video'>>();
|
|
102
|
-
private readonly
|
|
81
|
+
private readonly _dataChannels = new Map<number, ObservedDataChannel>();
|
|
103
82
|
|
|
104
|
-
|
|
105
|
-
private readonly _model:
|
|
83
|
+
public constructor(
|
|
84
|
+
private readonly _model: ObservedPeerConnectionModel,
|
|
106
85
|
public readonly client: ObservedClient,
|
|
107
|
-
private readonly _storageProvider: StorageProvider,
|
|
108
86
|
) {
|
|
109
87
|
super();
|
|
110
88
|
}
|
|
111
89
|
|
|
90
|
+
public get serviceId() {
|
|
91
|
+
return this.client.serviceId;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
public get roomId() {
|
|
95
|
+
return this.client.roomId;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
public get callId() {
|
|
99
|
+
return this.client.callId;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
public get clientId() {
|
|
103
|
+
return this.client.clientId;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
public get mediaUnitId() {
|
|
107
|
+
return this.client.mediaUnitId;
|
|
108
|
+
}
|
|
109
|
+
|
|
112
110
|
public get label() {
|
|
113
111
|
return this._model.label;
|
|
114
112
|
}
|
|
115
113
|
|
|
114
|
+
public set label(value: string | undefined) {
|
|
115
|
+
this._model.label = value;
|
|
116
|
+
}
|
|
117
|
+
|
|
116
118
|
public get usingTURN() {
|
|
117
119
|
return this.ICE.selectedRemoteCandidate?.candidateType?.toLowerCase() === 'relay';
|
|
118
120
|
}
|
|
@@ -158,6 +160,10 @@ export class ObservedPeerConnection extends EventEmitter {
|
|
|
158
160
|
return this._outboundVideoTracks;
|
|
159
161
|
}
|
|
160
162
|
|
|
163
|
+
public get dataChannels(): ReadonlyMap<number, ObservedDataChannel> {
|
|
164
|
+
return this._dataChannels;
|
|
165
|
+
}
|
|
166
|
+
|
|
161
167
|
public get uptimeInMs() {
|
|
162
168
|
return this._updated - this.created;
|
|
163
169
|
}
|
|
@@ -175,9 +181,7 @@ export class ObservedPeerConnection extends EventEmitter {
|
|
|
175
181
|
Array.from(this._outboundAudioTracks.values()).forEach((track) => track.close());
|
|
176
182
|
Array.from(this._outboundVideoTracks.values()).forEach((track) => track.close());
|
|
177
183
|
|
|
178
|
-
this.
|
|
179
|
-
.catch(() => void 0)
|
|
180
|
-
.finally(() => this.emit('close'));
|
|
184
|
+
this.emit('close');
|
|
181
185
|
}
|
|
182
186
|
|
|
183
187
|
public getTrack(trackId: string): ObservedInboundTrack<'audio'> | ObservedInboundTrack<'video'> | ObservedOutboundTrack<'audio'> | ObservedOutboundTrack<'video'> | undefined {
|
|
@@ -287,6 +291,14 @@ export class ObservedPeerConnection extends EventEmitter {
|
|
|
287
291
|
|
|
288
292
|
sumRttInMs = (track.rttInMs ?? 0);
|
|
289
293
|
});
|
|
294
|
+
|
|
295
|
+
this._dataChannels.forEach((channel) => {
|
|
296
|
+
this.deltaDataChannelBytesSent += channel.deltaBytesSent;
|
|
297
|
+
this.deltaDataChannelBytesReceived += channel.deltaBytesReceived;
|
|
298
|
+
this.totalDataChannelBytesSent += channel.totalBytesSent;
|
|
299
|
+
this.totalDataChannelBytesReceived += channel.totalBytesReceived;
|
|
300
|
+
});
|
|
301
|
+
|
|
290
302
|
const iceRttInMs = this.ICE.stats?.currentRoundTripTime;
|
|
291
303
|
let nrOfBelongings = this._inboundAudioTracks.size + this._inboundVideoTracks.size + this._outboundAudioTracks.size + this._outboundVideoTracks.size;
|
|
292
304
|
|
|
@@ -297,14 +309,13 @@ export class ObservedPeerConnection extends EventEmitter {
|
|
|
297
309
|
this.avgRttInMs = 0 < nrOfBelongings ? sumRttInMs / nrOfBelongings : undefined;
|
|
298
310
|
}
|
|
299
311
|
|
|
300
|
-
public
|
|
312
|
+
public update(sample: PeerConnectionTransport, timestamp: number) {
|
|
301
313
|
if (this._closed) return;
|
|
302
314
|
if (sample.peerConnectionId !== this._model.peerConnectionId) throw new Error(`TransportId mismatch. PeerConnectionId: ${ this._model.peerConnectionId } TransportId: ${ sample.transportId}`);
|
|
303
315
|
|
|
304
316
|
this._sample = sample;
|
|
305
317
|
if (this._model.label !== sample.label) {
|
|
306
318
|
this._model.label = sample.label;
|
|
307
|
-
await this._save().catch(() => void 0);
|
|
308
319
|
}
|
|
309
320
|
|
|
310
321
|
const report: PeerConnectionTransportReport = {
|
|
@@ -321,138 +332,94 @@ export class ObservedPeerConnection extends EventEmitter {
|
|
|
321
332
|
|
|
322
333
|
this.reports.addPeerConnectionTransportReports(report);
|
|
323
334
|
|
|
324
|
-
this._updated =
|
|
335
|
+
this._updated = Date.now();
|
|
325
336
|
this.emit('update');
|
|
326
337
|
}
|
|
327
338
|
|
|
328
|
-
public
|
|
339
|
+
public createInboundAudioTrack(config: Omit<ObservedInboundTrackModel<'audio'>, 'kind'>): ObservedInboundTrack<'audio'> {
|
|
329
340
|
if (this._closed) throw new Error(`PeerConnection ${this.peerConnectionId} is closed`);
|
|
330
|
-
|
|
331
|
-
const result =
|
|
341
|
+
|
|
342
|
+
const result = new ObservedInboundTrack<'audio'>({
|
|
332
343
|
kind: 'audio',
|
|
333
|
-
|
|
334
|
-
}, this
|
|
344
|
+
...config,
|
|
345
|
+
}, this);
|
|
335
346
|
|
|
336
|
-
const pendingTracksTimestamp = this.client.ωpendingCreatedTracksTimestamp.get(result.trackId);
|
|
337
|
-
|
|
338
|
-
if (pendingTracksTimestamp) {
|
|
339
|
-
this.client.ωpendingCreatedTracksTimestamp.delete(result.trackId);
|
|
340
|
-
result.created = pendingTracksTimestamp;
|
|
341
|
-
}
|
|
342
|
-
|
|
343
347
|
result.on('close', () => {
|
|
344
348
|
this._inboundAudioTracks.delete(result.trackId);
|
|
345
|
-
this._model.inboundTrackIds = this._model.inboundTrackIds.filter((id) => id !== result.trackId);
|
|
346
|
-
!this._closed &&this._save().catch(() => void 0);
|
|
347
349
|
});
|
|
348
350
|
this._inboundAudioTracks.set(result.trackId, result);
|
|
349
|
-
this._model.inboundTrackIds = [ ...(new Set<string>([ ...this._model.inboundTrackIds, result.trackId ])) ];
|
|
350
|
-
await this._save();
|
|
351
351
|
|
|
352
352
|
this.emit('newinboudaudiotrack', result);
|
|
353
353
|
|
|
354
354
|
return result;
|
|
355
355
|
}
|
|
356
356
|
|
|
357
|
-
public
|
|
357
|
+
public createInboundVideoTrack(config: Omit<ObservedInboundTrackModel<'video'>, 'kind'>): ObservedInboundTrack<'video'> {
|
|
358
358
|
if (this._closed) throw new Error(`PeerConnection ${this.peerConnectionId} is closed`);
|
|
359
|
-
|
|
360
|
-
const result = await ObservedInboundTrack.create<'video'>({
|
|
361
|
-
kind: 'video',
|
|
362
|
-
trackId: config.trackId,
|
|
363
|
-
}, this, this._storageProvider);
|
|
364
359
|
|
|
365
|
-
const
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
result.created = pendingTracksTimestamp;
|
|
370
|
-
}
|
|
360
|
+
const result = new ObservedInboundTrack<'video'>({
|
|
361
|
+
kind: 'video',
|
|
362
|
+
...config,
|
|
363
|
+
}, this);
|
|
371
364
|
|
|
372
365
|
result.on('close', () => {
|
|
373
366
|
this._inboundVideoTracks.delete(result.trackId);
|
|
374
|
-
this._model.inboundTrackIds = this._model.inboundTrackIds.filter((id) => id !== result.trackId);
|
|
375
|
-
!this._closed &&this._save().catch(() => void 0);
|
|
376
367
|
});
|
|
377
368
|
this._inboundVideoTracks.set(result.trackId, result);
|
|
378
|
-
this._model.inboundTrackIds = [ ...(new Set<string>([ ...this._model.inboundTrackIds, result.trackId ])) ];
|
|
379
|
-
await this._save();
|
|
380
369
|
|
|
381
|
-
this.emit('newinboudvideotrack', result);
|
|
382
|
-
|
|
370
|
+
this.emit('newinboudvideotrack', result);
|
|
371
|
+
|
|
383
372
|
return result;
|
|
384
373
|
}
|
|
385
374
|
|
|
386
|
-
public
|
|
375
|
+
public createOutboundAudioTrack(config: Omit<ObservedOutboundTrackModel<'audio'>, 'kind'>): ObservedOutboundTrack<'audio'> {
|
|
387
376
|
if (this._closed) throw new Error(`PeerConnection ${this.peerConnectionId} is closed`);
|
|
388
377
|
|
|
389
|
-
const result =
|
|
378
|
+
const result = new ObservedOutboundTrack<'audio'>({
|
|
390
379
|
kind: 'audio',
|
|
391
|
-
|
|
392
|
-
}, this
|
|
393
|
-
|
|
394
|
-
const pendingTracksTimestamp = this.client.ωpendingCreatedTracksTimestamp.get(result.trackId);
|
|
395
|
-
|
|
396
|
-
if (pendingTracksTimestamp) {
|
|
397
|
-
this.client.ωpendingCreatedTracksTimestamp.delete(result.trackId);
|
|
398
|
-
result.created = pendingTracksTimestamp;
|
|
399
|
-
}
|
|
380
|
+
...config,
|
|
381
|
+
}, this);
|
|
400
382
|
|
|
401
383
|
result.on('close', () => {
|
|
402
384
|
this._outboundAudioTracks.delete(result.trackId);
|
|
403
|
-
this._model.outboundTrackIds = this._model.outboundTrackIds.filter((id) => id !== result.trackId);
|
|
404
|
-
|
|
405
|
-
result.sfuStreamId && this.client.call.sfuStreamIdToOutboundAudioTrack.delete(result.sfuStreamId);
|
|
406
|
-
!this._closed &&this._save().catch(() => void 0);
|
|
407
385
|
});
|
|
408
386
|
this._outboundAudioTracks.set(result.trackId, result);
|
|
409
|
-
this._model.outboundTrackIds = [ ...(new Set<string>([ ...this._model.outboundTrackIds, result.trackId ])) ];
|
|
410
|
-
|
|
411
|
-
result.sfuStreamId && this.client.call.sfuStreamIdToOutboundAudioTrack.set(result.sfuStreamId, result);
|
|
412
|
-
await this._save();
|
|
413
387
|
|
|
414
388
|
this.emit('newoutboundaudiotrack', result);
|
|
415
389
|
|
|
416
390
|
return result;
|
|
417
391
|
}
|
|
418
392
|
|
|
419
|
-
public
|
|
393
|
+
public createOutboundVideoTrack(config: Omit<ObservedOutboundTrackModel<'video'>, 'kind'>): ObservedOutboundTrack<'video'> {
|
|
420
394
|
if (this._closed) throw new Error(`PeerConnection ${this.peerConnectionId} is closed`);
|
|
421
395
|
|
|
422
|
-
const result =
|
|
396
|
+
const result = new ObservedOutboundTrack<'video'>({
|
|
423
397
|
kind: 'video',
|
|
424
|
-
|
|
425
|
-
}, this
|
|
426
|
-
|
|
427
|
-
const pendingTracksTimestamp = this.client.ωpendingCreatedTracksTimestamp.get(result.trackId);
|
|
428
|
-
|
|
429
|
-
if (pendingTracksTimestamp) {
|
|
430
|
-
this.client.ωpendingCreatedTracksTimestamp.delete(result.trackId);
|
|
431
|
-
result.created = pendingTracksTimestamp;
|
|
432
|
-
}
|
|
398
|
+
...config,
|
|
399
|
+
}, this);
|
|
433
400
|
|
|
434
401
|
result.on('close', () => {
|
|
435
402
|
this._outboundVideoTracks.delete(result.trackId);
|
|
436
|
-
result.sfuStreamId && this.client.call.sfuStreamIdToOutboundVideoTrack.set(result.sfuStreamId, result);
|
|
437
|
-
this._model.outboundTrackIds = this._model.outboundTrackIds.filter((id) => id !== result.trackId);
|
|
438
|
-
!this._closed && this._save().catch(() => void 0);
|
|
439
403
|
});
|
|
440
404
|
this._outboundVideoTracks.set(result.trackId, result);
|
|
441
|
-
result.sfuStreamId && this.client.call.sfuStreamIdToOutboundVideoTrack.set(result.sfuStreamId, result);
|
|
442
|
-
this._model.outboundTrackIds = [ ...(new Set<string>([ ...this._model.outboundTrackIds, result.trackId ])) ];
|
|
443
|
-
await this._save();
|
|
444
405
|
|
|
445
406
|
this.emit('newoutboundvideotrack', result);
|
|
446
|
-
|
|
407
|
+
|
|
447
408
|
return result;
|
|
448
409
|
}
|
|
449
410
|
|
|
450
|
-
|
|
411
|
+
public createDataChannel(channelId: number) {
|
|
451
412
|
if (this._closed) throw new Error(`PeerConnection ${this.peerConnectionId} is closed`);
|
|
452
413
|
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
414
|
+
const result = new ObservedDataChannel({
|
|
415
|
+
channelId,
|
|
416
|
+
}, this);
|
|
417
|
+
|
|
418
|
+
result.on('close', () => {
|
|
419
|
+
this._dataChannels.delete(result.channelId);
|
|
456
420
|
});
|
|
421
|
+
this._dataChannels.set(result.channelId, result);
|
|
422
|
+
|
|
423
|
+
return result;
|
|
457
424
|
}
|
|
458
425
|
}
|
package/src/ObservedSfu.ts
CHANGED
|
@@ -1,14 +1,11 @@
|
|
|
1
1
|
import { EventEmitter } from 'events';
|
|
2
|
-
import * as Models from './models/Models';
|
|
3
2
|
import { Observer } from './Observer';
|
|
4
|
-
import { createSingleExecutor } from './common/SingleExecutor';
|
|
5
3
|
import { SfuSample } from '@observertc/sample-schemas-js';
|
|
6
4
|
|
|
7
|
-
export type
|
|
5
|
+
export type ObservedSfuModel= {
|
|
8
6
|
serviceId: string;
|
|
9
7
|
sfuId: string;
|
|
10
8
|
joined?: number;
|
|
11
|
-
appData: AppData;
|
|
12
9
|
};
|
|
13
10
|
|
|
14
11
|
export type ObservedSfuEvents = {
|
|
@@ -24,36 +21,13 @@ export declare interface ObservedSfu {
|
|
|
24
21
|
}
|
|
25
22
|
|
|
26
23
|
export class ObservedSfu<AppData extends Record<string, unknown> = Record<string, unknown>> extends EventEmitter {
|
|
27
|
-
public
|
|
28
|
-
config: ObservedSfuConfig<T>,
|
|
29
|
-
observer: Observer,
|
|
30
|
-
// reportsCollector: ReportsCollector,
|
|
31
|
-
) {
|
|
32
|
-
const model = new Models.Sfu({
|
|
33
|
-
serviceId: config.serviceId,
|
|
34
|
-
sfuId: config.sfuId,
|
|
35
|
-
sfuTransportIds: [],
|
|
36
|
-
joined: BigInt(config.joined ?? Date.now()),
|
|
37
|
-
});
|
|
38
|
-
const result = new ObservedSfu(
|
|
39
|
-
model,
|
|
40
|
-
observer,
|
|
41
|
-
config.appData,
|
|
42
|
-
);
|
|
43
|
-
|
|
44
|
-
const alreadyInserted = await observer.storage.sfuStorage.insert(config.sfuId, model);
|
|
45
|
-
|
|
46
|
-
if (alreadyInserted) throw new Error(`Sfu with id ${config.sfuId} already exists`);
|
|
47
|
-
|
|
48
|
-
return result;
|
|
49
|
-
}
|
|
24
|
+
public readonly created = Date.now();
|
|
50
25
|
|
|
51
26
|
private _updated = Date.now();
|
|
52
|
-
private readonly _execute = createSingleExecutor();
|
|
53
27
|
private _closed = false;
|
|
54
28
|
|
|
55
|
-
|
|
56
|
-
private readonly _model:
|
|
29
|
+
public constructor(
|
|
30
|
+
private readonly _model: ObservedSfuModel,
|
|
57
31
|
public readonly observer: Observer,
|
|
58
32
|
public readonly appData: AppData,
|
|
59
33
|
) {
|
|
@@ -75,6 +49,10 @@ export class ObservedSfu<AppData extends Record<string, unknown> = Record<string
|
|
|
75
49
|
return Number(this._model.joined!);
|
|
76
50
|
}
|
|
77
51
|
|
|
52
|
+
public get updated() {
|
|
53
|
+
return this._updated;
|
|
54
|
+
}
|
|
55
|
+
|
|
78
56
|
public get closed() {
|
|
79
57
|
return this._closed;
|
|
80
58
|
}
|
|
@@ -85,24 +63,11 @@ export class ObservedSfu<AppData extends Record<string, unknown> = Record<string
|
|
|
85
63
|
this.emit('close');
|
|
86
64
|
}
|
|
87
65
|
|
|
88
|
-
public
|
|
66
|
+
public update(sample: SfuSample) {
|
|
89
67
|
if (this._closed) throw new Error(`Sfu ${this.sfuId} is closed`);
|
|
90
68
|
if (sample.sfuId !== this.sfuId) throw new Error(`Sfu ${this.sfuId} is not the same as sample.sfuId`);
|
|
91
69
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
await this._save();
|
|
95
|
-
this.emit('update');
|
|
96
|
-
});
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
private async _save() {
|
|
100
|
-
if (this._closed) throw new Error(`Sfu ${this.sfuId} is closed`);
|
|
101
|
-
|
|
102
|
-
return this._execute(async () => {
|
|
103
|
-
if (this._closed) throw new Error(`Sfu ${this.sfuId} is closed`);
|
|
104
|
-
await this.observer.storage.sfuStorage.set(this.sfuId, this._model);
|
|
105
|
-
});
|
|
70
|
+
this._updated = Date.now();
|
|
71
|
+
this.emit('update');
|
|
106
72
|
}
|
|
107
|
-
|
|
108
73
|
}
|
package/src/Observer.ts
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import { createLogger } from './common/logger';
|
|
2
|
-
import {
|
|
3
|
-
import { ObservedCall, ObservedCallConfig } from './ObservedCall';
|
|
2
|
+
import { ObservedCall, ObservedCallModel } from './ObservedCall';
|
|
4
3
|
import { ReportsCollector } from './ReportsCollector';
|
|
5
4
|
import { EventEmitter } from 'events';
|
|
6
5
|
import { PartialBy } from './common/utils';
|
|
7
|
-
import { createCallStartedEventReport } from './common/callEventReports';
|
|
6
|
+
import { createCallEndedEventReport, createCallStartedEventReport } from './common/callEventReports';
|
|
8
7
|
|
|
9
8
|
const logger = createLogger('Observer');
|
|
10
9
|
|
|
@@ -36,8 +35,6 @@ export type ObserverConfig = {
|
|
|
36
35
|
maxCollectingTimeInMs?: number | undefined;
|
|
37
36
|
|
|
38
37
|
maxEntryIdleTimeInMs?: number | undefined;
|
|
39
|
-
|
|
40
|
-
storages?: StorageProvider;
|
|
41
38
|
};
|
|
42
39
|
|
|
43
40
|
export declare interface Observer {
|
|
@@ -63,9 +60,7 @@ export class Observer extends EventEmitter {
|
|
|
63
60
|
providedConfig
|
|
64
61
|
);
|
|
65
62
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
return new Observer(config, storages);
|
|
63
|
+
return new Observer(config);
|
|
69
64
|
}
|
|
70
65
|
|
|
71
66
|
public readonly reports = new ReportsCollector();
|
|
@@ -74,7 +69,6 @@ export class Observer extends EventEmitter {
|
|
|
74
69
|
private _closed = false;
|
|
75
70
|
public constructor(
|
|
76
71
|
public readonly config: ObserverConfig,
|
|
77
|
-
public readonly storage: StorageProvider,
|
|
78
72
|
) {
|
|
79
73
|
super();
|
|
80
74
|
logger.debug('Observer is created with config', this.config);
|
|
@@ -91,25 +85,26 @@ export class Observer extends EventEmitter {
|
|
|
91
85
|
this.reports.on('newreport', onNewReport);
|
|
92
86
|
}
|
|
93
87
|
|
|
94
|
-
public
|
|
95
|
-
config: PartialBy<
|
|
96
|
-
):
|
|
88
|
+
public createObservedCall<T extends Record<string, unknown> = Record<string, unknown>>(
|
|
89
|
+
config: PartialBy<ObservedCallModel, 'serviceId' | 'started'> & { appData: T }
|
|
90
|
+
): ObservedCall<T> {
|
|
97
91
|
if (this._closed) {
|
|
98
92
|
throw new Error('Attempted to create a call source on a closed observer');
|
|
99
93
|
}
|
|
100
94
|
|
|
101
|
-
const
|
|
95
|
+
const { appData, ...model } = config;
|
|
96
|
+
const call = new ObservedCall({
|
|
97
|
+
...model,
|
|
102
98
|
serviceId: this.config.defaultServiceId,
|
|
103
99
|
started: Date.now(),
|
|
104
|
-
|
|
105
|
-
}, this);
|
|
100
|
+
}, this, appData);
|
|
106
101
|
|
|
107
102
|
if (this._closed) throw new Error('Cannot create an observed call on a closed observer');
|
|
108
103
|
if (this._observedCalls.has(call.callId)) throw new Error(`Observed Call with id ${call.callId} already exists`);
|
|
109
104
|
|
|
110
105
|
call.once('close', () => {
|
|
111
106
|
this._observedCalls.delete(call.callId);
|
|
112
|
-
this.reports.addCallEventReport(
|
|
107
|
+
this.reports.addCallEventReport(createCallEndedEventReport(
|
|
113
108
|
call.serviceId,
|
|
114
109
|
call.roomId,
|
|
115
110
|
call.callId,
|
package/src/common/types.ts
CHANGED
|
@@ -18,78 +18,9 @@ import {
|
|
|
18
18
|
SfuSctpStreamReport,
|
|
19
19
|
SFUTransportReport,
|
|
20
20
|
} from '@observertc/report-schemas-js';
|
|
21
|
-
import * as Models from '../models/Models';
|
|
22
|
-
import { StorageProvider } from '../storages/StorageProvider';
|
|
23
|
-
import { Message } from '@bufbuild/protobuf';
|
|
24
21
|
|
|
25
22
|
export type MediaKind = 'audio' | 'video';
|
|
26
23
|
|
|
27
|
-
export interface EvaluatorContext {
|
|
28
|
-
readonly startedCallIds: string[];
|
|
29
|
-
readonly endedCalls: (Omit<Models.Call, keyof Message> & {
|
|
30
|
-
ended: number;
|
|
31
|
-
})[];
|
|
32
|
-
|
|
33
|
-
readonly joinedClientIds: string[];
|
|
34
|
-
readonly detachedClients: (Omit<Models.Client, keyof Message> & {
|
|
35
|
-
detached: number;
|
|
36
|
-
})[];
|
|
37
|
-
|
|
38
|
-
readonly openedPeerConnectionIds: string[];
|
|
39
|
-
readonly closedPeerConnections: (Omit<Models.PeerConnection, keyof Message> & {
|
|
40
|
-
closed: number;
|
|
41
|
-
})[];
|
|
42
|
-
|
|
43
|
-
readonly addedInboundAudioTrackIds: string[];
|
|
44
|
-
readonly removedInboundAudioTracks: (Omit<Models.InboundTrack, keyof Message> & {
|
|
45
|
-
removed: number;
|
|
46
|
-
})[];
|
|
47
|
-
|
|
48
|
-
readonly addedInboundVideoTrackIds: string[];
|
|
49
|
-
readonly removedInboundVideoTracks: (Omit<Models.InboundTrack, keyof Message> & {
|
|
50
|
-
removed: number;
|
|
51
|
-
})[];
|
|
52
|
-
|
|
53
|
-
readonly addedOutboundAudioTrackIds: string[];
|
|
54
|
-
readonly removedOutboundAudioTracks: (Omit<Models.OutboundTrack, keyof Message> & {
|
|
55
|
-
removed: number;
|
|
56
|
-
})[];
|
|
57
|
-
|
|
58
|
-
readonly addedOutboundVideoTrackIds: string[];
|
|
59
|
-
readonly removedOutboundVideoTracks: (Omit<Models.OutboundTrack, keyof Message> & {
|
|
60
|
-
removed: number;
|
|
61
|
-
})[];
|
|
62
|
-
|
|
63
|
-
readonly joinedSfuIds: string[];
|
|
64
|
-
readonly detachedSfus: (Omit<Models.Sfu, keyof Message> & {
|
|
65
|
-
detached: number;
|
|
66
|
-
})[];
|
|
67
|
-
|
|
68
|
-
readonly openedSfuTransportIds: string[];
|
|
69
|
-
readonly closedSfuTransports: (Omit<Models.SfuTransport, keyof Message> & {
|
|
70
|
-
closed: number;
|
|
71
|
-
})[];
|
|
72
|
-
|
|
73
|
-
readonly addedSfuInbounRtpPadIds: string[];
|
|
74
|
-
readonly removedSfuInbounRtpPadIds: (Omit<Models.SfuInboundRtpPad, keyof Message> & {
|
|
75
|
-
removed: number;
|
|
76
|
-
})[];
|
|
77
|
-
|
|
78
|
-
readonly addedSfuOutbounRtpPadIds: string[];
|
|
79
|
-
readonly removedSfuOutbounRtpPadIds: (Omit<Models.SfuOutboundRtpPad, keyof Message> & {
|
|
80
|
-
removed: number;
|
|
81
|
-
})[];
|
|
82
|
-
|
|
83
|
-
readonly openedSfuSctpChannelIds: string[];
|
|
84
|
-
readonly closedSfuSctpChannels: (Omit<Models.SfuSctpChannel, keyof Message> & {
|
|
85
|
-
closed: number;
|
|
86
|
-
})[];
|
|
87
|
-
|
|
88
|
-
readonly storages: StorageProvider;
|
|
89
|
-
readonly reports: ObserverSinkContext;
|
|
90
|
-
|
|
91
|
-
}
|
|
92
|
-
|
|
93
24
|
// export type EvaluatorMiddleware = Middleware<EvaluatorContext>;
|
|
94
25
|
|
|
95
26
|
export interface ObserverSinkContext {
|
package/src/index.ts
CHANGED
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
export type { ObserverConfig, ObserverEvents } from './Observer';
|
|
2
2
|
|
|
3
3
|
export { Observer } from './Observer';
|
|
4
|
-
export type { ObserverStorage } from './storages/ObserverStorage';
|
|
5
|
-
export type { StorageProvider } from './storages/StorageProvider';
|
|
6
4
|
|
|
7
5
|
export * as SampleSchema from '@observertc/sample-schemas-js';
|
|
8
6
|
export * as ReportSchema from '@observertc/report-schemas-js';
|
|
@@ -54,12 +52,12 @@ export type {
|
|
|
54
52
|
SFUTransportReport,
|
|
55
53
|
} from '@observertc/report-schemas-js';
|
|
56
54
|
|
|
57
|
-
export type { ObservedClient,
|
|
58
|
-
export type { ObservedPeerConnection,
|
|
59
|
-
export type { ObservedInboundTrack,
|
|
60
|
-
export type { ObservedOutboundTrack,
|
|
55
|
+
export type { ObservedClient, ObservedClientModel } from './ObservedClient';
|
|
56
|
+
export type { ObservedPeerConnection, ObservedPeerConnectionModel, ObservedPeerConnectionEvents } from './ObservedPeerConnection';
|
|
57
|
+
export type { ObservedInboundTrack, ObservedInboundTrackModel, ObservedInboundTrackEvents } from './ObservedInboundTrack';
|
|
58
|
+
export type { ObservedOutboundTrack, ObservedOutboundTrackModel, ObservedOutboundTrackEvents } from './ObservedOutboundTrack';
|
|
61
59
|
|
|
62
|
-
export type {
|
|
60
|
+
export type { ObserverSinkContext } from './common/types';
|
|
63
61
|
|
|
64
62
|
import { Observer, ObserverConfig } from './Observer';
|
|
65
63
|
export function createObserver(config?: Partial<ObserverConfig>) {
|