@webex/internal-plugin-metrics 3.12.0-next.6 → 3.12.0-next.60
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/.repo-context.json +466 -0
- package/.sdd/manifest.json +626 -0
- package/AGENTS.md +208 -0
- package/README.md +274 -0
- package/dist/automated-user.js +19 -0
- package/dist/automated-user.js.map +1 -0
- package/dist/batcher.js +3 -0
- package/dist/batcher.js.map +1 -1
- package/dist/call-diagnostic/call-diagnostic-metrics-latencies.js +613 -53
- package/dist/call-diagnostic/call-diagnostic-metrics-latencies.js.map +1 -1
- package/dist/call-diagnostic/call-diagnostic-metrics.js +240 -103
- package/dist/call-diagnostic/call-diagnostic-metrics.js.map +1 -1
- package/dist/call-diagnostic/call-diagnostic-metrics.util.js +5 -0
- package/dist/call-diagnostic/call-diagnostic-metrics.util.js.map +1 -1
- package/dist/call-diagnostic/config.js +19 -4
- package/dist/call-diagnostic/config.js.map +1 -1
- package/dist/config.js +8 -0
- package/dist/config.js.map +1 -1
- package/dist/index.js +25 -1
- package/dist/index.js.map +1 -1
- package/dist/metrics.js +118 -5
- package/dist/metrics.js.map +1 -1
- package/dist/metrics.types.js +4 -0
- package/dist/metrics.types.js.map +1 -1
- package/dist/network-telemetry.js +610 -0
- package/dist/network-telemetry.js.map +1 -0
- package/dist/new-metrics.js +63 -17
- package/dist/new-metrics.js.map +1 -1
- package/dist/privacy-and-security-permission-enricher/constants.js +18 -0
- package/dist/privacy-and-security-permission-enricher/constants.js.map +1 -0
- package/dist/privacy-and-security-permission-enricher/index.js +143 -0
- package/dist/privacy-and-security-permission-enricher/index.js.map +1 -0
- package/dist/privacy-and-security-permission-enricher/types.js +7 -0
- package/dist/privacy-and-security-permission-enricher/types.js.map +1 -0
- package/dist/privacy-and-security-permission-enricher/utils.js +71 -0
- package/dist/privacy-and-security-permission-enricher/utils.js.map +1 -0
- package/dist/types/automated-user.d.ts +2 -0
- package/dist/types/call-diagnostic/call-diagnostic-metrics-latencies.d.ts +200 -5
- package/dist/types/call-diagnostic/call-diagnostic-metrics.d.ts +77 -17
- package/dist/types/call-diagnostic/config.d.ts +6 -0
- package/dist/types/config.d.ts +9 -0
- package/dist/types/index.d.ts +5 -3
- package/dist/types/metrics.types.d.ts +11 -5
- package/dist/types/network-telemetry.d.ts +108 -0
- package/dist/types/new-metrics.d.ts +17 -1
- package/dist/types/privacy-and-security-permission-enricher/constants.d.ts +6 -0
- package/dist/types/privacy-and-security-permission-enricher/index.d.ts +40 -0
- package/dist/types/privacy-and-security-permission-enricher/types.d.ts +14 -0
- package/dist/types/privacy-and-security-permission-enricher/utils.d.ts +5 -0
- package/dist/types/unhandled-exception-telemetry/index.d.ts +60 -0
- package/dist/types/unhandled-exception-telemetry/utils.d.ts +6 -0
- package/dist/unhandled-exception-telemetry/index.js +331 -0
- package/dist/unhandled-exception-telemetry/index.js.map +1 -0
- package/dist/unhandled-exception-telemetry/utils.js +105 -0
- package/dist/unhandled-exception-telemetry/utils.js.map +1 -0
- package/docs/adr/index.md +27 -0
- package/docs/architecture.md +437 -0
- package/docs/getting-started.md +131 -0
- package/docs/index.md +52 -0
- package/docs/specs/README.md +88 -0
- package/package.json +12 -11
- package/schemas/repo-context.schema.json +796 -0
- package/src/automated-user.ts +16 -0
- package/src/batcher.js +4 -0
- package/src/call-diagnostic/call-diagnostic-metrics-latencies.ts +737 -60
- package/src/call-diagnostic/call-diagnostic-metrics.ts +184 -42
- package/src/call-diagnostic/call-diagnostic-metrics.util.ts +5 -0
- package/src/call-diagnostic/config.ts +16 -0
- package/src/call-diagnostic/docs/README.md +535 -0
- package/src/config.js +8 -0
- package/src/docs/README.md +703 -0
- package/src/index.ts +16 -0
- package/src/metrics.js +123 -5
- package/src/metrics.types.ts +29 -6
- package/src/network-telemetry.ts +757 -0
- package/src/new-metrics.ts +56 -6
- package/src/privacy-and-security-permission-enricher/constants.ts +33 -0
- package/src/privacy-and-security-permission-enricher/docs/README.md +356 -0
- package/src/privacy-and-security-permission-enricher/index.ts +142 -0
- package/src/privacy-and-security-permission-enricher/types.ts +21 -0
- package/src/privacy-and-security-permission-enricher/utils.ts +82 -0
- package/src/rtcMetrics/docs/README.md +447 -0
- package/src/unhandled-exception-telemetry/docs/README.md +536 -0
- package/src/unhandled-exception-telemetry/index.ts +404 -0
- package/src/unhandled-exception-telemetry/utils.ts +101 -0
- package/test/unit/spec/automated-user.ts +43 -0
- package/test/unit/spec/batcher.js +43 -0
- package/test/unit/spec/call-diagnostic/call-diagnostic-metrics-batcher.ts +10 -1
- package/test/unit/spec/call-diagnostic/call-diagnostic-metrics-latencies.ts +1336 -131
- package/test/unit/spec/call-diagnostic/call-diagnostic-metrics.ts +1265 -207
- package/test/unit/spec/call-diagnostic/call-diagnostic-metrics.util.ts +27 -0
- package/test/unit/spec/metrics.js +14 -5
- package/test/unit/spec/network-telemetry.ts +610 -0
- package/test/unit/spec/new-metrics.ts +203 -50
- package/test/unit/spec/prelogin-metrics-batcher.ts +71 -36
- package/test/unit/spec/privacy-and-security-permission-enricher.ts +318 -0
- package/test/unit/spec/unhandled-exception-telemetry/utils.ts +109 -0
- package/test/unit/spec/unhandled-exception-telemetry.ts +689 -0
|
@@ -5,11 +5,12 @@ import sinon from 'sinon';
|
|
|
5
5
|
describe('internal-plugin-metrics', () => {
|
|
6
6
|
describe('CallDiagnosticLatencies', () => {
|
|
7
7
|
let cdl: CallDiagnosticLatencies;
|
|
8
|
+
let clock: ReturnType<typeof sinon.useFakeTimers>;
|
|
8
9
|
var now = new Date();
|
|
9
10
|
|
|
10
11
|
beforeEach(() => {
|
|
11
12
|
sinon.createSandbox();
|
|
12
|
-
sinon.useFakeTimers(now.getTime());
|
|
13
|
+
clock = sinon.useFakeTimers(now.getTime());
|
|
13
14
|
const webex = {
|
|
14
15
|
meetings: {
|
|
15
16
|
getBasicMeetingInformation: (id: string) => {
|
|
@@ -51,17 +52,17 @@ describe('internal-plugin-metrics', () => {
|
|
|
51
52
|
|
|
52
53
|
it('should overwrite latency when accumulate is false', () => {
|
|
53
54
|
assert.deepEqual(cdl.precomputedLatencies.size, 0);
|
|
54
|
-
cdl.saveLatency('internal.client.pageJMT', 10, false);
|
|
55
|
+
cdl.saveLatency('internal.client.pageJMT', 10, {accumulate: false});
|
|
55
56
|
assert.deepEqual(cdl.precomputedLatencies.size, 1);
|
|
56
57
|
assert.deepEqual(cdl.precomputedLatencies.get('internal.client.pageJMT'), 10);
|
|
57
|
-
cdl.saveLatency('internal.client.pageJMT', 20, false);
|
|
58
|
+
cdl.saveLatency('internal.client.pageJMT', 20, {accumulate: false});
|
|
58
59
|
assert.deepEqual(cdl.precomputedLatencies.size, 1);
|
|
59
60
|
assert.deepEqual(cdl.precomputedLatencies.get('internal.client.pageJMT'), 20);
|
|
60
61
|
});
|
|
61
62
|
|
|
62
63
|
it('should save latency correctly when accumulate is true', () => {
|
|
63
64
|
assert.deepEqual(cdl.precomputedLatencies.size, 0);
|
|
64
|
-
cdl.saveLatency('internal.client.pageJMT', 10, true);
|
|
65
|
+
cdl.saveLatency('internal.client.pageJMT', 10, {accumulate: true});
|
|
65
66
|
assert.deepEqual(cdl.precomputedLatencies.size, 1);
|
|
66
67
|
assert.deepEqual(cdl.precomputedLatencies.get('internal.client.pageJMT'), 10);
|
|
67
68
|
});
|
|
@@ -71,11 +72,31 @@ describe('internal-plugin-metrics', () => {
|
|
|
71
72
|
cdl.saveLatency('internal.client.pageJMT', 10);
|
|
72
73
|
assert.deepEqual(cdl.precomputedLatencies.size, 1);
|
|
73
74
|
assert.deepEqual(cdl.precomputedLatencies.get('internal.client.pageJMT'), 10);
|
|
74
|
-
cdl.saveLatency('internal.client.pageJMT', 10, true);
|
|
75
|
+
cdl.saveLatency('internal.client.pageJMT', 10, {accumulate: true});
|
|
75
76
|
assert.deepEqual(cdl.precomputedLatencies.size, 1);
|
|
76
77
|
assert.deepEqual(cdl.precomputedLatencies.get('internal.client.pageJMT'), 20);
|
|
77
78
|
});
|
|
78
79
|
|
|
80
|
+
it('accumulates when accumulate is passed as the legacy boolean argument', () => {
|
|
81
|
+
assert.deepEqual(cdl.precomputedLatencies.size, 0);
|
|
82
|
+
// @ts-ignore - legacy boolean third argument from older (untyped) SDK/plugin consumers
|
|
83
|
+
cdl.saveLatency('internal.client.pageJMT', 10, true);
|
|
84
|
+
// @ts-ignore - legacy boolean third argument from older (untyped) SDK/plugin consumers
|
|
85
|
+
cdl.saveLatency('internal.client.pageJMT', 15, true);
|
|
86
|
+
assert.deepEqual(cdl.precomputedLatencies.size, 1);
|
|
87
|
+
assert.deepEqual(cdl.precomputedLatencies.get('internal.client.pageJMT'), 25);
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
it('overwrites when the legacy boolean argument is false', () => {
|
|
91
|
+
assert.deepEqual(cdl.precomputedLatencies.size, 0);
|
|
92
|
+
// @ts-ignore - legacy boolean third argument from older (untyped) SDK/plugin consumers
|
|
93
|
+
cdl.saveLatency('internal.client.pageJMT', 10, false);
|
|
94
|
+
// @ts-ignore - legacy boolean third argument from older (untyped) SDK/plugin consumers
|
|
95
|
+
cdl.saveLatency('internal.client.pageJMT', 15, false);
|
|
96
|
+
assert.deepEqual(cdl.precomputedLatencies.size, 1);
|
|
97
|
+
assert.deepEqual(cdl.precomputedLatencies.get('internal.client.pageJMT'), 15);
|
|
98
|
+
});
|
|
99
|
+
|
|
79
100
|
it('should save only first timestamp correctly', () => {
|
|
80
101
|
assert.deepEqual(cdl.latencyTimestamps.size, 0);
|
|
81
102
|
cdl.saveFirstTimestampOnly('client.alert.displayed', 10);
|
|
@@ -108,11 +129,1174 @@ describe('internal-plugin-metrics', () => {
|
|
|
108
129
|
assert.deepEqual(cdl.latencyTimestamps.size, 2);
|
|
109
130
|
cdl.saveLatency('internal.api.fetch.intelligence.models', 42);
|
|
110
131
|
assert.deepEqual(cdl.precomputedLatencies.size, 1);
|
|
132
|
+
cdl.saveTimestamp({
|
|
133
|
+
key: 'internal.client.locus.sync.start',
|
|
134
|
+
value: 1,
|
|
135
|
+
options: {
|
|
136
|
+
meetingId: 'meeting-1',
|
|
137
|
+
dataSetName: 'main',
|
|
138
|
+
randomBackoffTime: 10,
|
|
139
|
+
trackingId: 'sync-tracking-id',
|
|
140
|
+
},
|
|
141
|
+
});
|
|
142
|
+
assert.deepEqual(cdl.meetingLatencies.size, 1);
|
|
111
143
|
|
|
112
144
|
cdl.clearTimestamps();
|
|
113
145
|
|
|
114
146
|
assert.deepEqual(cdl.latencyTimestamps.size, 0);
|
|
115
147
|
assert.deepEqual(cdl.precomputedLatencies.size, 0);
|
|
148
|
+
assert.deepEqual(cdl.meetingLatencies.size, 0);
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
describe('locus sync latencies', () => {
|
|
152
|
+
it('uses pending sync backoff latency when sync starts', () => {
|
|
153
|
+
cdl.saveLatency('internal.client.locus.sync.random.backoff', 10.4, {
|
|
154
|
+
meetingId: 'meeting-1',
|
|
155
|
+
dataSetName: 'main',
|
|
156
|
+
});
|
|
157
|
+
cdl.saveTimestamp({
|
|
158
|
+
key: 'internal.client.locus.sync.start',
|
|
159
|
+
value: 100,
|
|
160
|
+
options: {meetingId: 'meeting-1', dataSetName: 'main', trackingId: 'sync-tracking-id'},
|
|
161
|
+
});
|
|
162
|
+
cdl.saveTimestamp({
|
|
163
|
+
key: 'internal.client.locus.sync.request',
|
|
164
|
+
value: 110,
|
|
165
|
+
options: {meetingId: 'meeting-1', dataSetName: 'main', trackingId: 'sync-tracking-id'},
|
|
166
|
+
});
|
|
167
|
+
cdl.saveTimestamp({
|
|
168
|
+
key: 'internal.client.locus.sync.response',
|
|
169
|
+
value: 130,
|
|
170
|
+
options: {meetingId: 'meeting-1', dataSetName: 'main', trackingId: 'sync-tracking-id'},
|
|
171
|
+
});
|
|
172
|
+
cdl.saveTimestamp({
|
|
173
|
+
key: 'internal.client.locus.sync.message.received',
|
|
174
|
+
value: 140,
|
|
175
|
+
options: {meetingId: 'meeting-1', dataSetName: 'main', trackingId: 'sync-tracking-id'},
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
assert.deepEqual(cdl.getLocusSyncLatency('meeting-1', 'sync-tracking-id'), {
|
|
179
|
+
randomBackoffTime: 10,
|
|
180
|
+
hashtreePrepTime: 0,
|
|
181
|
+
hashtreeResponseTime: 0,
|
|
182
|
+
syncPrepTime: 10,
|
|
183
|
+
syncResponseTime: 20,
|
|
184
|
+
syncMessageReceiveTime: 30,
|
|
185
|
+
totalTime: 40,
|
|
186
|
+
});
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
it('calculates sync latency values from milestones', () => {
|
|
190
|
+
cdl.saveLatency('internal.client.locus.sync.random.backoff', 10.4, {
|
|
191
|
+
meetingId: 'meeting-1',
|
|
192
|
+
dataSetName: 'main',
|
|
193
|
+
});
|
|
194
|
+
cdl.saveTimestamp({
|
|
195
|
+
key: 'internal.client.locus.sync.start',
|
|
196
|
+
value: 100,
|
|
197
|
+
options: {
|
|
198
|
+
meetingId: 'meeting-1',
|
|
199
|
+
dataSetName: 'main',
|
|
200
|
+
trackingId: 'sync-tracking-id',
|
|
201
|
+
},
|
|
202
|
+
});
|
|
203
|
+
cdl.saveTimestamp({
|
|
204
|
+
key: 'internal.client.locus.hashtree.request',
|
|
205
|
+
value: 105,
|
|
206
|
+
options: {meetingId: 'meeting-1', dataSetName: 'main', trackingId: 'sync-tracking-id'},
|
|
207
|
+
});
|
|
208
|
+
cdl.saveTimestamp({
|
|
209
|
+
key: 'internal.client.locus.hashtree.response',
|
|
210
|
+
value: 125,
|
|
211
|
+
options: {meetingId: 'meeting-1', dataSetName: 'main', trackingId: 'sync-tracking-id'},
|
|
212
|
+
});
|
|
213
|
+
cdl.saveTimestamp({
|
|
214
|
+
key: 'internal.client.locus.sync.request',
|
|
215
|
+
value: 128,
|
|
216
|
+
options: {meetingId: 'meeting-1', dataSetName: 'main', trackingId: 'sync-tracking-id'},
|
|
217
|
+
});
|
|
218
|
+
cdl.saveTimestamp({
|
|
219
|
+
key: 'internal.client.locus.sync.response',
|
|
220
|
+
value: 143,
|
|
221
|
+
options: {meetingId: 'meeting-1', dataSetName: 'main', trackingId: 'sync-tracking-id'},
|
|
222
|
+
});
|
|
223
|
+
cdl.saveTimestamp({
|
|
224
|
+
key: 'internal.client.locus.sync.message.received',
|
|
225
|
+
value: 150,
|
|
226
|
+
options: {meetingId: 'meeting-1', dataSetName: 'main', trackingId: 'sync-tracking-id'},
|
|
227
|
+
});
|
|
228
|
+
|
|
229
|
+
assert.deepEqual(cdl.getLocusSyncLatency('meeting-1', 'sync-tracking-id'), {
|
|
230
|
+
randomBackoffTime: 10,
|
|
231
|
+
hashtreePrepTime: 5,
|
|
232
|
+
hashtreeResponseTime: 20,
|
|
233
|
+
syncPrepTime: 3,
|
|
234
|
+
syncResponseTime: 15,
|
|
235
|
+
syncMessageReceiveTime: 22,
|
|
236
|
+
totalTime: 50,
|
|
237
|
+
});
|
|
238
|
+
});
|
|
239
|
+
|
|
240
|
+
it('calculates sync latency values when hash tree request is skipped', () => {
|
|
241
|
+
cdl.saveTimestamp({
|
|
242
|
+
key: 'internal.client.locus.sync.start',
|
|
243
|
+
value: 100,
|
|
244
|
+
options: {
|
|
245
|
+
meetingId: 'meeting-1',
|
|
246
|
+
dataSetName: 'main',
|
|
247
|
+
randomBackoffTime: 0,
|
|
248
|
+
trackingId: 'sync-tracking-1',
|
|
249
|
+
},
|
|
250
|
+
});
|
|
251
|
+
cdl.saveTimestamp({
|
|
252
|
+
key: 'internal.client.locus.sync.request',
|
|
253
|
+
value: 110,
|
|
254
|
+
options: {
|
|
255
|
+
meetingId: 'meeting-1',
|
|
256
|
+
dataSetName: 'main',
|
|
257
|
+
trackingId: 'sync-tracking-1',
|
|
258
|
+
},
|
|
259
|
+
});
|
|
260
|
+
cdl.saveTimestamp({
|
|
261
|
+
key: 'internal.client.locus.sync.response',
|
|
262
|
+
value: 130,
|
|
263
|
+
options: {meetingId: 'meeting-1', dataSetName: 'main', trackingId: 'sync-tracking-1'},
|
|
264
|
+
});
|
|
265
|
+
cdl.saveTimestamp({
|
|
266
|
+
key: 'internal.client.locus.sync.message.received',
|
|
267
|
+
value: 140,
|
|
268
|
+
options: {meetingId: 'meeting-1', dataSetName: 'main', trackingId: 'sync-tracking-1'},
|
|
269
|
+
});
|
|
270
|
+
|
|
271
|
+
assert.deepEqual(cdl.getLocusSyncLatency('meeting-1', 'sync-tracking-1'), {
|
|
272
|
+
randomBackoffTime: 0,
|
|
273
|
+
hashtreePrepTime: 0,
|
|
274
|
+
hashtreeResponseTime: 0,
|
|
275
|
+
syncPrepTime: 10,
|
|
276
|
+
syncResponseTime: 20,
|
|
277
|
+
syncMessageReceiveTime: 30,
|
|
278
|
+
totalTime: 40,
|
|
279
|
+
});
|
|
280
|
+
});
|
|
281
|
+
|
|
282
|
+
it('associates sync response tracking id and completes the matching meeting record', () => {
|
|
283
|
+
clock.setSystemTime(150);
|
|
284
|
+
|
|
285
|
+
try {
|
|
286
|
+
cdl.saveTimestamp({
|
|
287
|
+
key: 'internal.client.locus.sync.start',
|
|
288
|
+
value: 100,
|
|
289
|
+
options: {
|
|
290
|
+
meetingId: 'meeting-1',
|
|
291
|
+
dataSetName: 'main',
|
|
292
|
+
randomBackoffTime: 0,
|
|
293
|
+
trackingId: 'our-sync-tracking-id',
|
|
294
|
+
},
|
|
295
|
+
});
|
|
296
|
+
cdl.saveTimestamp({
|
|
297
|
+
key: 'internal.client.locus.sync.request',
|
|
298
|
+
value: 110,
|
|
299
|
+
options: {
|
|
300
|
+
meetingId: 'meeting-1',
|
|
301
|
+
dataSetName: 'main',
|
|
302
|
+
trackingId: 'our-sync-tracking-id',
|
|
303
|
+
},
|
|
304
|
+
});
|
|
305
|
+
cdl.saveTimestamp({
|
|
306
|
+
key: 'internal.client.locus.sync.response',
|
|
307
|
+
value: 130,
|
|
308
|
+
options: {
|
|
309
|
+
meetingId: 'meeting-1',
|
|
310
|
+
dataSetName: 'main',
|
|
311
|
+
trackingId: 'our-sync-tracking-id',
|
|
312
|
+
},
|
|
313
|
+
});
|
|
314
|
+
// the LLM state-update message that gates the metric arrives for this sync
|
|
315
|
+
cdl.saveTimestamp({
|
|
316
|
+
key: 'internal.client.locus.sync.message.received',
|
|
317
|
+
value: 150,
|
|
318
|
+
options: {
|
|
319
|
+
meetingId: 'meeting-1',
|
|
320
|
+
dataSetName: 'main',
|
|
321
|
+
trackingId: 'our-sync-tracking-id',
|
|
322
|
+
},
|
|
323
|
+
});
|
|
324
|
+
cdl.saveLatency('internal.client.locus.sync.random.backoff', 99, {
|
|
325
|
+
meetingId: 'meeting-1',
|
|
326
|
+
dataSetName: 'main',
|
|
327
|
+
});
|
|
328
|
+
|
|
329
|
+
// eager completion: both the /sync response and the LLM message are present
|
|
330
|
+
assert.deepEqual(cdl.completeLocusSyncLatency('meeting-1', 'our-sync-tracking-id'), {
|
|
331
|
+
dataSet: 'main',
|
|
332
|
+
syncLatency: {
|
|
333
|
+
randomBackoffTime: 0,
|
|
334
|
+
hashtreePrepTime: 0,
|
|
335
|
+
hashtreeResponseTime: 0,
|
|
336
|
+
syncPrepTime: 10,
|
|
337
|
+
syncResponseTime: 20,
|
|
338
|
+
syncMessageReceiveTime: 40,
|
|
339
|
+
totalTime: 50,
|
|
340
|
+
},
|
|
341
|
+
});
|
|
342
|
+
// completing the metric removes the matching record, leaving only the pending
|
|
343
|
+
// backoff record created above for the next sync to consume
|
|
344
|
+
assert.lengthOf(cdl.meetingLatencies.get('meeting-1'), 1);
|
|
345
|
+
|
|
346
|
+
cdl.saveTimestamp({
|
|
347
|
+
key: 'internal.client.locus.sync.start',
|
|
348
|
+
value: 200,
|
|
349
|
+
options: {
|
|
350
|
+
meetingId: 'meeting-1',
|
|
351
|
+
dataSetName: 'main',
|
|
352
|
+
trackingId: 'next-sync-tracking-id',
|
|
353
|
+
},
|
|
354
|
+
});
|
|
355
|
+
assert.deepInclude(cdl.meetingLatencies.get('meeting-1'), {
|
|
356
|
+
locusSync: {
|
|
357
|
+
meetingId: 'meeting-1',
|
|
358
|
+
dataSetName: 'main',
|
|
359
|
+
randomBackoffTime: 99,
|
|
360
|
+
trackingId: 'next-sync-tracking-id',
|
|
361
|
+
syncStart: 200,
|
|
362
|
+
},
|
|
363
|
+
});
|
|
364
|
+
} finally {
|
|
365
|
+
clock.setSystemTime(now.getTime());
|
|
366
|
+
}
|
|
367
|
+
});
|
|
368
|
+
|
|
369
|
+
it('does not bind message.received when tracking id does not match any record', () => {
|
|
370
|
+
clock.setSystemTime(500);
|
|
371
|
+
|
|
372
|
+
try {
|
|
373
|
+
cdl.saveTimestamp({
|
|
374
|
+
key: 'internal.client.locus.sync.start',
|
|
375
|
+
value: 100,
|
|
376
|
+
options: {
|
|
377
|
+
meetingId: 'meeting-1',
|
|
378
|
+
dataSetName: 'main',
|
|
379
|
+
randomBackoffTime: 0,
|
|
380
|
+
trackingId: 'sync-tracking-id',
|
|
381
|
+
},
|
|
382
|
+
});
|
|
383
|
+
cdl.saveTimestamp({
|
|
384
|
+
key: 'internal.client.locus.sync.request',
|
|
385
|
+
value: 110,
|
|
386
|
+
options: {
|
|
387
|
+
meetingId: 'meeting-1',
|
|
388
|
+
dataSetName: 'main',
|
|
389
|
+
trackingId: 'sync-tracking-id',
|
|
390
|
+
},
|
|
391
|
+
});
|
|
392
|
+
cdl.saveTimestamp({
|
|
393
|
+
key: 'internal.client.locus.sync.response',
|
|
394
|
+
value: 130,
|
|
395
|
+
options: {
|
|
396
|
+
meetingId: 'meeting-1',
|
|
397
|
+
dataSetName: 'main',
|
|
398
|
+
trackingId: 'sync-tracking-id',
|
|
399
|
+
},
|
|
400
|
+
});
|
|
401
|
+
cdl.saveTimestamp({
|
|
402
|
+
key: 'internal.client.locus.sync.message.received',
|
|
403
|
+
value: 140,
|
|
404
|
+
options: {
|
|
405
|
+
meetingId: 'meeting-1',
|
|
406
|
+
dataSetName: 'main',
|
|
407
|
+
trackingId: 'llm-envelope-id',
|
|
408
|
+
},
|
|
409
|
+
});
|
|
410
|
+
|
|
411
|
+
assert.isUndefined(cdl.completeLocusSyncLatency('meeting-1', 'llm-envelope-id'));
|
|
412
|
+
assert.isUndefined(cdl.meetingLatencies.get('meeting-1')?.[0].locusSync.messageReceived);
|
|
413
|
+
} finally {
|
|
414
|
+
clock.setSystemTime(now.getTime());
|
|
415
|
+
}
|
|
416
|
+
});
|
|
417
|
+
|
|
418
|
+
it('does not allow totalTime to drop below sync response duration when message.received is stale', () => {
|
|
419
|
+
cdl.saveTimestamp({
|
|
420
|
+
key: 'internal.client.locus.sync.start',
|
|
421
|
+
value: 100,
|
|
422
|
+
options: {
|
|
423
|
+
meetingId: 'meeting-1',
|
|
424
|
+
dataSetName: 'main',
|
|
425
|
+
randomBackoffTime: 0,
|
|
426
|
+
trackingId: 'sync-tracking-id',
|
|
427
|
+
},
|
|
428
|
+
});
|
|
429
|
+
cdl.saveTimestamp({
|
|
430
|
+
key: 'internal.client.locus.sync.request',
|
|
431
|
+
value: 101,
|
|
432
|
+
options: {
|
|
433
|
+
meetingId: 'meeting-1',
|
|
434
|
+
dataSetName: 'main',
|
|
435
|
+
trackingId: 'sync-tracking-id',
|
|
436
|
+
},
|
|
437
|
+
});
|
|
438
|
+
cdl.saveTimestamp({
|
|
439
|
+
key: 'internal.client.locus.sync.response',
|
|
440
|
+
value: 475,
|
|
441
|
+
options: {
|
|
442
|
+
meetingId: 'meeting-1',
|
|
443
|
+
dataSetName: 'main',
|
|
444
|
+
trackingId: 'sync-tracking-id',
|
|
445
|
+
},
|
|
446
|
+
});
|
|
447
|
+
cdl.saveTimestamp({
|
|
448
|
+
key: 'internal.client.locus.sync.message.received',
|
|
449
|
+
value: 90,
|
|
450
|
+
options: {
|
|
451
|
+
meetingId: 'meeting-1',
|
|
452
|
+
dataSetName: 'main',
|
|
453
|
+
trackingId: 'sync-tracking-id',
|
|
454
|
+
},
|
|
455
|
+
});
|
|
456
|
+
|
|
457
|
+
assert.deepEqual(cdl.completeLocusSyncLatency('meeting-1', 'sync-tracking-id'), {
|
|
458
|
+
dataSet: 'main',
|
|
459
|
+
syncLatency: {
|
|
460
|
+
randomBackoffTime: 0,
|
|
461
|
+
hashtreePrepTime: 0,
|
|
462
|
+
hashtreeResponseTime: 0,
|
|
463
|
+
syncPrepTime: 1,
|
|
464
|
+
syncResponseTime: 374,
|
|
465
|
+
syncMessageReceiveTime: 0,
|
|
466
|
+
totalTime: 375,
|
|
467
|
+
},
|
|
468
|
+
});
|
|
469
|
+
});
|
|
470
|
+
|
|
471
|
+
it('drops and consumes a completed sync latency record when a segment exceeds the clock skew threshold', () => {
|
|
472
|
+
cdl.saveTimestamp({
|
|
473
|
+
key: 'internal.client.locus.sync.start',
|
|
474
|
+
value: 100,
|
|
475
|
+
options: {
|
|
476
|
+
meetingId: 'meeting-1',
|
|
477
|
+
dataSetName: 'main',
|
|
478
|
+
trackingId: 'sync-tracking-id',
|
|
479
|
+
},
|
|
480
|
+
});
|
|
481
|
+
cdl.saveTimestamp({
|
|
482
|
+
key: 'internal.client.locus.sync.request',
|
|
483
|
+
value: 110,
|
|
484
|
+
options: {meetingId: 'meeting-1', dataSetName: 'main', trackingId: 'sync-tracking-id'},
|
|
485
|
+
});
|
|
486
|
+
cdl.saveTimestamp({
|
|
487
|
+
key: 'internal.client.locus.sync.response',
|
|
488
|
+
value: 600111,
|
|
489
|
+
options: {meetingId: 'meeting-1', dataSetName: 'main', trackingId: 'sync-tracking-id'},
|
|
490
|
+
});
|
|
491
|
+
cdl.saveTimestamp({
|
|
492
|
+
key: 'internal.client.locus.sync.message.received',
|
|
493
|
+
value: 600112,
|
|
494
|
+
options: {meetingId: 'meeting-1', dataSetName: 'main', trackingId: 'sync-tracking-id'},
|
|
495
|
+
});
|
|
496
|
+
|
|
497
|
+
assert.isUndefined(cdl.completeLocusSyncLatency('meeting-1', 'sync-tracking-id'));
|
|
498
|
+
assert.isFalse(cdl.meetingLatencies.has('meeting-1'));
|
|
499
|
+
});
|
|
500
|
+
|
|
501
|
+
it('allows a completed sync latency record when the largest segment equals the clock skew threshold', () => {
|
|
502
|
+
cdl.saveTimestamp({
|
|
503
|
+
key: 'internal.client.locus.sync.start',
|
|
504
|
+
value: 100,
|
|
505
|
+
options: {
|
|
506
|
+
meetingId: 'meeting-1',
|
|
507
|
+
dataSetName: 'main',
|
|
508
|
+
trackingId: 'sync-tracking-id',
|
|
509
|
+
},
|
|
510
|
+
});
|
|
511
|
+
cdl.saveTimestamp({
|
|
512
|
+
key: 'internal.client.locus.sync.request',
|
|
513
|
+
value: 110,
|
|
514
|
+
options: {meetingId: 'meeting-1', dataSetName: 'main', trackingId: 'sync-tracking-id'},
|
|
515
|
+
});
|
|
516
|
+
cdl.saveTimestamp({
|
|
517
|
+
key: 'internal.client.locus.sync.response',
|
|
518
|
+
value: 600100,
|
|
519
|
+
options: {meetingId: 'meeting-1', dataSetName: 'main', trackingId: 'sync-tracking-id'},
|
|
520
|
+
});
|
|
521
|
+
cdl.saveTimestamp({
|
|
522
|
+
key: 'internal.client.locus.sync.message.received',
|
|
523
|
+
value: 600100,
|
|
524
|
+
options: {meetingId: 'meeting-1', dataSetName: 'main', trackingId: 'sync-tracking-id'},
|
|
525
|
+
});
|
|
526
|
+
|
|
527
|
+
assert.deepEqual(cdl.completeLocusSyncLatency('meeting-1', 'sync-tracking-id'), {
|
|
528
|
+
dataSet: 'main',
|
|
529
|
+
syncLatency: {
|
|
530
|
+
randomBackoffTime: 0,
|
|
531
|
+
hashtreePrepTime: 0,
|
|
532
|
+
hashtreeResponseTime: 0,
|
|
533
|
+
syncPrepTime: 10,
|
|
534
|
+
syncResponseTime: 599990,
|
|
535
|
+
syncMessageReceiveTime: 599990,
|
|
536
|
+
totalTime: 600000,
|
|
537
|
+
},
|
|
538
|
+
});
|
|
539
|
+
assert.isFalse(cdl.meetingLatencies.has('meeting-1'));
|
|
540
|
+
});
|
|
541
|
+
|
|
542
|
+
it('matches exact record by tracking id on first pass', () => {
|
|
543
|
+
clock.setSystemTime(300);
|
|
544
|
+
|
|
545
|
+
try {
|
|
546
|
+
cdl.saveTimestamp({
|
|
547
|
+
key: 'internal.client.locus.sync.start',
|
|
548
|
+
value: 100,
|
|
549
|
+
options: {
|
|
550
|
+
meetingId: 'meeting-1',
|
|
551
|
+
dataSetName: 'main',
|
|
552
|
+
randomBackoffTime: 0,
|
|
553
|
+
trackingId: 'sync-tracking-1',
|
|
554
|
+
},
|
|
555
|
+
});
|
|
556
|
+
cdl.saveTimestamp({
|
|
557
|
+
key: 'internal.client.locus.sync.request',
|
|
558
|
+
value: 110,
|
|
559
|
+
options: {
|
|
560
|
+
meetingId: 'meeting-1',
|
|
561
|
+
dataSetName: 'main',
|
|
562
|
+
trackingId: 'sync-tracking-1',
|
|
563
|
+
},
|
|
564
|
+
});
|
|
565
|
+
cdl.saveTimestamp({
|
|
566
|
+
key: 'internal.client.locus.sync.response',
|
|
567
|
+
value: 130,
|
|
568
|
+
options: {
|
|
569
|
+
meetingId: 'meeting-1',
|
|
570
|
+
dataSetName: 'main',
|
|
571
|
+
trackingId: 'sync-tracking-1',
|
|
572
|
+
},
|
|
573
|
+
});
|
|
574
|
+
|
|
575
|
+
cdl.saveTimestamp({
|
|
576
|
+
key: 'internal.client.locus.sync.start',
|
|
577
|
+
value: 200,
|
|
578
|
+
options: {
|
|
579
|
+
meetingId: 'meeting-1',
|
|
580
|
+
dataSetName: 'main',
|
|
581
|
+
randomBackoffTime: 0,
|
|
582
|
+
trackingId: 'sync-tracking-2',
|
|
583
|
+
},
|
|
584
|
+
});
|
|
585
|
+
cdl.saveTimestamp({
|
|
586
|
+
key: 'internal.client.locus.sync.request',
|
|
587
|
+
value: 210,
|
|
588
|
+
options: {
|
|
589
|
+
meetingId: 'meeting-1',
|
|
590
|
+
dataSetName: 'main',
|
|
591
|
+
trackingId: 'sync-tracking-2',
|
|
592
|
+
},
|
|
593
|
+
});
|
|
594
|
+
cdl.saveTimestamp({
|
|
595
|
+
key: 'internal.client.locus.sync.response',
|
|
596
|
+
value: 230,
|
|
597
|
+
options: {
|
|
598
|
+
meetingId: 'meeting-1',
|
|
599
|
+
dataSetName: 'main',
|
|
600
|
+
trackingId: 'sync-tracking-2',
|
|
601
|
+
},
|
|
602
|
+
});
|
|
603
|
+
cdl.saveTimestamp({
|
|
604
|
+
key: 'internal.client.locus.sync.message.received',
|
|
605
|
+
value: 240,
|
|
606
|
+
options: {
|
|
607
|
+
meetingId: 'meeting-1',
|
|
608
|
+
dataSetName: 'main',
|
|
609
|
+
trackingId: 'sync-tracking-2',
|
|
610
|
+
},
|
|
611
|
+
});
|
|
612
|
+
|
|
613
|
+
assert.deepEqual(cdl.completeLocusSyncLatency('meeting-1', 'sync-tracking-2'), {
|
|
614
|
+
dataSet: 'main',
|
|
615
|
+
syncLatency: {
|
|
616
|
+
randomBackoffTime: 0,
|
|
617
|
+
hashtreePrepTime: 0,
|
|
618
|
+
hashtreeResponseTime: 0,
|
|
619
|
+
syncPrepTime: 10,
|
|
620
|
+
syncResponseTime: 20,
|
|
621
|
+
syncMessageReceiveTime: 30,
|
|
622
|
+
totalTime: 40,
|
|
623
|
+
},
|
|
624
|
+
});
|
|
625
|
+
} finally {
|
|
626
|
+
clock.setSystemTime(now.getTime());
|
|
627
|
+
}
|
|
628
|
+
});
|
|
629
|
+
|
|
630
|
+
it('does not bind message.received when tracking id does not match any record', () => {
|
|
631
|
+
cdl.saveTimestamp({
|
|
632
|
+
key: 'internal.client.locus.sync.start',
|
|
633
|
+
value: 100,
|
|
634
|
+
options: {
|
|
635
|
+
meetingId: 'meeting-1',
|
|
636
|
+
dataSetName: 'main',
|
|
637
|
+
randomBackoffTime: 0,
|
|
638
|
+
trackingId: 'sync-tracking-1',
|
|
639
|
+
},
|
|
640
|
+
});
|
|
641
|
+
cdl.saveTimestamp({
|
|
642
|
+
key: 'internal.client.locus.sync.request',
|
|
643
|
+
value: 110,
|
|
644
|
+
options: {meetingId: 'meeting-1', dataSetName: 'main', trackingId: 'sync-tracking-1'},
|
|
645
|
+
});
|
|
646
|
+
cdl.saveTimestamp({
|
|
647
|
+
key: 'internal.client.locus.sync.response',
|
|
648
|
+
value: 130,
|
|
649
|
+
options: {meetingId: 'meeting-1', dataSetName: 'main', trackingId: 'sync-tracking-1'},
|
|
650
|
+
});
|
|
651
|
+
|
|
652
|
+
cdl.saveTimestamp({
|
|
653
|
+
key: 'internal.client.locus.sync.start',
|
|
654
|
+
value: 200,
|
|
655
|
+
options: {
|
|
656
|
+
meetingId: 'meeting-1',
|
|
657
|
+
dataSetName: 'main',
|
|
658
|
+
randomBackoffTime: 0,
|
|
659
|
+
trackingId: 'sync-tracking-2',
|
|
660
|
+
},
|
|
661
|
+
});
|
|
662
|
+
cdl.saveTimestamp({
|
|
663
|
+
key: 'internal.client.locus.sync.request',
|
|
664
|
+
value: 210,
|
|
665
|
+
options: {
|
|
666
|
+
meetingId: 'meeting-1',
|
|
667
|
+
dataSetName: 'main',
|
|
668
|
+
trackingId: 'sync-tracking-2',
|
|
669
|
+
},
|
|
670
|
+
});
|
|
671
|
+
cdl.saveTimestamp({
|
|
672
|
+
key: 'internal.client.locus.sync.response',
|
|
673
|
+
value: 230,
|
|
674
|
+
options: {meetingId: 'meeting-1', dataSetName: 'main', trackingId: 'sync-tracking-2'},
|
|
675
|
+
});
|
|
676
|
+
|
|
677
|
+
cdl.saveTimestamp({
|
|
678
|
+
key: 'internal.client.locus.sync.message.received',
|
|
679
|
+
value: 120,
|
|
680
|
+
options: {
|
|
681
|
+
meetingId: 'meeting-1',
|
|
682
|
+
dataSetName: 'main',
|
|
683
|
+
trackingId: 'llm-unknown-id',
|
|
684
|
+
},
|
|
685
|
+
});
|
|
686
|
+
|
|
687
|
+
const records = cdl.meetingLatencies.get('meeting-1');
|
|
688
|
+
|
|
689
|
+
assert.isDefined(records);
|
|
690
|
+
assert.lengthOf(records!, 2);
|
|
691
|
+
assert.isUndefined(records![0].locusSync.messageReceived);
|
|
692
|
+
assert.isUndefined(records![1].locusSync.messageReceived);
|
|
693
|
+
});
|
|
694
|
+
|
|
695
|
+
it('binds message.received when the tracking id matches the only record', () => {
|
|
696
|
+
cdl.saveTimestamp({
|
|
697
|
+
key: 'internal.client.locus.sync.start',
|
|
698
|
+
value: 100,
|
|
699
|
+
options: {
|
|
700
|
+
meetingId: 'meeting-1',
|
|
701
|
+
dataSetName: 'main',
|
|
702
|
+
randomBackoffTime: 0,
|
|
703
|
+
trackingId: 'sync-tracking-id',
|
|
704
|
+
},
|
|
705
|
+
});
|
|
706
|
+
cdl.saveTimestamp({
|
|
707
|
+
key: 'internal.client.locus.sync.request',
|
|
708
|
+
value: 110,
|
|
709
|
+
options: {
|
|
710
|
+
meetingId: 'meeting-1',
|
|
711
|
+
dataSetName: 'main',
|
|
712
|
+
trackingId: 'sync-tracking-id',
|
|
713
|
+
},
|
|
714
|
+
});
|
|
715
|
+
cdl.saveTimestamp({
|
|
716
|
+
key: 'internal.client.locus.sync.response',
|
|
717
|
+
value: 130,
|
|
718
|
+
options: {meetingId: 'meeting-1', dataSetName: 'main', trackingId: 'sync-tracking-id'},
|
|
719
|
+
});
|
|
720
|
+
|
|
721
|
+
cdl.saveTimestamp({
|
|
722
|
+
key: 'internal.client.locus.sync.message.received',
|
|
723
|
+
value: 140,
|
|
724
|
+
options: {
|
|
725
|
+
meetingId: 'meeting-1',
|
|
726
|
+
dataSetName: 'main',
|
|
727
|
+
trackingId: 'sync-tracking-id',
|
|
728
|
+
},
|
|
729
|
+
});
|
|
730
|
+
|
|
731
|
+
const records = cdl.meetingLatencies.get('meeting-1');
|
|
732
|
+
|
|
733
|
+
assert.isDefined(records);
|
|
734
|
+
assert.lengthOf(records!, 1);
|
|
735
|
+
assert.equal(records![0].locusSync.messageReceived, 140);
|
|
736
|
+
});
|
|
737
|
+
|
|
738
|
+
it('returns undefined when the tracking id does not match', () => {
|
|
739
|
+
clock.setSystemTime(150);
|
|
740
|
+
|
|
741
|
+
try {
|
|
742
|
+
cdl.saveTimestamp({
|
|
743
|
+
key: 'internal.client.locus.sync.start',
|
|
744
|
+
value: 100,
|
|
745
|
+
options: {
|
|
746
|
+
meetingId: 'meeting-1',
|
|
747
|
+
dataSetName: 'main',
|
|
748
|
+
randomBackoffTime: 0,
|
|
749
|
+
trackingId: 'our-sync-tracking-id',
|
|
750
|
+
},
|
|
751
|
+
});
|
|
752
|
+
cdl.saveTimestamp({
|
|
753
|
+
key: 'internal.client.locus.sync.request',
|
|
754
|
+
value: 110,
|
|
755
|
+
options: {
|
|
756
|
+
meetingId: 'meeting-1',
|
|
757
|
+
dataSetName: 'main',
|
|
758
|
+
trackingId: 'our-sync-tracking-id',
|
|
759
|
+
},
|
|
760
|
+
});
|
|
761
|
+
cdl.saveTimestamp({
|
|
762
|
+
key: 'internal.client.locus.sync.response',
|
|
763
|
+
value: 130,
|
|
764
|
+
options: {
|
|
765
|
+
meetingId: 'meeting-1',
|
|
766
|
+
dataSetName: 'main',
|
|
767
|
+
trackingId: 'our-sync-tracking-id',
|
|
768
|
+
},
|
|
769
|
+
});
|
|
770
|
+
|
|
771
|
+
assert.isUndefined(cdl.completeLocusSyncLatency('meeting-1', 'llm-envelope-tracking-id'));
|
|
772
|
+
} finally {
|
|
773
|
+
clock.setSystemTime(now.getTime());
|
|
774
|
+
}
|
|
775
|
+
});
|
|
776
|
+
|
|
777
|
+
it('does not clean up older never-completed record for the same dataset when newer sync completes', () => {
|
|
778
|
+
// first sync: all sync milestones recorded, but its completing LLM event never arrives
|
|
779
|
+
cdl.saveTimestamp({
|
|
780
|
+
key: 'internal.client.locus.sync.start',
|
|
781
|
+
value: 100,
|
|
782
|
+
options: {
|
|
783
|
+
meetingId: 'meeting-1',
|
|
784
|
+
dataSetName: 'main',
|
|
785
|
+
randomBackoffTime: 0,
|
|
786
|
+
trackingId: 'sync-tracking-1',
|
|
787
|
+
},
|
|
788
|
+
});
|
|
789
|
+
cdl.saveTimestamp({
|
|
790
|
+
key: 'internal.client.locus.sync.request',
|
|
791
|
+
value: 110,
|
|
792
|
+
options: {meetingId: 'meeting-1', dataSetName: 'main', trackingId: 'sync-tracking-1'},
|
|
793
|
+
});
|
|
794
|
+
cdl.saveTimestamp({
|
|
795
|
+
key: 'internal.client.locus.sync.response',
|
|
796
|
+
value: 130,
|
|
797
|
+
options: {meetingId: 'meeting-1', dataSetName: 'main', trackingId: 'sync-tracking-1'},
|
|
798
|
+
});
|
|
799
|
+
|
|
800
|
+
// a second sync for the same dataset starts before the first one completed.
|
|
801
|
+
// because the first record already has syncStart set, it is not reused and a
|
|
802
|
+
// brand new record is created for the second sync
|
|
803
|
+
cdl.saveTimestamp({
|
|
804
|
+
key: 'internal.client.locus.sync.start',
|
|
805
|
+
value: 200,
|
|
806
|
+
options: {
|
|
807
|
+
meetingId: 'meeting-1',
|
|
808
|
+
dataSetName: 'main',
|
|
809
|
+
randomBackoffTime: 0,
|
|
810
|
+
trackingId: 'sync-tracking-2',
|
|
811
|
+
},
|
|
812
|
+
});
|
|
813
|
+
cdl.saveTimestamp({
|
|
814
|
+
key: 'internal.client.locus.sync.request',
|
|
815
|
+
value: 210,
|
|
816
|
+
options: {meetingId: 'meeting-1', dataSetName: 'main', trackingId: 'sync-tracking-2'},
|
|
817
|
+
});
|
|
818
|
+
cdl.saveTimestamp({
|
|
819
|
+
key: 'internal.client.locus.sync.response',
|
|
820
|
+
value: 230,
|
|
821
|
+
options: {meetingId: 'meeting-1', dataSetName: 'main', trackingId: 'sync-tracking-2'},
|
|
822
|
+
});
|
|
823
|
+
cdl.saveTimestamp({
|
|
824
|
+
key: 'internal.client.locus.sync.message.received',
|
|
825
|
+
value: 240,
|
|
826
|
+
options: {meetingId: 'meeting-1', dataSetName: 'main', trackingId: 'sync-tracking-2'},
|
|
827
|
+
});
|
|
828
|
+
|
|
829
|
+
// both records exist before completion
|
|
830
|
+
assert.lengthOf(cdl.meetingLatencies.get('meeting-1')!, 2);
|
|
831
|
+
|
|
832
|
+
// completing the second sync removes only its own record; the older pending record is left
|
|
833
|
+
// in place because a late LLM message could still complete it (stale cleanup is handled by
|
|
834
|
+
// the TTL / capacity pruning, not by completion).
|
|
835
|
+
const completed = cdl.completeLocusSyncLatency('meeting-1', 'sync-tracking-2');
|
|
836
|
+
|
|
837
|
+
assert.isDefined(completed);
|
|
838
|
+
assert.equal(completed!.dataSet, 'main');
|
|
839
|
+
|
|
840
|
+
const remaining = cdl.meetingLatencies.get('meeting-1');
|
|
841
|
+
|
|
842
|
+
assert.isDefined(remaining);
|
|
843
|
+
assert.lengthOf(remaining!, 1);
|
|
844
|
+
assert.equal(remaining![0].locusSync.trackingId, 'sync-tracking-1');
|
|
845
|
+
});
|
|
846
|
+
|
|
847
|
+
it('prunes an incomplete record once it is older than the pending TTL', () => {
|
|
848
|
+
// an incomplete sync record that never received its LLM message
|
|
849
|
+
cdl.saveTimestamp({
|
|
850
|
+
key: 'internal.client.locus.sync.start',
|
|
851
|
+
value: 100,
|
|
852
|
+
options: {
|
|
853
|
+
meetingId: 'meeting-1',
|
|
854
|
+
dataSetName: 'main',
|
|
855
|
+
trackingId: 'stale-tracking-id',
|
|
856
|
+
},
|
|
857
|
+
});
|
|
858
|
+
|
|
859
|
+
// a brand new sync for the same dataset starts more than the TTL later
|
|
860
|
+
cdl.saveTimestamp({
|
|
861
|
+
key: 'internal.client.locus.sync.start',
|
|
862
|
+
value: 100 + 5 * 60 * 1000 + 1,
|
|
863
|
+
options: {
|
|
864
|
+
meetingId: 'meeting-1',
|
|
865
|
+
dataSetName: 'main',
|
|
866
|
+
trackingId: 'fresh-tracking-id',
|
|
867
|
+
},
|
|
868
|
+
});
|
|
869
|
+
|
|
870
|
+
const records = cdl.meetingLatencies.get('meeting-1');
|
|
871
|
+
|
|
872
|
+
assert.isDefined(records);
|
|
873
|
+
assert.lengthOf(records!, 1);
|
|
874
|
+
assert.equal(records![0].locusSync.trackingId, 'fresh-tracking-id');
|
|
875
|
+
});
|
|
876
|
+
|
|
877
|
+
it('keeps an incomplete record that is still within the pending TTL', () => {
|
|
878
|
+
cdl.saveTimestamp({
|
|
879
|
+
key: 'internal.client.locus.sync.start',
|
|
880
|
+
value: 100,
|
|
881
|
+
options: {
|
|
882
|
+
meetingId: 'meeting-1',
|
|
883
|
+
dataSetName: 'main',
|
|
884
|
+
trackingId: 'pending-tracking-id',
|
|
885
|
+
},
|
|
886
|
+
});
|
|
887
|
+
|
|
888
|
+
// a new sync for the same dataset starts well within the TTL window
|
|
889
|
+
cdl.saveTimestamp({
|
|
890
|
+
key: 'internal.client.locus.sync.start',
|
|
891
|
+
value: 100 + 1000,
|
|
892
|
+
options: {
|
|
893
|
+
meetingId: 'meeting-1',
|
|
894
|
+
dataSetName: 'main',
|
|
895
|
+
trackingId: 'fresh-tracking-id',
|
|
896
|
+
},
|
|
897
|
+
});
|
|
898
|
+
|
|
899
|
+
const records = cdl.meetingLatencies.get('meeting-1');
|
|
900
|
+
|
|
901
|
+
assert.isDefined(records);
|
|
902
|
+
assert.lengthOf(records!, 2);
|
|
903
|
+
assert.equal(records![0].locusSync.trackingId, 'pending-tracking-id');
|
|
904
|
+
assert.equal(records![1].locusSync.trackingId, 'fresh-tracking-id');
|
|
905
|
+
});
|
|
906
|
+
|
|
907
|
+
it('does not prune incomplete records from a different dataset', () => {
|
|
908
|
+
cdl.saveTimestamp({
|
|
909
|
+
key: 'internal.client.locus.sync.start',
|
|
910
|
+
value: 100,
|
|
911
|
+
options: {
|
|
912
|
+
meetingId: 'meeting-1',
|
|
913
|
+
dataSetName: 'other',
|
|
914
|
+
trackingId: 'other-tracking-id',
|
|
915
|
+
},
|
|
916
|
+
});
|
|
917
|
+
|
|
918
|
+
// a much later sync for a different dataset must not touch the "other" record
|
|
919
|
+
cdl.saveTimestamp({
|
|
920
|
+
key: 'internal.client.locus.sync.start',
|
|
921
|
+
value: 100 + 5 * 60 * 1000 + 1,
|
|
922
|
+
options: {
|
|
923
|
+
meetingId: 'meeting-1',
|
|
924
|
+
dataSetName: 'main',
|
|
925
|
+
trackingId: 'main-tracking-id',
|
|
926
|
+
},
|
|
927
|
+
});
|
|
928
|
+
|
|
929
|
+
const records = cdl.meetingLatencies.get('meeting-1');
|
|
930
|
+
|
|
931
|
+
assert.isDefined(records);
|
|
932
|
+
assert.lengthOf(records!, 2);
|
|
933
|
+
assert.equal(records![0].locusSync.trackingId, 'other-tracking-id');
|
|
934
|
+
assert.equal(records![1].locusSync.trackingId, 'main-tracking-id');
|
|
935
|
+
});
|
|
936
|
+
|
|
937
|
+
it('caps the number of incomplete records kept per dataset', () => {
|
|
938
|
+
// create more incomplete records than the per-dataset cap, all within the TTL window
|
|
939
|
+
for (let i = 0; i <= 20; i += 1) {
|
|
940
|
+
cdl.saveTimestamp({
|
|
941
|
+
key: 'internal.client.locus.sync.start',
|
|
942
|
+
value: 100 + i,
|
|
943
|
+
options: {
|
|
944
|
+
meetingId: 'meeting-1',
|
|
945
|
+
dataSetName: 'main',
|
|
946
|
+
trackingId: `sync-tracking-${i}`,
|
|
947
|
+
},
|
|
948
|
+
});
|
|
949
|
+
}
|
|
950
|
+
|
|
951
|
+
const records = cdl.meetingLatencies.get('meeting-1');
|
|
952
|
+
const trackingIds = records!.map(({locusSync}) => locusSync.trackingId);
|
|
953
|
+
|
|
954
|
+
assert.isDefined(records);
|
|
955
|
+
assert.lengthOf(records!, 20);
|
|
956
|
+
// the oldest record is dropped, the newest is kept
|
|
957
|
+
assert.notInclude(trackingIds, 'sync-tracking-0');
|
|
958
|
+
assert.include(trackingIds, 'sync-tracking-20');
|
|
959
|
+
});
|
|
960
|
+
|
|
961
|
+
it('does not clean up never-completed records for a different dataset', () => {
|
|
962
|
+
// never-completed sync for dataset "other"
|
|
963
|
+
cdl.saveTimestamp({
|
|
964
|
+
key: 'internal.client.locus.sync.start',
|
|
965
|
+
value: 100,
|
|
966
|
+
options: {
|
|
967
|
+
meetingId: 'meeting-1',
|
|
968
|
+
dataSetName: 'other',
|
|
969
|
+
randomBackoffTime: 0,
|
|
970
|
+
trackingId: 'other-tracking-1',
|
|
971
|
+
},
|
|
972
|
+
});
|
|
973
|
+
cdl.saveTimestamp({
|
|
974
|
+
key: 'internal.client.locus.sync.request',
|
|
975
|
+
value: 110,
|
|
976
|
+
options: {meetingId: 'meeting-1', dataSetName: 'other', trackingId: 'other-tracking-1'},
|
|
977
|
+
});
|
|
978
|
+
cdl.saveTimestamp({
|
|
979
|
+
key: 'internal.client.locus.sync.response',
|
|
980
|
+
value: 130,
|
|
981
|
+
options: {meetingId: 'meeting-1', dataSetName: 'other', trackingId: 'other-tracking-1'},
|
|
982
|
+
});
|
|
983
|
+
|
|
984
|
+
// completed sync for dataset "main"
|
|
985
|
+
cdl.saveTimestamp({
|
|
986
|
+
key: 'internal.client.locus.sync.start',
|
|
987
|
+
value: 200,
|
|
988
|
+
options: {
|
|
989
|
+
meetingId: 'meeting-1',
|
|
990
|
+
dataSetName: 'main',
|
|
991
|
+
randomBackoffTime: 0,
|
|
992
|
+
trackingId: 'main-tracking-1',
|
|
993
|
+
},
|
|
994
|
+
});
|
|
995
|
+
cdl.saveTimestamp({
|
|
996
|
+
key: 'internal.client.locus.sync.request',
|
|
997
|
+
value: 210,
|
|
998
|
+
options: {meetingId: 'meeting-1', dataSetName: 'main', trackingId: 'main-tracking-1'},
|
|
999
|
+
});
|
|
1000
|
+
cdl.saveTimestamp({
|
|
1001
|
+
key: 'internal.client.locus.sync.response',
|
|
1002
|
+
value: 230,
|
|
1003
|
+
options: {meetingId: 'meeting-1', dataSetName: 'main', trackingId: 'main-tracking-1'},
|
|
1004
|
+
});
|
|
1005
|
+
cdl.saveTimestamp({
|
|
1006
|
+
key: 'internal.client.locus.sync.message.received',
|
|
1007
|
+
value: 240,
|
|
1008
|
+
options: {meetingId: 'meeting-1', dataSetName: 'main', trackingId: 'main-tracking-1'},
|
|
1009
|
+
});
|
|
1010
|
+
|
|
1011
|
+
const completed = cdl.completeLocusSyncLatency('meeting-1', 'main-tracking-1');
|
|
1012
|
+
|
|
1013
|
+
assert.isDefined(completed);
|
|
1014
|
+
|
|
1015
|
+
// the "other" dataset record must remain untouched
|
|
1016
|
+
const records = cdl.meetingLatencies.get('meeting-1');
|
|
1017
|
+
|
|
1018
|
+
assert.isDefined(records);
|
|
1019
|
+
assert.lengthOf(records!, 1);
|
|
1020
|
+
assert.equal(records![0].locusSync.dataSetName, 'other');
|
|
1021
|
+
assert.equal(records![0].locusSync.trackingId, 'other-tracking-1');
|
|
1022
|
+
});
|
|
1023
|
+
|
|
1024
|
+
it('keys sync latency records by meeting id', () => {
|
|
1025
|
+
cdl.saveTimestamp({
|
|
1026
|
+
key: 'internal.client.locus.sync.start',
|
|
1027
|
+
value: 100,
|
|
1028
|
+
options: {
|
|
1029
|
+
meetingId: 'meeting-1',
|
|
1030
|
+
dataSetName: 'main',
|
|
1031
|
+
randomBackoffTime: 10,
|
|
1032
|
+
trackingId: 'sync-tracking-1',
|
|
1033
|
+
},
|
|
1034
|
+
});
|
|
1035
|
+
cdl.saveTimestamp({
|
|
1036
|
+
key: 'internal.client.locus.sync.request',
|
|
1037
|
+
value: 110,
|
|
1038
|
+
options: {meetingId: 'meeting-1', dataSetName: 'main', trackingId: 'sync-tracking-1'},
|
|
1039
|
+
});
|
|
1040
|
+
|
|
1041
|
+
cdl.saveTimestamp({
|
|
1042
|
+
key: 'internal.client.locus.sync.start',
|
|
1043
|
+
value: 200,
|
|
1044
|
+
options: {
|
|
1045
|
+
meetingId: 'meeting-2',
|
|
1046
|
+
dataSetName: 'main',
|
|
1047
|
+
randomBackoffTime: 23,
|
|
1048
|
+
trackingId: 'sync-tracking-2',
|
|
1049
|
+
},
|
|
1050
|
+
});
|
|
1051
|
+
cdl.saveTimestamp({
|
|
1052
|
+
key: 'internal.client.locus.sync.request',
|
|
1053
|
+
value: 217,
|
|
1054
|
+
options: {meetingId: 'meeting-2', dataSetName: 'main', trackingId: 'sync-tracking-2'},
|
|
1055
|
+
});
|
|
1056
|
+
cdl.saveTimestamp({
|
|
1057
|
+
key: 'internal.client.locus.sync.response',
|
|
1058
|
+
value: 241,
|
|
1059
|
+
options: {meetingId: 'meeting-2', dataSetName: 'main', trackingId: 'sync-tracking-2'},
|
|
1060
|
+
});
|
|
1061
|
+
cdl.saveTimestamp({
|
|
1062
|
+
key: 'internal.client.locus.sync.message.received',
|
|
1063
|
+
value: 268,
|
|
1064
|
+
options: {meetingId: 'meeting-2', dataSetName: 'main', trackingId: 'sync-tracking-2'},
|
|
1065
|
+
});
|
|
1066
|
+
|
|
1067
|
+
cdl.saveTimestamp({
|
|
1068
|
+
key: 'internal.client.locus.sync.response',
|
|
1069
|
+
value: 125,
|
|
1070
|
+
options: {meetingId: 'meeting-1', dataSetName: 'main', trackingId: 'sync-tracking-1'},
|
|
1071
|
+
});
|
|
1072
|
+
cdl.saveTimestamp({
|
|
1073
|
+
key: 'internal.client.locus.sync.message.received',
|
|
1074
|
+
value: 150,
|
|
1075
|
+
options: {meetingId: 'meeting-1', dataSetName: 'main', trackingId: 'sync-tracking-1'},
|
|
1076
|
+
});
|
|
1077
|
+
|
|
1078
|
+
assert.deepEqual(cdl.getLocusSyncLatency('meeting-1', 'sync-tracking-1'), {
|
|
1079
|
+
randomBackoffTime: 0,
|
|
1080
|
+
hashtreePrepTime: 0,
|
|
1081
|
+
hashtreeResponseTime: 0,
|
|
1082
|
+
syncPrepTime: 10,
|
|
1083
|
+
syncResponseTime: 15,
|
|
1084
|
+
syncMessageReceiveTime: 40,
|
|
1085
|
+
totalTime: 50,
|
|
1086
|
+
});
|
|
1087
|
+
assert.deepEqual(cdl.getLocusSyncLatency('meeting-2', 'sync-tracking-2'), {
|
|
1088
|
+
randomBackoffTime: 0,
|
|
1089
|
+
hashtreePrepTime: 0,
|
|
1090
|
+
hashtreeResponseTime: 0,
|
|
1091
|
+
syncPrepTime: 17,
|
|
1092
|
+
syncResponseTime: 24,
|
|
1093
|
+
syncMessageReceiveTime: 51,
|
|
1094
|
+
totalTime: 68,
|
|
1095
|
+
});
|
|
1096
|
+
|
|
1097
|
+
cdl.clearLocusSyncLatency('main', 'meeting-1');
|
|
1098
|
+
|
|
1099
|
+
assert.isUndefined(cdl.getLocusSyncLatency('meeting-1', 'sync-tracking-1'));
|
|
1100
|
+
assert.isDefined(cdl.getLocusSyncLatency('meeting-2', 'sync-tracking-2'));
|
|
1101
|
+
});
|
|
1102
|
+
|
|
1103
|
+
it('returns undefined and clears state when required milestones are missing', () => {
|
|
1104
|
+
cdl.saveTimestamp({
|
|
1105
|
+
key: 'internal.client.locus.sync.start',
|
|
1106
|
+
value: 100,
|
|
1107
|
+
options: {
|
|
1108
|
+
meetingId: 'meeting-1',
|
|
1109
|
+
dataSetName: 'main',
|
|
1110
|
+
randomBackoffTime: 0,
|
|
1111
|
+
trackingId: 'sync-tracking-id',
|
|
1112
|
+
},
|
|
1113
|
+
});
|
|
1114
|
+
cdl.saveTimestamp({
|
|
1115
|
+
key: 'internal.client.locus.sync.message.received',
|
|
1116
|
+
value: 140,
|
|
1117
|
+
options: {meetingId: 'meeting-1', dataSetName: 'main', trackingId: 'sync-tracking-id'},
|
|
1118
|
+
});
|
|
1119
|
+
|
|
1120
|
+
assert.isUndefined(cdl.getLocusSyncLatency('meeting-1', 'sync-tracking-id'));
|
|
1121
|
+
cdl.clearLocusSyncLatency('main', 'meeting-1');
|
|
1122
|
+
assert.isFalse(cdl.meetingLatencies.has('meeting-1'));
|
|
1123
|
+
});
|
|
1124
|
+
|
|
1125
|
+
it('clears only the record matching the tracking id when one is supplied', () => {
|
|
1126
|
+
const stampFullRecord = (trackingId: string, base: number) => {
|
|
1127
|
+
cdl.saveTimestamp({
|
|
1128
|
+
key: 'internal.client.locus.sync.start',
|
|
1129
|
+
value: base,
|
|
1130
|
+
options: {meetingId: 'meeting-1', dataSetName: 'main', trackingId},
|
|
1131
|
+
});
|
|
1132
|
+
cdl.saveTimestamp({
|
|
1133
|
+
key: 'internal.client.locus.sync.request',
|
|
1134
|
+
value: base + 10,
|
|
1135
|
+
options: {meetingId: 'meeting-1', dataSetName: 'main', trackingId},
|
|
1136
|
+
});
|
|
1137
|
+
cdl.saveTimestamp({
|
|
1138
|
+
key: 'internal.client.locus.sync.response',
|
|
1139
|
+
value: base + 25,
|
|
1140
|
+
options: {meetingId: 'meeting-1', dataSetName: 'main', trackingId},
|
|
1141
|
+
});
|
|
1142
|
+
cdl.saveTimestamp({
|
|
1143
|
+
key: 'internal.client.locus.sync.message.received',
|
|
1144
|
+
value: base + 50,
|
|
1145
|
+
options: {meetingId: 'meeting-1', dataSetName: 'main', trackingId},
|
|
1146
|
+
});
|
|
1147
|
+
};
|
|
1148
|
+
|
|
1149
|
+
// Two records for the same dataset/meeting but different tracking ids.
|
|
1150
|
+
stampFullRecord('sync-tracking-1', 100);
|
|
1151
|
+
stampFullRecord('sync-tracking-2', 200);
|
|
1152
|
+
|
|
1153
|
+
assert.isDefined(cdl.getLocusSyncLatency('meeting-1', 'sync-tracking-1'));
|
|
1154
|
+
assert.isDefined(cdl.getLocusSyncLatency('meeting-1', 'sync-tracking-2'));
|
|
1155
|
+
|
|
1156
|
+
// Clearing with a tracking id drops only that record, leaving the other intact.
|
|
1157
|
+
cdl.clearLocusSyncLatency('main', 'meeting-1', 'sync-tracking-1');
|
|
1158
|
+
|
|
1159
|
+
assert.isUndefined(cdl.getLocusSyncLatency('meeting-1', 'sync-tracking-1'));
|
|
1160
|
+
assert.isDefined(cdl.getLocusSyncLatency('meeting-1', 'sync-tracking-2'));
|
|
1161
|
+
});
|
|
1162
|
+
|
|
1163
|
+
describe('recordLocusSyncMessageReceived', () => {
|
|
1164
|
+
const startPendingSync = (trackingId: string) => {
|
|
1165
|
+
cdl.saveTimestamp({
|
|
1166
|
+
key: 'internal.client.locus.sync.start',
|
|
1167
|
+
value: 100,
|
|
1168
|
+
options: {meetingId: 'meeting-1', dataSetName: 'main', trackingId},
|
|
1169
|
+
});
|
|
1170
|
+
};
|
|
1171
|
+
|
|
1172
|
+
it('stamps messageReceived on the matching pending record using the current time', () => {
|
|
1173
|
+
clock.setSystemTime(500);
|
|
1174
|
+
|
|
1175
|
+
try {
|
|
1176
|
+
startPendingSync('sync-tracking-id');
|
|
1177
|
+
cdl.recordLocusSyncMessageReceived('meeting-1', 'sync-tracking-id');
|
|
1178
|
+
|
|
1179
|
+
assert.equal(cdl.meetingLatencies.get('meeting-1')![0].locusSync.messageReceived, 500);
|
|
1180
|
+
} finally {
|
|
1181
|
+
clock.setSystemTime(now.getTime());
|
|
1182
|
+
}
|
|
1183
|
+
});
|
|
1184
|
+
|
|
1185
|
+
it('does not overwrite an already recorded messageReceived', () => {
|
|
1186
|
+
clock.setSystemTime(999);
|
|
1187
|
+
|
|
1188
|
+
try {
|
|
1189
|
+
startPendingSync('sync-tracking-id');
|
|
1190
|
+
cdl.saveTimestamp({
|
|
1191
|
+
key: 'internal.client.locus.sync.message.received',
|
|
1192
|
+
value: 140,
|
|
1193
|
+
options: {meetingId: 'meeting-1', dataSetName: 'main', trackingId: 'sync-tracking-id'},
|
|
1194
|
+
});
|
|
1195
|
+
cdl.recordLocusSyncMessageReceived('meeting-1', 'sync-tracking-id');
|
|
1196
|
+
|
|
1197
|
+
assert.equal(cdl.meetingLatencies.get('meeting-1')![0].locusSync.messageReceived, 140);
|
|
1198
|
+
} finally {
|
|
1199
|
+
clock.setSystemTime(now.getTime());
|
|
1200
|
+
}
|
|
1201
|
+
});
|
|
1202
|
+
|
|
1203
|
+
it('is a no-op when no record matches the tracking id', () => {
|
|
1204
|
+
startPendingSync('sync-tracking-id');
|
|
1205
|
+
cdl.recordLocusSyncMessageReceived('meeting-1', 'some-other-tracking-id');
|
|
1206
|
+
|
|
1207
|
+
assert.isUndefined(cdl.meetingLatencies.get('meeting-1')![0].locusSync.messageReceived);
|
|
1208
|
+
});
|
|
1209
|
+
|
|
1210
|
+
it('is a no-op when trackingId is empty', () => {
|
|
1211
|
+
startPendingSync('sync-tracking-id');
|
|
1212
|
+
|
|
1213
|
+
assert.doesNotThrow(() => cdl.recordLocusSyncMessageReceived('meeting-1', ''));
|
|
1214
|
+
assert.isUndefined(cdl.meetingLatencies.get('meeting-1')![0].locusSync.messageReceived);
|
|
1215
|
+
});
|
|
1216
|
+
});
|
|
1217
|
+
|
|
1218
|
+
describe('completeLocusSyncLatency requires both milestones', () => {
|
|
1219
|
+
const recordSyncRequest = (trackingId: string) => {
|
|
1220
|
+
cdl.saveTimestamp({
|
|
1221
|
+
key: 'internal.client.locus.sync.start',
|
|
1222
|
+
value: 100,
|
|
1223
|
+
options: {meetingId: 'meeting-1', dataSetName: 'main', trackingId},
|
|
1224
|
+
});
|
|
1225
|
+
cdl.saveTimestamp({
|
|
1226
|
+
key: 'internal.client.locus.sync.request',
|
|
1227
|
+
value: 110,
|
|
1228
|
+
options: {meetingId: 'meeting-1', dataSetName: 'main', trackingId},
|
|
1229
|
+
});
|
|
1230
|
+
};
|
|
1231
|
+
const recordSyncResponse = (trackingId: string) =>
|
|
1232
|
+
cdl.saveTimestamp({
|
|
1233
|
+
key: 'internal.client.locus.sync.response',
|
|
1234
|
+
value: 130,
|
|
1235
|
+
options: {meetingId: 'meeting-1', dataSetName: 'main', trackingId},
|
|
1236
|
+
});
|
|
1237
|
+
const recordMessageReceived = (trackingId: string) =>
|
|
1238
|
+
cdl.saveTimestamp({
|
|
1239
|
+
key: 'internal.client.locus.sync.message.received',
|
|
1240
|
+
value: 150,
|
|
1241
|
+
options: {meetingId: 'meeting-1', dataSetName: 'main', trackingId},
|
|
1242
|
+
});
|
|
1243
|
+
|
|
1244
|
+
it('returns undefined and keeps the record when only the /sync response is present', () => {
|
|
1245
|
+
recordSyncRequest('sync-tracking-id');
|
|
1246
|
+
recordSyncResponse('sync-tracking-id');
|
|
1247
|
+
|
|
1248
|
+
assert.isUndefined(cdl.completeLocusSyncLatency('meeting-1', 'sync-tracking-id'));
|
|
1249
|
+
assert.lengthOf(cdl.meetingLatencies.get('meeting-1')!, 1);
|
|
1250
|
+
});
|
|
1251
|
+
|
|
1252
|
+
it('returns undefined and keeps the record when only the LLM message is present', () => {
|
|
1253
|
+
recordSyncRequest('sync-tracking-id');
|
|
1254
|
+
recordMessageReceived('sync-tracking-id');
|
|
1255
|
+
|
|
1256
|
+
assert.isUndefined(cdl.completeLocusSyncLatency('meeting-1', 'sync-tracking-id'));
|
|
1257
|
+
assert.lengthOf(cdl.meetingLatencies.get('meeting-1')!, 1);
|
|
1258
|
+
});
|
|
1259
|
+
|
|
1260
|
+
it('emits and consumes the record when the /sync response arrives after the LLM message', () => {
|
|
1261
|
+
recordSyncRequest('sync-tracking-id');
|
|
1262
|
+
// LLM message arrives first, before the HTTP response
|
|
1263
|
+
recordMessageReceived('sync-tracking-id');
|
|
1264
|
+
assert.isUndefined(cdl.completeLocusSyncLatency('meeting-1', 'sync-tracking-id'));
|
|
1265
|
+
|
|
1266
|
+
// /sync response lands second -> now both milestones are in
|
|
1267
|
+
recordSyncResponse('sync-tracking-id');
|
|
1268
|
+
|
|
1269
|
+
assert.deepEqual(cdl.completeLocusSyncLatency('meeting-1', 'sync-tracking-id'), {
|
|
1270
|
+
dataSet: 'main',
|
|
1271
|
+
syncLatency: {
|
|
1272
|
+
randomBackoffTime: 0,
|
|
1273
|
+
hashtreePrepTime: 0,
|
|
1274
|
+
hashtreeResponseTime: 0,
|
|
1275
|
+
syncPrepTime: 10,
|
|
1276
|
+
syncResponseTime: 20,
|
|
1277
|
+
syncMessageReceiveTime: 40,
|
|
1278
|
+
totalTime: 50,
|
|
1279
|
+
},
|
|
1280
|
+
});
|
|
1281
|
+
assert.isUndefined(cdl.meetingLatencies.get('meeting-1'));
|
|
1282
|
+
});
|
|
1283
|
+
|
|
1284
|
+
it('emits and consumes the record when the LLM message arrives after the /sync response', () => {
|
|
1285
|
+
recordSyncRequest('sync-tracking-id');
|
|
1286
|
+
// HTTP response arrives first
|
|
1287
|
+
recordSyncResponse('sync-tracking-id');
|
|
1288
|
+
assert.isUndefined(cdl.completeLocusSyncLatency('meeting-1', 'sync-tracking-id'));
|
|
1289
|
+
|
|
1290
|
+
// LLM message lands second
|
|
1291
|
+
recordMessageReceived('sync-tracking-id');
|
|
1292
|
+
|
|
1293
|
+
const completed = cdl.completeLocusSyncLatency('meeting-1', 'sync-tracking-id');
|
|
1294
|
+
|
|
1295
|
+
assert.isDefined(completed);
|
|
1296
|
+
assert.equal(completed!.dataSet, 'main');
|
|
1297
|
+
assert.isUndefined(cdl.meetingLatencies.get('meeting-1'));
|
|
1298
|
+
});
|
|
1299
|
+
});
|
|
116
1300
|
});
|
|
117
1301
|
|
|
118
1302
|
it('should calculate diff between timestamps correctly', () => {
|
|
@@ -235,20 +1419,12 @@ describe('internal-plugin-metrics', () => {
|
|
|
235
1419
|
});
|
|
236
1420
|
|
|
237
1421
|
describe('measureLatency', () => {
|
|
238
|
-
let clock;
|
|
239
1422
|
let saveLatencySpy;
|
|
240
1423
|
|
|
241
1424
|
beforeEach(() => {
|
|
242
|
-
clock = sinon.useFakeTimers();
|
|
243
|
-
|
|
244
1425
|
saveLatencySpy = sinon.stub(cdl, 'saveLatency');
|
|
245
1426
|
});
|
|
246
1427
|
|
|
247
|
-
afterEach(() => {
|
|
248
|
-
clock.restore();
|
|
249
|
-
sinon.restore();
|
|
250
|
-
});
|
|
251
|
-
|
|
252
1428
|
it('checks measureLatency with accumulate false', async () => {
|
|
253
1429
|
const key = 'internal.client.pageJMT';
|
|
254
1430
|
const accumulate = false;
|
|
@@ -264,7 +1440,7 @@ describe('internal-plugin-metrics', () => {
|
|
|
264
1440
|
const resolvedValue = await promise;
|
|
265
1441
|
assert.deepEqual(resolvedValue, 'test');
|
|
266
1442
|
assert.calledOnceWithExactly(callbackStub);
|
|
267
|
-
assert.calledOnceWithExactly(saveLatencySpy, key, 50, accumulate);
|
|
1443
|
+
assert.calledOnceWithExactly(saveLatencySpy, key, 50, {accumulate});
|
|
268
1444
|
});
|
|
269
1445
|
|
|
270
1446
|
it('checks measureLatency with accumulate true', async () => {
|
|
@@ -280,7 +1456,7 @@ describe('internal-plugin-metrics', () => {
|
|
|
280
1456
|
const resolvedValue = await promise;
|
|
281
1457
|
assert.deepEqual(resolvedValue, 'test123');
|
|
282
1458
|
assert.calledOnceWithExactly(callbackStub);
|
|
283
|
-
assert.calledOnceWithExactly(saveLatencySpy, key, 20, accumulate);
|
|
1459
|
+
assert.calledOnceWithExactly(saveLatencySpy, key, 20, {accumulate});
|
|
284
1460
|
});
|
|
285
1461
|
|
|
286
1462
|
it('checks measureLatency when callBack rejects', async () => {
|
|
@@ -297,7 +1473,7 @@ describe('internal-plugin-metrics', () => {
|
|
|
297
1473
|
const rejectedValue = await assert.isRejected(promise);
|
|
298
1474
|
assert.deepEqual(rejectedValue, error);
|
|
299
1475
|
assert.calledOnceWithExactly(callbackStub);
|
|
300
|
-
assert.calledOnceWithExactly(saveLatencySpy, key, 50, accumulate);
|
|
1476
|
+
assert.calledOnceWithExactly(saveLatencySpy, key, 50, {accumulate});
|
|
301
1477
|
});
|
|
302
1478
|
});
|
|
303
1479
|
|
|
@@ -412,8 +1588,10 @@ describe('internal-plugin-metrics', () => {
|
|
|
412
1588
|
});
|
|
413
1589
|
|
|
414
1590
|
it('calculates getCallInitJoinReq correctly', () => {
|
|
1591
|
+
cdl.saveTimestamp({key: 'internal.client.meeting.interstitial-window.showed', value: 5});
|
|
415
1592
|
cdl.saveTimestamp({key: 'internal.client.interstitial-window.click.joinbutton', value: 10});
|
|
416
1593
|
cdl.saveTimestamp({key: 'client.locus.join.request', value: 20});
|
|
1594
|
+
// showedToJoinReq = 20-5 = 15, showInterstitialTime = 10-5 = 5, result = 15-5 = 10
|
|
417
1595
|
assert.deepEqual(cdl.getCallInitJoinReq(), 10);
|
|
418
1596
|
});
|
|
419
1597
|
|
|
@@ -509,7 +1687,7 @@ describe('internal-plugin-metrics', () => {
|
|
|
509
1687
|
|
|
510
1688
|
it('calculates getStayLobbyTime correctly', () => {
|
|
511
1689
|
cdl.saveTimestamp({
|
|
512
|
-
key: 'client.
|
|
1690
|
+
key: 'client.lobby.entered',
|
|
513
1691
|
value: 10,
|
|
514
1692
|
});
|
|
515
1693
|
cdl.saveTimestamp({
|
|
@@ -520,44 +1698,44 @@ describe('internal-plugin-metrics', () => {
|
|
|
520
1698
|
});
|
|
521
1699
|
|
|
522
1700
|
describe('getStayLobbyTimeCappedBy', () => {
|
|
523
|
-
it('returns
|
|
1701
|
+
it('returns 0 when lobbyStartTimestamp is missing', () => {
|
|
524
1702
|
cdl.saveTimestamp({key: 'client.media-engine.ready', value: 100});
|
|
525
|
-
assert.deepEqual(cdl.getStayLobbyTimeCappedBy('client.media-engine.ready'),
|
|
1703
|
+
assert.deepEqual(cdl.getStayLobbyTimeCappedBy('client.media-engine.ready'), 0);
|
|
526
1704
|
});
|
|
527
1705
|
|
|
528
1706
|
it('returns undefined when endTimestampKey is missing', () => {
|
|
529
|
-
cdl.saveTimestamp({key: 'client.
|
|
1707
|
+
cdl.saveTimestamp({key: 'client.lobby.entered', value: 10});
|
|
530
1708
|
assert.deepEqual(cdl.getStayLobbyTimeCappedBy('client.media-engine.ready'), undefined);
|
|
531
1709
|
});
|
|
532
1710
|
|
|
533
1711
|
it('uses maximumEndTimestamp when lobby end does not exist', () => {
|
|
534
|
-
cdl.saveTimestamp({key: 'client.
|
|
1712
|
+
cdl.saveTimestamp({key: 'client.lobby.entered', value: 10});
|
|
535
1713
|
cdl.saveTimestamp({key: 'client.media-engine.ready', value: 50});
|
|
536
1714
|
assert.deepEqual(cdl.getStayLobbyTimeCappedBy('client.media-engine.ready'), 40);
|
|
537
1715
|
});
|
|
538
1716
|
|
|
539
1717
|
it('uses lobby end when it is before maximumEndTimestamp', () => {
|
|
540
|
-
cdl.saveTimestamp({key: 'client.
|
|
1718
|
+
cdl.saveTimestamp({key: 'client.lobby.entered', value: 10});
|
|
541
1719
|
cdl.saveTimestamp({key: 'client.lobby.exited', value: 30});
|
|
542
1720
|
cdl.saveTimestamp({key: 'client.media-engine.ready', value: 50});
|
|
543
1721
|
assert.deepEqual(cdl.getStayLobbyTimeCappedBy('client.media-engine.ready'), 20);
|
|
544
1722
|
});
|
|
545
1723
|
|
|
546
1724
|
it('uses maximumEndTimestamp when lobby end is after it', () => {
|
|
547
|
-
cdl.saveTimestamp({key: 'client.
|
|
1725
|
+
cdl.saveTimestamp({key: 'client.lobby.entered', value: 10});
|
|
548
1726
|
cdl.saveTimestamp({key: 'client.lobby.exited', value: 60});
|
|
549
1727
|
cdl.saveTimestamp({key: 'client.media-engine.ready', value: 50});
|
|
550
1728
|
assert.deepEqual(cdl.getStayLobbyTimeCappedBy('client.media-engine.ready'), 40);
|
|
551
1729
|
});
|
|
552
1730
|
|
|
553
1731
|
it('clamps to 0 when result would be negative', () => {
|
|
554
|
-
cdl.saveTimestamp({key: 'client.
|
|
1732
|
+
cdl.saveTimestamp({key: 'client.lobby.entered', value: 100});
|
|
555
1733
|
cdl.saveTimestamp({key: 'client.media-engine.ready', value: 50});
|
|
556
1734
|
assert.deepEqual(cdl.getStayLobbyTimeCappedBy('client.media-engine.ready'), 0);
|
|
557
1735
|
});
|
|
558
1736
|
|
|
559
1737
|
it('clamps to MAX_INTEGER when result is very large', () => {
|
|
560
|
-
cdl.saveTimestamp({key: 'client.
|
|
1738
|
+
cdl.saveTimestamp({key: 'client.lobby.entered', value: 0});
|
|
561
1739
|
cdl.saveTimestamp({key: 'client.media-engine.ready', value: 2147483648});
|
|
562
1740
|
assert.deepEqual(cdl.getStayLobbyTimeCappedBy('client.media-engine.ready'), 2147483647);
|
|
563
1741
|
});
|
|
@@ -574,76 +1752,40 @@ describe('internal-plugin-metrics', () => {
|
|
|
574
1752
|
});
|
|
575
1753
|
|
|
576
1754
|
it('calculates getClickToInterstitial correctly', () => {
|
|
577
|
-
cdl.saveTimestamp({
|
|
578
|
-
key: 'internal.client.meeting.click.joinbutton',
|
|
579
|
-
value: 10,
|
|
580
|
-
});
|
|
581
|
-
cdl.saveTimestamp({
|
|
582
|
-
key: 'internal.client.meeting.interstitial-window.showed',
|
|
583
|
-
value: 20,
|
|
584
|
-
});
|
|
585
|
-
assert.deepEqual(cdl.getClickToInterstitial(), 10);
|
|
586
|
-
});
|
|
587
|
-
|
|
588
|
-
it('calculates getClickToInterstitial without join button timestamp', () => {
|
|
589
1755
|
cdl.saveLatency('internal.click.to.interstitial', 5);
|
|
590
|
-
cdl.saveTimestamp({
|
|
591
|
-
key: 'internal.client.meeting.interstitial-window.showed',
|
|
592
|
-
value: 20,
|
|
593
|
-
});
|
|
594
1756
|
assert.deepEqual(cdl.getClickToInterstitial(), 5);
|
|
595
1757
|
});
|
|
596
1758
|
|
|
597
|
-
it('calculates getClickToInterstitial
|
|
1759
|
+
it('calculates getClickToInterstitial correctly when it is 0', () => {
|
|
598
1760
|
cdl.saveLatency('internal.click.to.interstitial', 0);
|
|
599
|
-
cdl.saveTimestamp({
|
|
600
|
-
key: 'internal.client.meeting.interstitial-window.showed',
|
|
601
|
-
value: 20,
|
|
602
|
-
});
|
|
603
1761
|
assert.deepEqual(cdl.getClickToInterstitial(), 0);
|
|
604
1762
|
});
|
|
605
1763
|
|
|
606
|
-
it('calculates getClickToInterstitial
|
|
1764
|
+
it('calculates getClickToInterstitial correctly when it is greater than MAX_INTEGER', () => {
|
|
607
1765
|
cdl.saveLatency('internal.click.to.interstitial', 2147483648);
|
|
608
1766
|
assert.deepEqual(cdl.getClickToInterstitial(), 2147483647);
|
|
609
1767
|
});
|
|
610
1768
|
|
|
611
1769
|
it('calculates getClickToInterstitialWithUserDelay correctly', () => {
|
|
612
|
-
cdl.saveTimestamp({
|
|
613
|
-
key: 'internal.client.meeting.click.joinbutton',
|
|
614
|
-
value: 10,
|
|
615
|
-
});
|
|
616
|
-
cdl.saveTimestamp({
|
|
617
|
-
key: 'internal.client.meeting.interstitial-window.showed',
|
|
618
|
-
value: 20,
|
|
619
|
-
});
|
|
620
|
-
assert.deepEqual(cdl.getClickToInterstitialWithUserDelay(), 10);
|
|
621
|
-
});
|
|
622
|
-
|
|
623
|
-
it('calculates getClickToInterstitialWithUserDelay without join button timestamp', () => {
|
|
624
1770
|
cdl.saveLatency('internal.click.to.interstitial.with.user.delay', 5);
|
|
625
|
-
cdl.saveTimestamp({
|
|
626
|
-
key: 'internal.client.meeting.interstitial-window.showed',
|
|
627
|
-
value: 20,
|
|
628
|
-
});
|
|
629
1771
|
assert.deepEqual(cdl.getClickToInterstitialWithUserDelay(), 5);
|
|
630
1772
|
});
|
|
631
1773
|
|
|
632
|
-
it('calculates getClickToInterstitialWithUserDelay
|
|
1774
|
+
it('calculates getClickToInterstitialWithUserDelay correctly when it is 0', () => {
|
|
633
1775
|
cdl.saveLatency('internal.click.to.interstitial.with.user.delay', 0);
|
|
634
|
-
cdl.saveTimestamp({
|
|
635
|
-
key: 'internal.client.meeting.interstitial-window.showed',
|
|
636
|
-
value: 20,
|
|
637
|
-
});
|
|
638
1776
|
assert.deepEqual(cdl.getClickToInterstitialWithUserDelay(), 0);
|
|
639
1777
|
});
|
|
640
1778
|
|
|
641
|
-
it('calculates getClickToInterstitialWithUserDelay
|
|
1779
|
+
it('calculates getClickToInterstitialWithUserDelay correctly when it is greater than MAX_INTEGER', () => {
|
|
642
1780
|
cdl.saveLatency('internal.click.to.interstitial.with.user.delay', 2147483648);
|
|
643
1781
|
assert.deepEqual(cdl.getClickToInterstitialWithUserDelay(), 2147483647);
|
|
644
1782
|
});
|
|
645
1783
|
|
|
646
1784
|
it('calculates getInterstitialToJoinOK correctly', () => {
|
|
1785
|
+
cdl.saveTimestamp({
|
|
1786
|
+
key: 'internal.client.meeting.interstitial-window.showed',
|
|
1787
|
+
value: 5,
|
|
1788
|
+
});
|
|
647
1789
|
cdl.saveTimestamp({
|
|
648
1790
|
key: 'internal.client.interstitial-window.click.joinbutton',
|
|
649
1791
|
value: 10,
|
|
@@ -652,12 +1794,13 @@ describe('internal-plugin-metrics', () => {
|
|
|
652
1794
|
key: 'client.locus.join.response',
|
|
653
1795
|
value: 20,
|
|
654
1796
|
});
|
|
1797
|
+
// showedToJoinResp = 20-5 = 15, showInterstitialTime = 10-5 = 5, result = 15-5 = 10
|
|
655
1798
|
assert.deepEqual(cdl.getInterstitialToJoinOK(), 10);
|
|
656
1799
|
});
|
|
657
1800
|
|
|
658
1801
|
it('calculates getInterstitialToJoinOK correctly when one value is not a number', () => {
|
|
659
1802
|
cdl.saveTimestamp({
|
|
660
|
-
key: 'internal.client.interstitial-window.
|
|
1803
|
+
key: 'internal.client.meeting.interstitial-window.showed',
|
|
661
1804
|
value: 'ten' as unknown as number,
|
|
662
1805
|
});
|
|
663
1806
|
cdl.saveTimestamp({
|
|
@@ -668,22 +1811,12 @@ describe('internal-plugin-metrics', () => {
|
|
|
668
1811
|
});
|
|
669
1812
|
|
|
670
1813
|
it('calculates getCallInitMediaEngineReady correctly', () => {
|
|
671
|
-
cdl.
|
|
672
|
-
|
|
673
|
-
value: 10,
|
|
674
|
-
});
|
|
675
|
-
cdl.saveTimestamp({
|
|
676
|
-
key: 'client.media-engine.ready',
|
|
677
|
-
value: 20,
|
|
678
|
-
});
|
|
679
|
-
assert.deepEqual(cdl.getCallInitMediaEngineReady(), 10);
|
|
1814
|
+
sinon.stub(cdl, 'getInterstitialToMediaOKJMT').returns(42);
|
|
1815
|
+
assert.deepEqual(cdl.getCallInitMediaEngineReady(), 42);
|
|
680
1816
|
});
|
|
681
1817
|
|
|
682
1818
|
it('calculates getTotalJMT correctly', () => {
|
|
683
|
-
cdl.
|
|
684
|
-
key: 'internal.client.interstitial-window.click.joinbutton',
|
|
685
|
-
value: 5,
|
|
686
|
-
});
|
|
1819
|
+
cdl.saveLatency('internal.click.to.interstitial', 10);
|
|
687
1820
|
cdl.saveTimestamp({
|
|
688
1821
|
key: 'internal.client.meeting.click.joinbutton',
|
|
689
1822
|
value: 10,
|
|
@@ -692,29 +1825,39 @@ describe('internal-plugin-metrics', () => {
|
|
|
692
1825
|
key: 'internal.client.meeting.interstitial-window.showed',
|
|
693
1826
|
value: 20,
|
|
694
1827
|
});
|
|
1828
|
+
cdl.saveTimestamp({
|
|
1829
|
+
key: 'internal.client.interstitial-window.click.joinbutton',
|
|
1830
|
+
value: 25,
|
|
1831
|
+
});
|
|
695
1832
|
cdl.saveTimestamp({
|
|
696
1833
|
key: 'client.locus.join.response',
|
|
697
1834
|
value: 40,
|
|
698
1835
|
});
|
|
699
|
-
|
|
1836
|
+
// clickToInterstitial = 20-10 = 10
|
|
1837
|
+
// showedToJoinLocusResponse = 40-20 = 20
|
|
1838
|
+
// showInterstitialTime = 25-20 = 5
|
|
1839
|
+
// total = 10 + 20 - 5 = 25
|
|
1840
|
+
assert.deepEqual(cdl.getTotalJMT(), 25);
|
|
700
1841
|
});
|
|
701
1842
|
|
|
702
1843
|
it('calculates getTotalJMT correctly when clickToInterstitial is 0', () => {
|
|
703
1844
|
cdl.saveLatency('internal.click.to.interstitial', 0);
|
|
704
1845
|
cdl.saveTimestamp({
|
|
705
|
-
key: 'internal.client.interstitial-window.
|
|
1846
|
+
key: 'internal.client.meeting.interstitial-window.showed',
|
|
706
1847
|
value: 20,
|
|
707
1848
|
});
|
|
708
1849
|
cdl.saveTimestamp({
|
|
709
1850
|
key: 'client.locus.join.response',
|
|
710
1851
|
value: 40,
|
|
711
1852
|
});
|
|
1853
|
+
// showedToJoinLocusResponse = 40-20 = 20, showInterstitialTime = 0
|
|
1854
|
+
// total = 0 + 20 - 0 = 20
|
|
712
1855
|
assert.deepEqual(cdl.getTotalJMT(), 20);
|
|
713
1856
|
});
|
|
714
1857
|
|
|
715
1858
|
it('calculates getTotalJMT correctly when interstitialClickJoinToJoinLocusResponse is 0', () => {
|
|
716
1859
|
cdl.saveTimestamp({
|
|
717
|
-
key: 'internal.client.interstitial-window.
|
|
1860
|
+
key: 'internal.client.meeting.interstitial-window.showed',
|
|
718
1861
|
value: 40,
|
|
719
1862
|
});
|
|
720
1863
|
cdl.saveLatency('internal.click.to.interstitial', 12);
|
|
@@ -722,12 +1865,14 @@ describe('internal-plugin-metrics', () => {
|
|
|
722
1865
|
key: 'client.locus.join.response',
|
|
723
1866
|
value: 40,
|
|
724
1867
|
});
|
|
1868
|
+
// showedToJoinLocusResponse = 0, showInterstitialTime = 0
|
|
1869
|
+
// total = 12 + 0 - 0 = 12
|
|
725
1870
|
assert.deepEqual(cdl.getTotalJMT(), 12);
|
|
726
1871
|
});
|
|
727
1872
|
|
|
728
1873
|
it('calculates getTotalJMT correctly when both clickToInterstitial and interstitialClickJoinToJoinLocusResponse are 0', () => {
|
|
729
1874
|
cdl.saveTimestamp({
|
|
730
|
-
key: 'internal.client.interstitial-window.
|
|
1875
|
+
key: 'internal.client.meeting.interstitial-window.showed',
|
|
731
1876
|
value: 40,
|
|
732
1877
|
});
|
|
733
1878
|
cdl.saveLatency('internal.click.to.interstitial', 0);
|
|
@@ -740,7 +1885,7 @@ describe('internal-plugin-metrics', () => {
|
|
|
740
1885
|
|
|
741
1886
|
it('calculates getTotalJMT correctly when both clickToInterstitial is not a number', () => {
|
|
742
1887
|
cdl.saveTimestamp({
|
|
743
|
-
key: 'internal.client.interstitial-window.
|
|
1888
|
+
key: 'internal.client.meeting.interstitial-window.showed',
|
|
744
1889
|
value: 40,
|
|
745
1890
|
});
|
|
746
1891
|
cdl.saveLatency('internal.click.to.interstitial', 'eleven' as unknown as number);
|
|
@@ -753,7 +1898,7 @@ describe('internal-plugin-metrics', () => {
|
|
|
753
1898
|
|
|
754
1899
|
it('calculates getTotalJMT correctly when it is greater than MAX_INTEGER', () => {
|
|
755
1900
|
cdl.saveTimestamp({
|
|
756
|
-
key: 'internal.client.interstitial-window.
|
|
1901
|
+
key: 'internal.client.meeting.interstitial-window.showed',
|
|
757
1902
|
value: 5,
|
|
758
1903
|
});
|
|
759
1904
|
cdl.saveTimestamp({
|
|
@@ -765,14 +1910,7 @@ describe('internal-plugin-metrics', () => {
|
|
|
765
1910
|
});
|
|
766
1911
|
|
|
767
1912
|
it('calculates getTotalJMTWithUserDelay correctly', () => {
|
|
768
|
-
cdl.
|
|
769
|
-
key: 'internal.client.interstitial-window.click.joinbutton',
|
|
770
|
-
value: 5,
|
|
771
|
-
});
|
|
772
|
-
cdl.saveTimestamp({
|
|
773
|
-
key: 'internal.client.meeting.click.joinbutton',
|
|
774
|
-
value: 10,
|
|
775
|
-
});
|
|
1913
|
+
cdl.saveLatency('internal.click.to.interstitial.with.user.delay', 10);
|
|
776
1914
|
cdl.saveTimestamp({
|
|
777
1915
|
key: 'internal.client.meeting.interstitial-window.showed',
|
|
778
1916
|
value: 20,
|
|
@@ -853,65 +1991,79 @@ describe('internal-plugin-metrics', () => {
|
|
|
853
1991
|
});
|
|
854
1992
|
|
|
855
1993
|
it('calculates getTotalMediaJMT correctly with lobby exiting before media-engine.ready', () => {
|
|
856
|
-
cdl.
|
|
1994
|
+
cdl.saveLatency('internal.click.to.interstitial', 3);
|
|
1995
|
+
// clickToInterstitial = 3
|
|
857
1996
|
cdl.saveTimestamp({key: 'internal.client.meeting.interstitial-window.showed', value: 8});
|
|
858
|
-
// clickToInterstitial = 8 - 5 = 3
|
|
859
1997
|
cdl.saveTimestamp({key: 'internal.client.interstitial-window.click.joinbutton', value: 10});
|
|
860
1998
|
cdl.saveTimestamp({key: 'client.media-engine.ready', value: 50});
|
|
861
|
-
//
|
|
862
|
-
|
|
1999
|
+
// interstitialShowedToMediaEngineReady = 50 - 8 = 42
|
|
2000
|
+
// showInterstitialTime = 10 - 8 = 2
|
|
2001
|
+
cdl.saveTimestamp({key: 'client.lobby.entered', value: 20});
|
|
863
2002
|
cdl.saveTimestamp({key: 'client.lobby.exited', value: 30});
|
|
864
2003
|
// stayLobbyTimeCappedByMediaEngineReady = min(30, 50) - 20 = 10
|
|
865
|
-
// total = 3 +
|
|
2004
|
+
// total = 3 + 42 - 2 - 10 = 33
|
|
866
2005
|
assert.deepEqual(cdl.getTotalMediaJMT(), 33);
|
|
867
2006
|
});
|
|
868
2007
|
|
|
869
2008
|
it('calculates getTotalMediaJMT correctly without lobby', () => {
|
|
870
|
-
cdl.
|
|
871
|
-
cdl.saveTimestamp({key: 'internal.client.meeting.interstitial-window.showed', value: 8});
|
|
2009
|
+
cdl.saveLatency('internal.click.to.interstitial', 3);
|
|
872
2010
|
// clickToInterstitial = 3
|
|
2011
|
+
cdl.saveTimestamp({key: 'internal.client.meeting.interstitial-window.showed', value: 8});
|
|
873
2012
|
cdl.saveTimestamp({key: 'internal.client.interstitial-window.click.joinbutton', value: 10});
|
|
874
2013
|
cdl.saveTimestamp({key: 'client.media-engine.ready', value: 50});
|
|
875
|
-
//
|
|
876
|
-
|
|
877
|
-
// no client.lobby.
|
|
878
|
-
//
|
|
879
|
-
|
|
880
|
-
assert.deepEqual(cdl.getTotalMediaJMT(), 13);
|
|
2014
|
+
// interstitialShowedToMediaEngineReady = 50 - 8 = 42
|
|
2015
|
+
// showInterstitialTime = 10 - 8 = 2
|
|
2016
|
+
// no client.lobby.entered → stayLobbyTimeCappedByMediaEngineReady = 0
|
|
2017
|
+
// total = 3 + 42 - 2 - 0 = 43
|
|
2018
|
+
assert.deepEqual(cdl.getTotalMediaJMT(), 43);
|
|
881
2019
|
});
|
|
882
2020
|
|
|
883
2021
|
it('calculates getTotalMediaJMT correctly with lobby exiting after media-engine.ready', () => {
|
|
884
|
-
cdl.
|
|
885
|
-
cdl.saveTimestamp({key: 'internal.client.meeting.interstitial-window.showed', value: 8});
|
|
2022
|
+
cdl.saveLatency('internal.click.to.interstitial', 3);
|
|
886
2023
|
// clickToInterstitial = 3
|
|
2024
|
+
cdl.saveTimestamp({key: 'internal.client.meeting.interstitial-window.showed', value: 8});
|
|
887
2025
|
cdl.saveTimestamp({key: 'internal.client.interstitial-window.click.joinbutton', value: 10});
|
|
888
2026
|
cdl.saveTimestamp({key: 'client.media-engine.ready', value: 50});
|
|
889
|
-
//
|
|
890
|
-
|
|
2027
|
+
// interstitialShowedToMediaEngineReady = 50 - 8 = 42
|
|
2028
|
+
// showInterstitialTime = 10 - 8 = 2
|
|
2029
|
+
cdl.saveTimestamp({key: 'client.lobby.entered', value: 20});
|
|
891
2030
|
cdl.saveTimestamp({key: 'client.lobby.exited', value: 60});
|
|
892
2031
|
// stayLobbyTimeCappedByMediaEngineReady = min(60, 50) - 20 = 30
|
|
893
|
-
// total = 3 +
|
|
2032
|
+
// total = 3 + 42 - 2 - 30 = 13
|
|
894
2033
|
assert.deepEqual(cdl.getTotalMediaJMT(), 13);
|
|
895
2034
|
});
|
|
896
2035
|
|
|
897
2036
|
it('calculates getTotalMediaJMT correctly when it is greater than MAX_INTEGER', () => {
|
|
898
|
-
cdl.
|
|
899
|
-
cdl.saveTimestamp({key: 'internal.client.meeting.interstitial-window.showed', value:
|
|
2037
|
+
cdl.saveLatency('internal.click.to.interstitial', 5);
|
|
2038
|
+
cdl.saveTimestamp({key: 'internal.client.meeting.interstitial-window.showed', value: 10});
|
|
900
2039
|
cdl.saveTimestamp({key: 'internal.client.interstitial-window.click.joinbutton', value: 10});
|
|
901
2040
|
cdl.saveTimestamp({key: 'client.media-engine.ready', value: 4294967400});
|
|
902
|
-
cdl.saveTimestamp({key: 'client.
|
|
2041
|
+
cdl.saveTimestamp({key: 'client.lobby.entered', value: 28});
|
|
903
2042
|
cdl.saveTimestamp({key: 'client.lobby.exited', value: 30});
|
|
904
2043
|
assert.deepEqual(cdl.getTotalMediaJMT(), 2147483647);
|
|
905
2044
|
});
|
|
906
2045
|
|
|
907
2046
|
it('returns undefined for getTotalMediaJMT when media-engine.ready is missing', () => {
|
|
908
|
-
cdl.
|
|
2047
|
+
cdl.saveLatency('internal.click.to.interstitial', 3);
|
|
909
2048
|
cdl.saveTimestamp({key: 'internal.client.meeting.interstitial-window.showed', value: 8});
|
|
910
2049
|
cdl.saveTimestamp({key: 'internal.client.interstitial-window.click.joinbutton', value: 10});
|
|
911
2050
|
cdl.saveTimestamp({key: 'client.locus.join.response', value: 20});
|
|
912
2051
|
assert.deepEqual(cdl.getTotalMediaJMT(), undefined);
|
|
913
2052
|
});
|
|
914
2053
|
|
|
2054
|
+
it('calculates getTotalMediaJMT correctly when there is no lobby and stayLobbyTime defaults to 0', () => {
|
|
2055
|
+
cdl.saveLatency('internal.click.to.interstitial', 3);
|
|
2056
|
+
// clickToInterstitial = 3
|
|
2057
|
+
cdl.saveTimestamp({key: 'internal.client.meeting.interstitial-window.showed', value: 8});
|
|
2058
|
+
cdl.saveTimestamp({key: 'internal.client.interstitial-window.click.joinbutton', value: 10});
|
|
2059
|
+
cdl.saveTimestamp({key: 'client.media-engine.ready', value: 50});
|
|
2060
|
+
// interstitialShowedToMediaEngineReady = 50 - 8 = 42
|
|
2061
|
+
// showInterstitialTime = 10 - 8 = 2
|
|
2062
|
+
// no client.lobby.entered → stayLobbyTimeCappedByMediaEngineReady = 0
|
|
2063
|
+
// total = 3 + 42 - 2 - 0 = 43
|
|
2064
|
+
assert.deepEqual(cdl.getTotalMediaJMT(), 43);
|
|
2065
|
+
});
|
|
2066
|
+
|
|
915
2067
|
it('calculates getTotalMediaJMTWithUserDelay correctly', () => {
|
|
916
2068
|
cdl.saveLatency('internal.click.to.interstitial.with.user.delay', 7);
|
|
917
2069
|
// clickToInterstitialWithUserDelay = 7
|
|
@@ -923,9 +2075,9 @@ describe('internal-plugin-metrics', () => {
|
|
|
923
2075
|
});
|
|
924
2076
|
|
|
925
2077
|
it('calculates getTotalMediaJMTWithUserDelay correctly for guest join', () => {
|
|
926
|
-
cdl.
|
|
2078
|
+
cdl.saveLatency('internal.click.to.interstitial.with.user.delay', 3);
|
|
2079
|
+
// clickToInterstitialWithUserDelay = 3
|
|
927
2080
|
cdl.saveTimestamp({key: 'internal.client.meeting.interstitial-window.showed', value: 8});
|
|
928
|
-
// clickToInterstitialWithUserDelay = 8 - 5 = 3
|
|
929
2081
|
cdl.saveTimestamp({key: 'client.media-engine.ready', value: 50});
|
|
930
2082
|
// interstitialShowedToMediaEngineReady = 50 - 8 = 42
|
|
931
2083
|
// total = 3 + 42 = 45
|
|
@@ -988,6 +2140,11 @@ describe('internal-plugin-metrics', () => {
|
|
|
988
2140
|
});
|
|
989
2141
|
|
|
990
2142
|
it('calculates getClientJMT correctly', () => {
|
|
2143
|
+
cdl.saveLatency('internal.click.to.interstitial.for.client.jmt', 5);
|
|
2144
|
+
cdl.saveTimestamp({
|
|
2145
|
+
key: 'internal.client.meeting.interstitial-window.showed',
|
|
2146
|
+
value: 1,
|
|
2147
|
+
});
|
|
991
2148
|
cdl.saveTimestamp({
|
|
992
2149
|
key: 'internal.client.interstitial-window.click.joinbutton',
|
|
993
2150
|
value: 2,
|
|
@@ -996,19 +2153,30 @@ describe('internal-plugin-metrics', () => {
|
|
|
996
2153
|
key: 'client.locus.join.request',
|
|
997
2154
|
value: 6,
|
|
998
2155
|
});
|
|
2156
|
+
// showedToLocusJoinRequest = 6-1 = 5, showInterstitialTime = 2-1 = 1
|
|
2157
|
+
// clickToInterstitialForClientJmt (5) + 5 - 1 = 9
|
|
2158
|
+
assert.deepEqual(cdl.getClientJMT(), 9);
|
|
2159
|
+
});
|
|
2160
|
+
|
|
2161
|
+
it('returns undefined for getClientJMT when clickToInterstitialForClientJmt is missing', () => {
|
|
999
2162
|
cdl.saveTimestamp({
|
|
1000
|
-
key: 'client.
|
|
1001
|
-
value:
|
|
2163
|
+
key: 'internal.client.meeting.interstitial-window.showed',
|
|
2164
|
+
value: 1,
|
|
1002
2165
|
});
|
|
1003
2166
|
cdl.saveTimestamp({
|
|
1004
|
-
key: 'client.
|
|
1005
|
-
value:
|
|
2167
|
+
key: 'internal.client.interstitial-window.click.joinbutton',
|
|
2168
|
+
value: 2,
|
|
1006
2169
|
});
|
|
1007
2170
|
cdl.saveTimestamp({
|
|
1008
|
-
key: 'client.
|
|
1009
|
-
value:
|
|
2171
|
+
key: 'client.locus.join.request',
|
|
2172
|
+
value: 6,
|
|
1010
2173
|
});
|
|
1011
|
-
assert.deepEqual(cdl.getClientJMT(),
|
|
2174
|
+
assert.deepEqual(cdl.getClientJMT(), undefined);
|
|
2175
|
+
});
|
|
2176
|
+
|
|
2177
|
+
it('returns undefined for getClientJMT when interstitialJoinToLocusJoinRequest is missing', () => {
|
|
2178
|
+
cdl.saveLatency('internal.click.to.interstitial.for.client.jmt', 5);
|
|
2179
|
+
assert.deepEqual(cdl.getClientJMT(), undefined);
|
|
1012
2180
|
});
|
|
1013
2181
|
|
|
1014
2182
|
it('calculates getAudioJoinRespRxStart correctly', () => {
|
|
@@ -1060,12 +2228,16 @@ describe('internal-plugin-metrics', () => {
|
|
|
1060
2228
|
});
|
|
1061
2229
|
|
|
1062
2230
|
it('calculates getInterstitialToMediaOKJMT correctly', () => {
|
|
2231
|
+
cdl.saveTimestamp({
|
|
2232
|
+
key: 'internal.client.meeting.interstitial-window.showed',
|
|
2233
|
+
value: 2,
|
|
2234
|
+
});
|
|
1063
2235
|
cdl.saveTimestamp({
|
|
1064
2236
|
key: 'internal.client.interstitial-window.click.joinbutton',
|
|
1065
2237
|
value: 4,
|
|
1066
2238
|
});
|
|
1067
2239
|
cdl.saveTimestamp({
|
|
1068
|
-
key: 'client.
|
|
2240
|
+
key: 'client.lobby.entered',
|
|
1069
2241
|
value: 10,
|
|
1070
2242
|
});
|
|
1071
2243
|
cdl.saveTimestamp({
|
|
@@ -1076,21 +2248,28 @@ describe('internal-plugin-metrics', () => {
|
|
|
1076
2248
|
key: 'client.ice.end',
|
|
1077
2249
|
value: 14,
|
|
1078
2250
|
});
|
|
2251
|
+
// showedToIceEnd = 14-2 = 12, showInterstitialTime = 4-2 = 2
|
|
2252
|
+
// stayLobbyTimeCappedByIceEnd = min(12,14)-10 = 2
|
|
2253
|
+
// result = 12 - 2 - 2 = 8
|
|
1079
2254
|
assert.deepEqual(cdl.getInterstitialToMediaOKJMT(), 8);
|
|
1080
2255
|
});
|
|
1081
2256
|
|
|
1082
2257
|
it('calculates getInterstitialToMediaOKJMT correctly when it is greater than MAX_INTEGER', () => {
|
|
2258
|
+
cdl.saveTimestamp({
|
|
2259
|
+
key: 'internal.client.meeting.interstitial-window.showed',
|
|
2260
|
+
value: 4,
|
|
2261
|
+
});
|
|
1083
2262
|
cdl.saveTimestamp({
|
|
1084
2263
|
key: 'internal.client.interstitial-window.click.joinbutton',
|
|
1085
2264
|
value: 4,
|
|
1086
2265
|
});
|
|
1087
2266
|
cdl.saveTimestamp({
|
|
1088
|
-
key: 'client.
|
|
2267
|
+
key: 'client.lobby.entered',
|
|
1089
2268
|
value: 10,
|
|
1090
2269
|
});
|
|
1091
2270
|
cdl.saveTimestamp({
|
|
1092
2271
|
key: 'client.lobby.exited',
|
|
1093
|
-
value:
|
|
2272
|
+
value: 10,
|
|
1094
2273
|
});
|
|
1095
2274
|
cdl.saveTimestamp({
|
|
1096
2275
|
key: 'client.ice.end',
|
|
@@ -1100,6 +2279,29 @@ describe('internal-plugin-metrics', () => {
|
|
|
1100
2279
|
});
|
|
1101
2280
|
|
|
1102
2281
|
it('calculates getInterstitialToMediaOKJMT correctly without lobby', () => {
|
|
2282
|
+
cdl.saveTimestamp({
|
|
2283
|
+
key: 'internal.client.meeting.interstitial-window.showed',
|
|
2284
|
+
value: 2,
|
|
2285
|
+
});
|
|
2286
|
+
cdl.saveTimestamp({
|
|
2287
|
+
key: 'internal.client.interstitial-window.click.joinbutton',
|
|
2288
|
+
value: 4,
|
|
2289
|
+
});
|
|
2290
|
+
cdl.saveTimestamp({
|
|
2291
|
+
key: 'client.ice.end',
|
|
2292
|
+
value: 14,
|
|
2293
|
+
});
|
|
2294
|
+
// showedToIceEnd = 14-2 = 12, showInterstitialTime = 4-2 = 2
|
|
2295
|
+
// stayLobbyTimeCappedByIceEnd = 0 (no lobby)
|
|
2296
|
+
// result = 12 - 2 - 0 = 10
|
|
2297
|
+
assert.deepEqual(cdl.getInterstitialToMediaOKJMT(), 10);
|
|
2298
|
+
});
|
|
2299
|
+
|
|
2300
|
+
it('calculates getInterstitialToMediaOKJMT correctly when there is no lobby and stayLobbyTime defaults to 0', () => {
|
|
2301
|
+
cdl.saveTimestamp({
|
|
2302
|
+
key: 'internal.client.meeting.interstitial-window.showed',
|
|
2303
|
+
value: 2,
|
|
2304
|
+
});
|
|
1103
2305
|
cdl.saveTimestamp({
|
|
1104
2306
|
key: 'internal.client.interstitial-window.click.joinbutton',
|
|
1105
2307
|
value: 4,
|
|
@@ -1108,6 +2310,9 @@ describe('internal-plugin-metrics', () => {
|
|
|
1108
2310
|
key: 'client.ice.end',
|
|
1109
2311
|
value: 14,
|
|
1110
2312
|
});
|
|
2313
|
+
// showedToIceEnd = 14-2 = 12, showInterstitialTime = 4-2 = 2
|
|
2314
|
+
// stayLobbyTimeCappedByIceEnd = 0 (no lobby)
|
|
2315
|
+
// result = 12 - 2 - 0 = 10
|
|
1111
2316
|
assert.deepEqual(cdl.getInterstitialToMediaOKJMT(), 10);
|
|
1112
2317
|
});
|
|
1113
2318
|
|