@fluid-internal/presence-runtime 2.101.1 → 2.103.0

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.
Files changed (85) hide show
  1. package/dist/packageVersion.d.ts +1 -1
  2. package/dist/packageVersion.js +1 -1
  3. package/dist/packageVersion.js.map +1 -1
  4. package/dist/runtime/extension/containerPresence.d.ts +1 -1
  5. package/dist/runtime/presenceDatastoreManager.d.ts +2 -2
  6. package/dist/runtime/presenceDatastoreManager.d.ts.map +1 -1
  7. package/dist/runtime/presenceDatastoreManager.js.map +1 -1
  8. package/dist/runtime/presenceManager.js.map +1 -1
  9. package/lib/packageVersion.d.ts +1 -1
  10. package/lib/packageVersion.js +1 -1
  11. package/lib/packageVersion.js.map +1 -1
  12. package/lib/runtime/extension/containerPresence.d.ts +1 -1
  13. package/lib/runtime/presenceDatastoreManager.d.ts +2 -2
  14. package/lib/runtime/presenceDatastoreManager.d.ts.map +1 -1
  15. package/lib/runtime/presenceDatastoreManager.js.map +1 -1
  16. package/lib/runtime/presenceManager.js.map +1 -1
  17. package/package.json +14 -14
  18. package/dist/runtime/test/presenceDatastoreManager.spec.js +0 -618
  19. package/dist/runtime/test/presenceDatastoreManager.spec.js.map +0 -1
  20. package/dist/runtime/test/presenceManager.spec.js +0 -651
  21. package/dist/runtime/test/presenceManager.spec.js.map +0 -1
  22. package/dist/states/test/batching.spec.js +0 -843
  23. package/dist/states/test/batching.spec.js.map +0 -1
  24. package/dist/states/test/broadcastControlsTests.js +0 -60
  25. package/dist/states/test/broadcastControlsTests.js.map +0 -1
  26. package/dist/states/test/eventing.spec.js +0 -576
  27. package/dist/states/test/eventing.spec.js.map +0 -1
  28. package/dist/states/test/latestMapValueManager.spec.js +0 -210
  29. package/dist/states/test/latestMapValueManager.spec.js.map +0 -1
  30. package/dist/states/test/latestValueManager.spec.js +0 -193
  31. package/dist/states/test/latestValueManager.spec.js.map +0 -1
  32. package/dist/states/test/mockEphemeralRuntime.js +0 -11
  33. package/dist/states/test/mockEphemeralRuntime.js.map +0 -1
  34. package/dist/states/test/notificationsManager.spec.js +0 -460
  35. package/dist/states/test/notificationsManager.spec.js.map +0 -1
  36. package/dist/states/test/presenceStates.spec.js +0 -73
  37. package/dist/states/test/presenceStates.spec.js.map +0 -1
  38. package/dist/states/test/schemaValidation/protocol.spec.js +0 -246
  39. package/dist/states/test/schemaValidation/protocol.spec.js.map +0 -1
  40. package/dist/states/test/schemaValidation/valueManagers.spec.js +0 -784
  41. package/dist/states/test/schemaValidation/valueManagers.spec.js.map +0 -1
  42. package/dist/states/test/testUtils.js +0 -21
  43. package/dist/states/test/testUtils.js.map +0 -1
  44. package/dist/test/mockEphemeralRuntime.js +0 -175
  45. package/dist/test/mockEphemeralRuntime.js.map +0 -1
  46. package/dist/test/testUtils.js +0 -262
  47. package/dist/test/testUtils.js.map +0 -1
  48. package/dist/test/utils/index.js +0 -27
  49. package/dist/test/utils/index.js.map +0 -1
  50. package/dist/utils/test/timerManager.spec.js +0 -93
  51. package/dist/utils/test/timerManager.spec.js.map +0 -1
  52. package/lib/runtime/test/presenceDatastoreManager.spec.js +0 -616
  53. package/lib/runtime/test/presenceDatastoreManager.spec.js.map +0 -1
  54. package/lib/runtime/test/presenceManager.spec.js +0 -649
  55. package/lib/runtime/test/presenceManager.spec.js.map +0 -1
  56. package/lib/states/test/batching.spec.js +0 -841
  57. package/lib/states/test/batching.spec.js.map +0 -1
  58. package/lib/states/test/broadcastControlsTests.js +0 -56
  59. package/lib/states/test/broadcastControlsTests.js.map +0 -1
  60. package/lib/states/test/eventing.spec.js +0 -574
  61. package/lib/states/test/eventing.spec.js.map +0 -1
  62. package/lib/states/test/latestMapValueManager.spec.js +0 -206
  63. package/lib/states/test/latestMapValueManager.spec.js.map +0 -1
  64. package/lib/states/test/latestValueManager.spec.js +0 -189
  65. package/lib/states/test/latestValueManager.spec.js.map +0 -1
  66. package/lib/states/test/mockEphemeralRuntime.js +0 -6
  67. package/lib/states/test/mockEphemeralRuntime.js.map +0 -1
  68. package/lib/states/test/notificationsManager.spec.js +0 -456
  69. package/lib/states/test/notificationsManager.spec.js.map +0 -1
  70. package/lib/states/test/presenceStates.spec.js +0 -69
  71. package/lib/states/test/presenceStates.spec.js.map +0 -1
  72. package/lib/states/test/schemaValidation/protocol.spec.js +0 -244
  73. package/lib/states/test/schemaValidation/protocol.spec.js.map +0 -1
  74. package/lib/states/test/schemaValidation/valueManagers.spec.js +0 -782
  75. package/lib/states/test/schemaValidation/valueManagers.spec.js.map +0 -1
  76. package/lib/states/test/testUtils.js +0 -6
  77. package/lib/states/test/testUtils.js.map +0 -1
  78. package/lib/test/mockEphemeralRuntime.js +0 -171
  79. package/lib/test/mockEphemeralRuntime.js.map +0 -1
  80. package/lib/test/testUtils.js +0 -251
  81. package/lib/test/testUtils.js.map +0 -1
  82. package/lib/test/utils/index.js +0 -8
  83. package/lib/test/utils/index.js.map +0 -1
  84. package/lib/utils/test/timerManager.spec.js +0 -91
  85. package/lib/utils/test/timerManager.spec.js.map +0 -1
@@ -1,841 +0,0 @@
1
- /*!
2
- * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
3
- * Licensed under the MIT License.
4
- */
5
- import { strict as assert } from "node:assert";
6
- import { EventAndErrorTrackingLogger } from "@fluidframework/test-utils/internal";
7
- import { describe, it, after, afterEach, before, beforeEach } from "mocha";
8
- import { useFakeTimers } from "sinon";
9
- import { Notifications, StateFactory } from "@fluid-internal/presence-runtime/states";
10
- import { toOpaqueJson } from "@fluid-internal/presence-runtime/utils";
11
- import { MockEphemeralRuntime } from "./mockEphemeralRuntime.js";
12
- import { assertFinalExpectations, initialLocalClientConnectionId, prepareConnectedPresence, localAttendeeId, } from "./testUtils.js";
13
- describe("Presence/States", () => {
14
- describe("batching", () => {
15
- let runtime;
16
- let logger;
17
- const initialTime = 500;
18
- const testStartTime = 1010;
19
- let clock;
20
- let presence;
21
- before(async () => {
22
- clock = useFakeTimers();
23
- });
24
- beforeEach(() => {
25
- logger = new EventAndErrorTrackingLogger();
26
- runtime = new MockEphemeralRuntime(logger);
27
- clock.setSystemTime(initialTime);
28
- // Set up the presence connection.
29
- presence = prepareConnectedPresence(runtime, localAttendeeId, initialLocalClientConnectionId, clock, logger).presence;
30
- // Note that while the initialTime was set to 500, the prepareConnectedPresence call advances
31
- // it. Set a consistent start time for all tests.
32
- const deltaToStart = testStartTime - clock.now;
33
- assert(deltaToStart >= 0);
34
- clock.tick(deltaToStart);
35
- });
36
- afterEach(() => {
37
- // Tick the clock forward by a large amount before resetting it
38
- // in case there are lingering queued signals or timers
39
- clock.tick(1000);
40
- clock.reset();
41
- });
42
- after(() => {
43
- clock.restore();
44
- });
45
- describe("Latest", () => {
46
- it("sends signal immediately when allowable latency is 0", async () => {
47
- runtime.signalsExpected.push([
48
- {
49
- type: "Pres:DatastoreUpdate",
50
- content: {
51
- "sendTimestamp": 1010,
52
- "avgLatency": 10,
53
- "data": {
54
- "system:presence": {
55
- "clientToSessionId": {
56
- [initialLocalClientConnectionId]: {
57
- "rev": 0,
58
- "timestamp": initialTime,
59
- "value": localAttendeeId,
60
- },
61
- },
62
- },
63
- "s:name:testStateWorkspace": {
64
- "count": {
65
- [localAttendeeId]: {
66
- "rev": 0,
67
- "timestamp": 1010,
68
- "value": toOpaqueJson({
69
- "num": 0,
70
- }),
71
- },
72
- },
73
- },
74
- },
75
- },
76
- },
77
- ], [
78
- {
79
- type: "Pres:DatastoreUpdate",
80
- content: {
81
- "sendTimestamp": 1020,
82
- "avgLatency": 10,
83
- "data": {
84
- "system:presence": {
85
- "clientToSessionId": {
86
- [initialLocalClientConnectionId]: {
87
- "rev": 0,
88
- "timestamp": initialTime,
89
- "value": localAttendeeId,
90
- },
91
- },
92
- },
93
- "s:name:testStateWorkspace": {
94
- "count": {
95
- [localAttendeeId]: {
96
- "rev": 1,
97
- "timestamp": 1020,
98
- "value": toOpaqueJson({
99
- "num": 42,
100
- }),
101
- },
102
- },
103
- },
104
- },
105
- },
106
- },
107
- ], [
108
- {
109
- type: "Pres:DatastoreUpdate",
110
- content: {
111
- "sendTimestamp": 1020,
112
- "avgLatency": 10,
113
- "data": {
114
- "system:presence": {
115
- "clientToSessionId": {
116
- [initialLocalClientConnectionId]: {
117
- "rev": 0,
118
- "timestamp": initialTime,
119
- "value": localAttendeeId,
120
- },
121
- },
122
- },
123
- "s:name:testStateWorkspace": {
124
- "count": {
125
- [localAttendeeId]: {
126
- "rev": 2,
127
- "timestamp": 1020,
128
- "value": toOpaqueJson({
129
- "num": 84,
130
- }),
131
- },
132
- },
133
- },
134
- },
135
- },
136
- },
137
- ]);
138
- // Configure a state workspace
139
- // SIGNAL #1 - intial data is sent immediately
140
- const stateWorkspace = presence.states.getWorkspace("name:testStateWorkspace", {
141
- count: StateFactory.latest({
142
- local: { num: 0 },
143
- settings: { allowableUpdateLatencyMs: 0 },
144
- }),
145
- });
146
- const { count } = stateWorkspace.states;
147
- clock.tick(10); // Time is now 1020
148
- // SIGNAL #2
149
- count.local = { num: 42 };
150
- // SIGNAL #3
151
- count.local = { num: 84 };
152
- assertFinalExpectations(runtime, logger);
153
- });
154
- it("sets timer for default allowableUpdateLatencyMs", async () => {
155
- runtime.signalsExpected.push([
156
- {
157
- type: "Pres:DatastoreUpdate",
158
- content: {
159
- "sendTimestamp": 1070,
160
- "avgLatency": 10,
161
- "data": {
162
- "system:presence": {
163
- "clientToSessionId": {
164
- [initialLocalClientConnectionId]: {
165
- "rev": 0,
166
- "timestamp": initialTime,
167
- "value": localAttendeeId,
168
- },
169
- },
170
- },
171
- "s:name:testStateWorkspace": {
172
- "count": {
173
- [localAttendeeId]: {
174
- "rev": 0,
175
- "timestamp": 1010,
176
- "value": toOpaqueJson({
177
- "num": 0,
178
- }),
179
- },
180
- },
181
- },
182
- },
183
- },
184
- },
185
- ]);
186
- // Configure a state workspace
187
- presence.states.getWorkspace("name:testStateWorkspace", {
188
- count: StateFactory.latest({
189
- local: { num: 0 } /* default allowableUpdateLatencyMs = 60 */,
190
- }),
191
- }); // will be queued; deadline is now 1070
192
- // SIGNAL #1
193
- // The deadline timer will fire at time 1070 and send a single
194
- // signal with the value from the last signal (num=0).
195
- clock.tick(100); // Time is now 1110
196
- });
197
- it("batches signals sent within default allowableUpdateLatencyMs", async () => {
198
- runtime.signalsExpected.push([
199
- {
200
- type: "Pres:DatastoreUpdate",
201
- content: {
202
- "sendTimestamp": 1070,
203
- "avgLatency": 10,
204
- "data": {
205
- "system:presence": {
206
- "clientToSessionId": {
207
- [initialLocalClientConnectionId]: {
208
- "rev": 0,
209
- "timestamp": initialTime,
210
- "value": localAttendeeId,
211
- },
212
- },
213
- },
214
- "s:name:testStateWorkspace": {
215
- "count": {
216
- [localAttendeeId]: {
217
- "rev": 3,
218
- "timestamp": 1060,
219
- "value": toOpaqueJson({
220
- "num": 22,
221
- }),
222
- },
223
- },
224
- },
225
- },
226
- },
227
- },
228
- ], [
229
- {
230
- type: "Pres:DatastoreUpdate",
231
- content: {
232
- "sendTimestamp": 1150,
233
- "avgLatency": 10,
234
- "data": {
235
- "system:presence": {
236
- "clientToSessionId": {
237
- [initialLocalClientConnectionId]: {
238
- "rev": 0,
239
- "timestamp": initialTime,
240
- "value": localAttendeeId,
241
- },
242
- },
243
- },
244
- "s:name:testStateWorkspace": {
245
- "count": {
246
- [localAttendeeId]: {
247
- "rev": 6,
248
- "timestamp": 1140,
249
- "value": toOpaqueJson({
250
- "num": 90,
251
- }),
252
- },
253
- },
254
- },
255
- },
256
- },
257
- },
258
- ]);
259
- // Configure a state workspace
260
- const stateWorkspace = presence.states.getWorkspace("name:testStateWorkspace", {
261
- count: StateFactory.latest({
262
- local: { num: 0 } /* default allowableUpdateLatencyMs = 60 */,
263
- }),
264
- }); // will be queued; deadline is now 1070
265
- const { count } = stateWorkspace.states;
266
- clock.tick(10); // Time is now 1020
267
- count.local = { num: 12 }; // will be queued; deadline remains 1070
268
- clock.tick(10); // Time is now 1030
269
- count.local = { num: 34 }; // will be queued; deadline remains 1070
270
- clock.tick(30); // Time is now 1060
271
- count.local = { num: 22 }; // will be queued; deadline remains 1070
272
- // SIGNAL #1
273
- // The deadline timer will fire at time 1070 and send a single
274
- // signal with the value from the last signal (num=22).
275
- // It's necessary to tick the timer beyond the deadline so the timer will fire.
276
- clock.tick(20); // Time is now 1080
277
- clock.tick(10); // Time is now 1090
278
- count.local = { num: 56 }; // will be queued; deadline is set to 1150
279
- clock.tick(40); // Time is now 1130
280
- count.local = { num: 78 }; // will be queued; deadline remains 1150
281
- clock.tick(10); // Time is now 1140
282
- count.local = { num: 90 }; // will be queued; deadline remains 1150
283
- // SIGNAL #2
284
- // The deadline timer will fire at time 1150 and send a single
285
- // signal with the value from the last signal (num=90).
286
- // It's necessary to tick the timer beyond the deadline so the timer will fire.
287
- clock.tick(30); // Time is now 1180
288
- });
289
- it("batches signals sent within a specified allowableUpdateLatencyMs", async () => {
290
- runtime.signalsExpected.push([
291
- {
292
- type: "Pres:DatastoreUpdate",
293
- content: {
294
- "sendTimestamp": 1110,
295
- "avgLatency": 10,
296
- "data": {
297
- "system:presence": {
298
- "clientToSessionId": {
299
- [initialLocalClientConnectionId]: {
300
- "rev": 0,
301
- "timestamp": initialTime,
302
- "value": localAttendeeId,
303
- },
304
- },
305
- },
306
- "s:name:testStateWorkspace": {
307
- "count": {
308
- [localAttendeeId]: {
309
- "rev": 2,
310
- "timestamp": 1100,
311
- "value": toOpaqueJson({
312
- "num": 34,
313
- }),
314
- },
315
- },
316
- },
317
- },
318
- },
319
- },
320
- ], [
321
- {
322
- type: "Pres:DatastoreUpdate",
323
- content: {
324
- "sendTimestamp": 1240,
325
- "avgLatency": 10,
326
- "data": {
327
- "system:presence": {
328
- "clientToSessionId": {
329
- [initialLocalClientConnectionId]: {
330
- "rev": 0,
331
- "timestamp": initialTime,
332
- "value": localAttendeeId,
333
- },
334
- },
335
- },
336
- "s:name:testStateWorkspace": {
337
- "count": {
338
- [localAttendeeId]: {
339
- "rev": 5,
340
- "timestamp": 1220,
341
- "value": toOpaqueJson({
342
- "num": 90,
343
- }),
344
- },
345
- },
346
- },
347
- },
348
- },
349
- },
350
- ]);
351
- // Configure a state workspace
352
- const stateWorkspace = presence.states.getWorkspace("name:testStateWorkspace", {
353
- count: StateFactory.latest({
354
- local: { num: 0 },
355
- settings: { allowableUpdateLatencyMs: 100 },
356
- }),
357
- });
358
- const { count } = stateWorkspace.states;
359
- clock.tick(10); // Time is now 1020
360
- count.local = { num: 12 }; // will be queued; deadline is set to 1120
361
- clock.tick(80); // Time is now 1100
362
- count.local = { num: 34 }; // will be queued; deadline remains 1120
363
- // SIGNAL #1
364
- // The deadline timer will fire at time 1120 and send a single
365
- // signal with the value from the last signal (num=34).
366
- // It's necessary to tick the timer beyond the deadline so the timer will fire.
367
- clock.tick(30); // Time is now 1130
368
- clock.tick(10); // Time is now 1140
369
- count.local = { num: 56 }; // will be queued; deadline is set to 1240
370
- clock.tick(40); // Time is now 1180
371
- count.local = { num: 78 }; // will be queued; deadline remains 1240
372
- clock.tick(40); // Time is now 1220
373
- count.local = { num: 90 }; // will be queued; deadline remains 1240
374
- // SIGNAL #2
375
- // The deadline timer will fire at time 1240 and send a single
376
- // signal with the value from the last signal (num=90).
377
- // It's necessary to tick the timer beyond the deadline so the timer will fire.
378
- clock.tick(30); // Time is now 1250
379
- });
380
- it("queued signal is sent immediately with immediate update message", async () => {
381
- runtime.signalsExpected.push([
382
- {
383
- type: "Pres:DatastoreUpdate",
384
- content: {
385
- "sendTimestamp": 1010,
386
- "avgLatency": 10,
387
- "data": {
388
- "system:presence": {
389
- "clientToSessionId": {
390
- [initialLocalClientConnectionId]: {
391
- "rev": 0,
392
- "timestamp": initialTime,
393
- "value": localAttendeeId,
394
- },
395
- },
396
- },
397
- "s:name:testStateWorkspace": {
398
- "count": {
399
- [localAttendeeId]: {
400
- "rev": 0,
401
- "timestamp": 1010,
402
- "value": toOpaqueJson({
403
- "num": 0,
404
- }),
405
- },
406
- },
407
- "immediateUpdate": {
408
- [localAttendeeId]: {
409
- "rev": 0,
410
- "timestamp": 1010,
411
- "value": toOpaqueJson({
412
- "num": 0,
413
- }),
414
- },
415
- },
416
- },
417
- },
418
- },
419
- },
420
- ], [
421
- {
422
- type: "Pres:DatastoreUpdate",
423
- content: {
424
- "sendTimestamp": 1110,
425
- "avgLatency": 10,
426
- "data": {
427
- "system:presence": {
428
- "clientToSessionId": {
429
- [initialLocalClientConnectionId]: {
430
- "rev": 0,
431
- "timestamp": initialTime,
432
- "value": localAttendeeId,
433
- },
434
- },
435
- },
436
- "s:name:testStateWorkspace": {
437
- "count": {
438
- [localAttendeeId]: {
439
- "rev": 2,
440
- "timestamp": 1100,
441
- "value": toOpaqueJson({
442
- "num": 34,
443
- }),
444
- },
445
- },
446
- "immediateUpdate": {
447
- [localAttendeeId]: {
448
- "rev": 1,
449
- "timestamp": 1110,
450
- "value": toOpaqueJson({
451
- "num": 56,
452
- }),
453
- },
454
- },
455
- },
456
- },
457
- },
458
- },
459
- ]);
460
- // Configure a state workspace
461
- // SIGNAL #1 - this signal is not queued because it contains a State object with a latency of 0,
462
- // so the initial data will be sent immediately.
463
- const stateWorkspace = presence.states.getWorkspace("name:testStateWorkspace", {
464
- count: StateFactory.latest({
465
- local: { num: 0 },
466
- settings: { allowableUpdateLatencyMs: 100 },
467
- }),
468
- immediateUpdate: StateFactory.latest({
469
- local: { num: 0 },
470
- settings: { allowableUpdateLatencyMs: 0 },
471
- }),
472
- });
473
- const { count, immediateUpdate } = stateWorkspace.states;
474
- clock.tick(10); // Time is now 1020
475
- count.local = { num: 12 }; // will be queued; deadline is set to 1120
476
- clock.tick(80); // Time is now 1100
477
- count.local = { num: 34 }; // will be queued; deadline remains 1120
478
- clock.tick(10); // Time is now 1110
479
- // SIGNAL #2
480
- // The following update should cause the queued signals to be merged with this immediately-sent
481
- // signal with the value from the last signal (num=34).
482
- immediateUpdate.local = { num: 56 };
483
- });
484
- it("batches signals with different allowed latencies", async () => {
485
- runtime.signalsExpected.push([
486
- {
487
- type: "Pres:DatastoreUpdate",
488
- content: {
489
- "sendTimestamp": 1060,
490
- "avgLatency": 10,
491
- "data": {
492
- "system:presence": {
493
- "clientToSessionId": {
494
- [initialLocalClientConnectionId]: {
495
- "rev": 0,
496
- "timestamp": initialTime,
497
- "value": localAttendeeId,
498
- },
499
- },
500
- },
501
- "s:name:testStateWorkspace": {
502
- "count": {
503
- [localAttendeeId]: {
504
- "rev": 2,
505
- "timestamp": 1050,
506
- "value": toOpaqueJson({
507
- "num": 34,
508
- }),
509
- },
510
- },
511
- "note": {
512
- [localAttendeeId]: {
513
- "rev": 1,
514
- "timestamp": 1020,
515
- "value": toOpaqueJson({
516
- "message": "will be queued",
517
- }),
518
- },
519
- },
520
- },
521
- },
522
- },
523
- },
524
- ], [
525
- {
526
- type: "Pres:DatastoreUpdate",
527
- content: {
528
- "sendTimestamp": 1110,
529
- "avgLatency": 10,
530
- "data": {
531
- "system:presence": {
532
- "clientToSessionId": {
533
- [initialLocalClientConnectionId]: {
534
- "rev": 0,
535
- "timestamp": initialTime,
536
- "value": localAttendeeId,
537
- },
538
- },
539
- },
540
- "s:name:testStateWorkspace": {
541
- "note": {
542
- [localAttendeeId]: {
543
- "rev": 2,
544
- "timestamp": 1060,
545
- "value": toOpaqueJson({ "message": "final message" }),
546
- },
547
- },
548
- },
549
- },
550
- },
551
- },
552
- ]);
553
- // Configure a state workspace
554
- const stateWorkspace = presence.states.getWorkspace("name:testStateWorkspace", {
555
- count: StateFactory.latest({
556
- local: { num: 0 },
557
- settings: { allowableUpdateLatencyMs: 100 },
558
- }),
559
- note: StateFactory.latest({
560
- local: { message: "" },
561
- settings: { allowableUpdateLatencyMs: 50 },
562
- }),
563
- }); // will be queued, deadline is set to 1060
564
- const { count, note } = stateWorkspace.states;
565
- clock.tick(10); // Time is now 1020
566
- note.local = { message: "will be queued" }; // will be queued, deadline remains 1060
567
- count.local = { num: 12 }; // will be queued; deadline remains 1060
568
- clock.tick(30); // Time is now 1050
569
- count.local = { num: 34 }; // will be queued; deadline remains 1060
570
- // SIGNAL #1
571
- // At time 1060, the deadline timer will fire and send a single signal with the value
572
- // from both workspaces (num=34, message="will be queued").
573
- clock.tick(10); // Time is now 1060
574
- note.local = { message: "final message" }; // will be queued; deadline is 1110
575
- // SIGNAL #2
576
- // At time 1110, the deadline timer will fire and send a single signal with the value
577
- // from the note workspace (message="final message").
578
- // It's necessary to tick the timer beyond the deadline so the timer will fire.
579
- clock.tick(100); // Time is now 1160
580
- });
581
- it("batches signals from multiple workspaces", async () => {
582
- runtime.signalsExpected.push([
583
- {
584
- type: "Pres:DatastoreUpdate",
585
- content: {
586
- "sendTimestamp": 1070,
587
- "avgLatency": 10,
588
- "data": {
589
- "system:presence": {
590
- "clientToSessionId": {
591
- [initialLocalClientConnectionId]: {
592
- "rev": 0,
593
- "timestamp": initialTime,
594
- "value": localAttendeeId,
595
- },
596
- },
597
- },
598
- "s:name:testStateWorkspace": {
599
- "count": {
600
- [localAttendeeId]: {
601
- "rev": 2,
602
- "timestamp": 1050,
603
- "value": toOpaqueJson({
604
- "num": 34,
605
- }),
606
- },
607
- },
608
- },
609
- "s:name:testStateWorkspace2": {
610
- "note": {
611
- [localAttendeeId]: {
612
- "rev": 2,
613
- "timestamp": 1060,
614
- "value": toOpaqueJson({
615
- "message": "final message",
616
- }),
617
- },
618
- },
619
- },
620
- },
621
- },
622
- },
623
- ]);
624
- // Configure two state workspaces
625
- const stateWorkspace = presence.states.getWorkspace("name:testStateWorkspace", {
626
- count: StateFactory.latest({
627
- local: { num: 0 },
628
- settings: { allowableUpdateLatencyMs: 100 },
629
- }),
630
- }); // will be queued, deadline is 1110
631
- const stateWorkspace2 = presence.states.getWorkspace("name:testStateWorkspace2", {
632
- note: StateFactory.latest({
633
- local: { message: "" },
634
- settings: { allowableUpdateLatencyMs: 60 },
635
- }),
636
- }); // will be queued, deadline is 1070
637
- const { count } = stateWorkspace.states;
638
- const { note } = stateWorkspace2.states;
639
- clock.tick(10); // Time is now 1020
640
- note.local = { message: "will be queued" }; // will be queued, deadline is 1070
641
- count.local = { num: 12 }; // will be queued; deadline remains 1070
642
- clock.tick(30); // Time is now 1050
643
- count.local = { num: 34 }; // will be queued; deadline remains 1070
644
- clock.tick(10); // Time is now 1060
645
- note.local = { message: "final message" }; // will be queued; deadline remains 1070
646
- // SIGNAL #1
647
- // The deadline timer will fire at time 1070 and send a single
648
- // signal with the values from the most recent workspace updates (num=34, message="final message").
649
- // It's necessary to tick the timer beyond the deadline so the timer will fire.
650
- clock.tick(30); // Time is now 1090
651
- });
652
- });
653
- describe("NotificationsManager", () => {
654
- it("notification signals are sent immediately", async () => {
655
- runtime.signalsExpected.push([
656
- {
657
- type: "Pres:DatastoreUpdate",
658
- content: {
659
- "sendTimestamp": 1050,
660
- "avgLatency": 10,
661
- "data": {
662
- "system:presence": {
663
- "clientToSessionId": {
664
- [initialLocalClientConnectionId]: {
665
- "rev": 0,
666
- "timestamp": initialTime,
667
- "value": localAttendeeId,
668
- },
669
- },
670
- },
671
- "n:name:testNotificationWorkspace": {
672
- "testEvents": {
673
- [localAttendeeId]: {
674
- "rev": 0,
675
- "timestamp": 0,
676
- "value": toOpaqueJson({ "name": "newId", "args": [77] }),
677
- "ignoreUnmonitored": true,
678
- },
679
- },
680
- },
681
- },
682
- },
683
- },
684
- ], [
685
- {
686
- type: "Pres:DatastoreUpdate",
687
- content: {
688
- "sendTimestamp": 1060,
689
- "avgLatency": 10,
690
- "data": {
691
- "system:presence": {
692
- "clientToSessionId": {
693
- [initialLocalClientConnectionId]: {
694
- "rev": 0,
695
- "timestamp": initialTime,
696
- "value": localAttendeeId,
697
- },
698
- },
699
- },
700
- "n:name:testNotificationWorkspace": {
701
- "testEvents": {
702
- [localAttendeeId]: {
703
- "rev": 0,
704
- "timestamp": 0,
705
- "value": toOpaqueJson({ "name": "newId", "args": [88] }),
706
- "ignoreUnmonitored": true,
707
- },
708
- },
709
- },
710
- },
711
- },
712
- },
713
- ]);
714
- // Configure a notifications workspace
715
- // eslint-disable-next-line @typescript-eslint/no-empty-object-type
716
- const notificationsWorkspace = presence.notifications.getWorkspace("name:testNotificationWorkspace", {});
717
- notificationsWorkspace.add("testEvents", Notifications(
718
- // A default handler is not required
719
- {}));
720
- const { testEvents } = notificationsWorkspace.notifications;
721
- clock.tick(40); // Time is now 1050
722
- // SIGNAL #1
723
- testEvents.emit.broadcast("newId", 77);
724
- clock.tick(10); // Time is now 1060
725
- // SIGNAL #2
726
- testEvents.emit.broadcast("newId", 88);
727
- });
728
- it("notification signals cause queued messages to be sent immediately", async () => {
729
- runtime.signalsExpected.push([
730
- {
731
- type: "Pres:DatastoreUpdate",
732
- content: {
733
- "sendTimestamp": 1060,
734
- "avgLatency": 10,
735
- "data": {
736
- "system:presence": {
737
- "clientToSessionId": {
738
- [initialLocalClientConnectionId]: {
739
- "rev": 0,
740
- "timestamp": initialTime,
741
- "value": localAttendeeId,
742
- },
743
- },
744
- },
745
- "s:name:testStateWorkspace": {
746
- "count": {
747
- [localAttendeeId]: {
748
- "rev": 3,
749
- "timestamp": 1040,
750
- "value": toOpaqueJson({
751
- "num": 56,
752
- }),
753
- },
754
- },
755
- },
756
- "n:name:testNotificationWorkspace": {
757
- "testEvents": {
758
- [localAttendeeId]: {
759
- "rev": 0,
760
- "timestamp": 0,
761
- "value": toOpaqueJson({
762
- "name": "newId",
763
- "args": [99],
764
- }),
765
- "ignoreUnmonitored": true,
766
- },
767
- },
768
- },
769
- },
770
- },
771
- },
772
- ], [
773
- {
774
- type: "Pres:DatastoreUpdate",
775
- content: {
776
- "sendTimestamp": 1090,
777
- "avgLatency": 10,
778
- "data": {
779
- "system:presence": {
780
- "clientToSessionId": {
781
- [initialLocalClientConnectionId]: {
782
- "rev": 0,
783
- "timestamp": initialTime,
784
- "value": localAttendeeId,
785
- },
786
- },
787
- },
788
- "n:name:testNotificationWorkspace": {
789
- "testEvents": {
790
- [localAttendeeId]: {
791
- "rev": 0,
792
- "timestamp": 0,
793
- "value": toOpaqueJson({
794
- "name": "newId",
795
- "args": [111],
796
- }),
797
- "ignoreUnmonitored": true,
798
- },
799
- },
800
- },
801
- },
802
- },
803
- },
804
- ]);
805
- // Configure a state workspace
806
- const stateWorkspace = presence.states.getWorkspace("name:testStateWorkspace", {
807
- count: StateFactory.latest({
808
- local: { num: 0 },
809
- settings: { allowableUpdateLatencyMs: 100 },
810
- }),
811
- }); // will be queued, deadline is 1110
812
- // eslint-disable-next-line @typescript-eslint/no-empty-object-type
813
- const notificationsWorkspace = presence.notifications.getWorkspace("name:testNotificationWorkspace", {});
814
- notificationsWorkspace.add("testEvents", Notifications(
815
- // A default handler is not required
816
- {}));
817
- const { count } = stateWorkspace.states;
818
- const { testEvents } = notificationsWorkspace.notifications;
819
- testEvents.notifications.on("newId", (attendee, newId) => {
820
- // do nothing
821
- });
822
- clock.tick(10); // Time is now 1020
823
- count.local = { num: 12 }; // will be queued, deadline remains 1110
824
- clock.tick(10); // Time is now 1030
825
- count.local = { num: 34 }; // will be queued, deadline remains 1110
826
- clock.tick(10); // Time is now 1040
827
- count.local = { num: 56 }; // will be queued, deadline remains 1110
828
- clock.tick(20); // Time is now 1060
829
- // SIGNAL #1
830
- // The notification below will cause an immediate broadcast of the queued signal
831
- // along with the notification signal.
832
- testEvents.emit.broadcast("newId", 99);
833
- clock.tick(30); // Time is now 1090
834
- // SIGNAL #2
835
- // Immediate broadcast of the notification signal.
836
- testEvents.emit.broadcast("newId", 111);
837
- });
838
- });
839
- });
840
- });
841
- //# sourceMappingURL=batching.spec.js.map