cojson 0.13.15 → 0.13.17
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/.turbo/turbo-build.log +1 -1
- package/CHANGELOG.md +13 -0
- package/dist/coValue.d.ts +2 -0
- package/dist/coValue.d.ts.map +1 -1
- package/dist/coValue.js +1 -0
- package/dist/coValue.js.map +1 -1
- package/dist/coValueCore.d.ts +1 -0
- package/dist/coValueCore.d.ts.map +1 -1
- package/dist/coValueCore.js.map +1 -1
- package/dist/coValueState.d.ts.map +1 -1
- package/dist/coValueState.js +58 -96
- package/dist/coValueState.js.map +1 -1
- package/dist/coValues/coList.d.ts +7 -3
- package/dist/coValues/coList.d.ts.map +1 -1
- package/dist/coValues/coList.js +35 -12
- package/dist/coValues/coList.js.map +1 -1
- package/dist/coValues/coMap.d.ts +1 -0
- package/dist/coValues/coMap.d.ts.map +1 -1
- package/dist/coValues/coMap.js +2 -0
- package/dist/coValues/coMap.js.map +1 -1
- package/dist/coValues/coPlainText.d.ts.map +1 -1
- package/dist/coValues/coPlainText.js +1 -1
- package/dist/coValues/coPlainText.js.map +1 -1
- package/dist/coValues/coStream.d.ts +2 -1
- package/dist/coValues/coStream.d.ts.map +1 -1
- package/dist/coValues/coStream.js +2 -0
- package/dist/coValues/coStream.js.map +1 -1
- package/dist/coreToCoValue.d.ts +2 -1
- package/dist/coreToCoValue.d.ts.map +1 -1
- package/dist/localNode.d.ts.map +1 -1
- package/dist/localNode.js +21 -14
- package/dist/localNode.js.map +1 -1
- package/dist/sync.js +3 -3
- package/dist/sync.js.map +1 -1
- package/dist/tests/coList.test.js +119 -2
- package/dist/tests/coList.test.js.map +1 -1
- package/dist/tests/coMap.test.js +32 -2
- package/dist/tests/coMap.test.js.map +1 -1
- package/dist/tests/coStream.test.js +28 -2
- package/dist/tests/coStream.test.js.map +1 -1
- package/dist/tests/coValueState.test.js +10 -143
- package/dist/tests/coValueState.test.js.map +1 -1
- package/dist/tests/sync.load.test.js +59 -1
- package/dist/tests/sync.load.test.js.map +1 -1
- package/dist/tests/sync.mesh.test.js +48 -1
- package/dist/tests/sync.mesh.test.js.map +1 -1
- package/package.json +1 -1
- package/src/coValue.ts +3 -0
- package/src/coValueCore.ts +1 -0
- package/src/coValueState.ts +67 -122
- package/src/coValues/coList.ts +51 -23
- package/src/coValues/coMap.ts +4 -0
- package/src/coValues/coPlainText.ts +1 -2
- package/src/coValues/coStream.ts +3 -1
- package/src/localNode.ts +29 -18
- package/src/sync.ts +3 -3
- package/src/tests/coList.test.ts +184 -2
- package/src/tests/coMap.test.ts +54 -2
- package/src/tests/coStream.test.ts +56 -2
- package/src/tests/coValueState.test.ts +9 -207
- package/src/tests/sync.load.test.ts +78 -1
- package/src/tests/sync.mesh.test.ts +67 -0
|
@@ -10,26 +10,15 @@ import {
|
|
|
10
10
|
} from "vitest";
|
|
11
11
|
import { PeerState } from "../PeerState";
|
|
12
12
|
import { CoValueCore } from "../coValueCore";
|
|
13
|
-
import {
|
|
13
|
+
import { CoValueState } from "../coValueState";
|
|
14
14
|
import { RawCoID } from "../ids";
|
|
15
15
|
import { Peer } from "../sync";
|
|
16
16
|
import { createTestMetricReader, tearDownTestMetricReader } from "./testUtils";
|
|
17
17
|
|
|
18
|
-
const initialMaxRetries = CO_VALUE_LOADING_CONFIG.MAX_RETRIES;
|
|
19
|
-
|
|
20
|
-
function mockMaxRetries(maxRetries: number) {
|
|
21
|
-
CO_VALUE_LOADING_CONFIG.MAX_RETRIES = maxRetries;
|
|
22
|
-
|
|
23
|
-
onTestFinished(() => {
|
|
24
|
-
CO_VALUE_LOADING_CONFIG.MAX_RETRIES = initialMaxRetries;
|
|
25
|
-
});
|
|
26
|
-
}
|
|
27
|
-
|
|
28
18
|
let metricReader: ReturnType<typeof createTestMetricReader>;
|
|
29
19
|
|
|
30
20
|
beforeEach(() => {
|
|
31
21
|
metricReader = createTestMetricReader();
|
|
32
|
-
mockMaxRetries(5);
|
|
33
22
|
});
|
|
34
23
|
|
|
35
24
|
afterEach(() => {
|
|
@@ -122,51 +111,6 @@ describe("CoValueState", () => {
|
|
|
122
111
|
).toBe(0);
|
|
123
112
|
});
|
|
124
113
|
|
|
125
|
-
test("should retry loading from peers when unsuccessful", async () => {
|
|
126
|
-
vi.useFakeTimers();
|
|
127
|
-
|
|
128
|
-
const peer1 = createMockPeerState(
|
|
129
|
-
{
|
|
130
|
-
id: "peer1",
|
|
131
|
-
role: "server",
|
|
132
|
-
},
|
|
133
|
-
async () => {
|
|
134
|
-
state.markNotFoundInPeer("peer1");
|
|
135
|
-
},
|
|
136
|
-
);
|
|
137
|
-
const peer2 = createMockPeerState(
|
|
138
|
-
{
|
|
139
|
-
id: "peer2",
|
|
140
|
-
role: "server",
|
|
141
|
-
},
|
|
142
|
-
async () => {
|
|
143
|
-
state.markNotFoundInPeer("peer2");
|
|
144
|
-
},
|
|
145
|
-
);
|
|
146
|
-
const mockPeers = [peer1, peer2] as unknown as PeerState[];
|
|
147
|
-
|
|
148
|
-
const state = new CoValueState(mockCoValueId);
|
|
149
|
-
const loadPromise = state.loadFromPeers(mockPeers);
|
|
150
|
-
|
|
151
|
-
// Should attempt CO_VALUE_LOADING_CONFIG.MAX_RETRIES retries
|
|
152
|
-
for (let i = 0; i < CO_VALUE_LOADING_CONFIG.MAX_RETRIES; i++) {
|
|
153
|
-
await vi.runAllTimersAsync();
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
await loadPromise;
|
|
157
|
-
|
|
158
|
-
expect(peer1.pushOutgoingMessage).toHaveBeenCalledTimes(
|
|
159
|
-
CO_VALUE_LOADING_CONFIG.MAX_RETRIES,
|
|
160
|
-
);
|
|
161
|
-
expect(peer2.pushOutgoingMessage).toHaveBeenCalledTimes(
|
|
162
|
-
CO_VALUE_LOADING_CONFIG.MAX_RETRIES,
|
|
163
|
-
);
|
|
164
|
-
expect(state.highLevelState).toBe("unavailable");
|
|
165
|
-
await expect(state.getCoValue()).resolves.toBe("unavailable");
|
|
166
|
-
|
|
167
|
-
vi.useRealTimers();
|
|
168
|
-
});
|
|
169
|
-
|
|
170
114
|
test("should skip errored coValues when loading from peers", async () => {
|
|
171
115
|
vi.useFakeTimers();
|
|
172
116
|
|
|
@@ -194,108 +138,18 @@ describe("CoValueState", () => {
|
|
|
194
138
|
const state = new CoValueState(mockCoValueId);
|
|
195
139
|
const loadPromise = state.loadFromPeers(mockPeers);
|
|
196
140
|
|
|
197
|
-
|
|
198
|
-
for (let i = 0; i < CO_VALUE_LOADING_CONFIG.MAX_RETRIES; i++) {
|
|
199
|
-
await vi.runAllTimersAsync();
|
|
200
|
-
}
|
|
141
|
+
await vi.runAllTimersAsync();
|
|
201
142
|
|
|
202
143
|
await loadPromise;
|
|
203
144
|
|
|
204
145
|
expect(peer1.pushOutgoingMessage).toHaveBeenCalledTimes(1);
|
|
205
|
-
expect(peer2.pushOutgoingMessage).toHaveBeenCalledTimes(
|
|
206
|
-
CO_VALUE_LOADING_CONFIG.MAX_RETRIES,
|
|
207
|
-
);
|
|
146
|
+
expect(peer2.pushOutgoingMessage).toHaveBeenCalledTimes(1);
|
|
208
147
|
expect(state.highLevelState).toBe("unavailable");
|
|
209
148
|
await expect(state.getCoValue()).resolves.toBe("unavailable");
|
|
210
149
|
|
|
211
150
|
vi.useRealTimers();
|
|
212
151
|
});
|
|
213
152
|
|
|
214
|
-
test("should retry only on server peers", async () => {
|
|
215
|
-
vi.useFakeTimers();
|
|
216
|
-
|
|
217
|
-
const peer1 = createMockPeerState(
|
|
218
|
-
{
|
|
219
|
-
id: "peer1",
|
|
220
|
-
role: "storage",
|
|
221
|
-
},
|
|
222
|
-
async () => {
|
|
223
|
-
state.markNotFoundInPeer("peer1");
|
|
224
|
-
},
|
|
225
|
-
);
|
|
226
|
-
const peer2 = createMockPeerState(
|
|
227
|
-
{
|
|
228
|
-
id: "peer2",
|
|
229
|
-
role: "server",
|
|
230
|
-
},
|
|
231
|
-
async () => {
|
|
232
|
-
state.markNotFoundInPeer("peer2");
|
|
233
|
-
},
|
|
234
|
-
);
|
|
235
|
-
const mockPeers = [peer1, peer2] as unknown as PeerState[];
|
|
236
|
-
|
|
237
|
-
const state = new CoValueState(mockCoValueId);
|
|
238
|
-
const loadPromise = state.loadFromPeers(mockPeers);
|
|
239
|
-
|
|
240
|
-
// Should attempt CO_VALUE_LOADING_CONFIG.MAX_RETRIES retries
|
|
241
|
-
for (let i = 0; i < CO_VALUE_LOADING_CONFIG.MAX_RETRIES; i++) {
|
|
242
|
-
await vi.runAllTimersAsync();
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
await loadPromise;
|
|
246
|
-
|
|
247
|
-
expect(peer1.pushOutgoingMessage).toHaveBeenCalledTimes(1);
|
|
248
|
-
expect(peer2.pushOutgoingMessage).toHaveBeenCalledTimes(
|
|
249
|
-
CO_VALUE_LOADING_CONFIG.MAX_RETRIES,
|
|
250
|
-
);
|
|
251
|
-
expect(state.highLevelState).toBe("unavailable");
|
|
252
|
-
await expect(state.getCoValue()).resolves.toEqual("unavailable");
|
|
253
|
-
|
|
254
|
-
vi.useRealTimers();
|
|
255
|
-
});
|
|
256
|
-
|
|
257
|
-
test("should handle the coValues that become available in between of the retries", async () => {
|
|
258
|
-
vi.useFakeTimers();
|
|
259
|
-
|
|
260
|
-
mockMaxRetries(5);
|
|
261
|
-
|
|
262
|
-
let retries = 0;
|
|
263
|
-
|
|
264
|
-
const peer1 = createMockPeerState(
|
|
265
|
-
{
|
|
266
|
-
id: "peer1",
|
|
267
|
-
role: "server",
|
|
268
|
-
},
|
|
269
|
-
async () => {
|
|
270
|
-
retries++;
|
|
271
|
-
state.markNotFoundInPeer("peer1");
|
|
272
|
-
|
|
273
|
-
if (retries === 2) {
|
|
274
|
-
setTimeout(() => {
|
|
275
|
-
state.markAvailable(createMockCoValueCore(mockCoValueId), "peer1");
|
|
276
|
-
}, 100);
|
|
277
|
-
}
|
|
278
|
-
},
|
|
279
|
-
);
|
|
280
|
-
|
|
281
|
-
const mockPeers = [peer1] as unknown as PeerState[];
|
|
282
|
-
|
|
283
|
-
const state = new CoValueState(mockCoValueId);
|
|
284
|
-
const loadPromise = state.loadFromPeers(mockPeers);
|
|
285
|
-
|
|
286
|
-
// Should attempt CO_VALUE_LOADING_CONFIG.MAX_RETRIES retries
|
|
287
|
-
for (let i = 0; i < CO_VALUE_LOADING_CONFIG.MAX_RETRIES + 1; i++) {
|
|
288
|
-
await vi.runAllTimersAsync();
|
|
289
|
-
}
|
|
290
|
-
|
|
291
|
-
await loadPromise;
|
|
292
|
-
|
|
293
|
-
expect(peer1.pushOutgoingMessage).toHaveBeenCalledTimes(2);
|
|
294
|
-
expect(state.highLevelState).toBe("available");
|
|
295
|
-
await expect(state.getCoValue()).resolves.toEqual({ id: mockCoValueId });
|
|
296
|
-
vi.useRealTimers();
|
|
297
|
-
});
|
|
298
|
-
|
|
299
153
|
test("should have a coValue as value property when becomes available after that have been marked as unavailable", async () => {
|
|
300
154
|
vi.useFakeTimers();
|
|
301
155
|
|
|
@@ -314,57 +168,13 @@ describe("CoValueState", () => {
|
|
|
314
168
|
const state = new CoValueState(mockCoValueId);
|
|
315
169
|
const loadPromise = state.loadFromPeers(mockPeers);
|
|
316
170
|
|
|
317
|
-
|
|
318
|
-
for (let i = 0; i < CO_VALUE_LOADING_CONFIG.MAX_RETRIES; i++) {
|
|
319
|
-
await vi.runAllTimersAsync();
|
|
320
|
-
}
|
|
171
|
+
await vi.runAllTimersAsync();
|
|
321
172
|
|
|
322
173
|
state.internalMarkMagicallyAvailable(createMockCoValueCore(mockCoValueId));
|
|
323
174
|
|
|
324
175
|
await loadPromise;
|
|
325
176
|
|
|
326
|
-
expect(peer1.pushOutgoingMessage).toHaveBeenCalledTimes(
|
|
327
|
-
CO_VALUE_LOADING_CONFIG.MAX_RETRIES,
|
|
328
|
-
);
|
|
329
|
-
expect(state.highLevelState).toBe("available");
|
|
330
|
-
await expect(state.getCoValue()).resolves.toEqual({ id: mockCoValueId });
|
|
331
|
-
|
|
332
|
-
vi.useRealTimers();
|
|
333
|
-
});
|
|
334
|
-
|
|
335
|
-
test("should stop retrying when value becomes available", async () => {
|
|
336
|
-
vi.useFakeTimers();
|
|
337
|
-
|
|
338
|
-
mockMaxRetries(5);
|
|
339
|
-
|
|
340
|
-
let run = 1;
|
|
341
|
-
|
|
342
|
-
const peer1 = createMockPeerState(
|
|
343
|
-
{
|
|
344
|
-
id: "peer1",
|
|
345
|
-
role: "server",
|
|
346
|
-
},
|
|
347
|
-
async () => {
|
|
348
|
-
if (run > 2) {
|
|
349
|
-
state.markAvailable(createMockCoValueCore(mockCoValueId), "peer1");
|
|
350
|
-
} else {
|
|
351
|
-
state.markNotFoundInPeer("peer1");
|
|
352
|
-
run++;
|
|
353
|
-
}
|
|
354
|
-
},
|
|
355
|
-
);
|
|
356
|
-
|
|
357
|
-
const mockPeers = [peer1] as unknown as PeerState[];
|
|
358
|
-
|
|
359
|
-
const state = new CoValueState(mockCoValueId);
|
|
360
|
-
const loadPromise = state.loadFromPeers(mockPeers);
|
|
361
|
-
|
|
362
|
-
for (let i = 0; i < CO_VALUE_LOADING_CONFIG.MAX_RETRIES; i++) {
|
|
363
|
-
await vi.runAllTimersAsync();
|
|
364
|
-
}
|
|
365
|
-
await loadPromise;
|
|
366
|
-
|
|
367
|
-
expect(peer1.pushOutgoingMessage).toHaveBeenCalledTimes(3);
|
|
177
|
+
expect(peer1.pushOutgoingMessage).toHaveBeenCalledTimes(1);
|
|
368
178
|
expect(state.highLevelState).toBe("available");
|
|
369
179
|
await expect(state.getCoValue()).resolves.toEqual({ id: mockCoValueId });
|
|
370
180
|
|
|
@@ -398,9 +208,7 @@ describe("CoValueState", () => {
|
|
|
398
208
|
const state = new CoValueState(mockCoValueId);
|
|
399
209
|
const loadPromise = state.loadFromPeers([peer1, peer2]);
|
|
400
210
|
|
|
401
|
-
|
|
402
|
-
await vi.runAllTimersAsync();
|
|
403
|
-
}
|
|
211
|
+
await vi.runAllTimersAsync();
|
|
404
212
|
await loadPromise;
|
|
405
213
|
|
|
406
214
|
expect(peer1.pushOutgoingMessage).toHaveBeenCalledTimes(1);
|
|
@@ -444,9 +252,7 @@ describe("CoValueState", () => {
|
|
|
444
252
|
const state = new CoValueState(mockCoValueId);
|
|
445
253
|
const loadPromise = state.loadFromPeers([peer1, peer2]);
|
|
446
254
|
|
|
447
|
-
|
|
448
|
-
await vi.runAllTimersAsync();
|
|
449
|
-
}
|
|
255
|
+
await vi.runAllTimersAsync();
|
|
450
256
|
await loadPromise;
|
|
451
257
|
|
|
452
258
|
expect(peer1.pushOutgoingMessage).toHaveBeenCalledTimes(0);
|
|
@@ -472,14 +278,10 @@ describe("CoValueState", () => {
|
|
|
472
278
|
const state = new CoValueState(mockCoValueId);
|
|
473
279
|
const loadPromise = state.loadFromPeers([peer1]);
|
|
474
280
|
|
|
475
|
-
|
|
476
|
-
await vi.runAllTimersAsync();
|
|
477
|
-
}
|
|
281
|
+
await vi.runAllTimersAsync();
|
|
478
282
|
await loadPromise;
|
|
479
283
|
|
|
480
|
-
expect(peer1.pushOutgoingMessage).toHaveBeenCalledTimes(
|
|
481
|
-
CO_VALUE_LOADING_CONFIG.MAX_RETRIES,
|
|
482
|
-
);
|
|
284
|
+
expect(peer1.pushOutgoingMessage).toHaveBeenCalledTimes(1);
|
|
483
285
|
|
|
484
286
|
expect(state.highLevelState).toBe("unavailable");
|
|
485
287
|
await expect(state.getCoValue()).resolves.toEqual("unavailable");
|
|
@@ -45,6 +45,53 @@ describe("loading coValues from server", () => {
|
|
|
45
45
|
`);
|
|
46
46
|
});
|
|
47
47
|
|
|
48
|
+
test("unavailable coValue retry", async () => {
|
|
49
|
+
const client = setupTestNode();
|
|
50
|
+
const client2 = setupTestNode();
|
|
51
|
+
|
|
52
|
+
client2.connectToSyncServer({
|
|
53
|
+
ourName: "client2",
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
const group = client.node.createGroup();
|
|
57
|
+
const map = group.createMap();
|
|
58
|
+
map.set("hello", "world", "trusting");
|
|
59
|
+
|
|
60
|
+
const promise = loadCoValueOrFail(client2.node, map.id);
|
|
61
|
+
|
|
62
|
+
await new Promise((resolve) => setTimeout(resolve, 1));
|
|
63
|
+
|
|
64
|
+
client.connectToSyncServer();
|
|
65
|
+
|
|
66
|
+
const mapOnClient2 = await promise;
|
|
67
|
+
|
|
68
|
+
expect(mapOnClient2.get("hello")).toEqual("world");
|
|
69
|
+
|
|
70
|
+
expect(
|
|
71
|
+
SyncMessagesLog.getMessages({
|
|
72
|
+
Group: group.core,
|
|
73
|
+
Map: map.core,
|
|
74
|
+
}),
|
|
75
|
+
).toMatchInlineSnapshot(`
|
|
76
|
+
[
|
|
77
|
+
"client2 -> server | LOAD Map sessions: empty",
|
|
78
|
+
"server -> client2 | KNOWN Map sessions: empty",
|
|
79
|
+
"client -> server | LOAD Group sessions: header/3",
|
|
80
|
+
"client -> server | LOAD Map sessions: header/1",
|
|
81
|
+
"server -> client | KNOWN Group sessions: empty",
|
|
82
|
+
"client -> server | CONTENT Group header: true new: After: 0 New: 3",
|
|
83
|
+
"server -> client | KNOWN Map sessions: empty",
|
|
84
|
+
"client -> server | CONTENT Map header: true new: After: 0 New: 1",
|
|
85
|
+
"server -> client | KNOWN Group sessions: header/3",
|
|
86
|
+
"server -> client | KNOWN Map sessions: header/1",
|
|
87
|
+
"server -> client2 | CONTENT Group header: true new: After: 0 New: 3",
|
|
88
|
+
"client2 -> server | KNOWN Group sessions: header/3",
|
|
89
|
+
"server -> client2 | CONTENT Map header: true new: After: 0 New: 1",
|
|
90
|
+
"client2 -> server | KNOWN Map sessions: header/1",
|
|
91
|
+
]
|
|
92
|
+
`);
|
|
93
|
+
});
|
|
94
|
+
|
|
48
95
|
test("coValue with parent groups loading", async () => {
|
|
49
96
|
const client = setupTestNode({
|
|
50
97
|
connected: true,
|
|
@@ -327,5 +374,35 @@ describe("loading coValues from server", () => {
|
|
|
327
374
|
`);
|
|
328
375
|
});
|
|
329
376
|
|
|
330
|
-
test
|
|
377
|
+
test("should mark the coValue as unavailable if the peer is closed", async () => {
|
|
378
|
+
const client = setupTestNode();
|
|
379
|
+
const { peerState } = client.connectToSyncServer();
|
|
380
|
+
|
|
381
|
+
const group = jazzCloud.node.createGroup();
|
|
382
|
+
group.addMember("everyone", "writer");
|
|
383
|
+
|
|
384
|
+
const map = group.createMap({
|
|
385
|
+
test: "value",
|
|
386
|
+
});
|
|
387
|
+
|
|
388
|
+
const promise = client.node.load(map.id);
|
|
389
|
+
|
|
390
|
+
// Close the peer connection
|
|
391
|
+
peerState.gracefulShutdown();
|
|
392
|
+
|
|
393
|
+
expect(await promise).toEqual("unavailable");
|
|
394
|
+
|
|
395
|
+
expect(
|
|
396
|
+
SyncMessagesLog.getMessages({
|
|
397
|
+
Group: group.core,
|
|
398
|
+
Map: map.core,
|
|
399
|
+
}),
|
|
400
|
+
).toMatchInlineSnapshot(`
|
|
401
|
+
[
|
|
402
|
+
"client -> server | LOAD Map sessions: empty",
|
|
403
|
+
"server -> client | CONTENT Group header: true new: After: 0 New: 5",
|
|
404
|
+
"server -> client | CONTENT Map header: true new: After: 0 New: 1",
|
|
405
|
+
]
|
|
406
|
+
`);
|
|
407
|
+
});
|
|
331
408
|
});
|
|
@@ -3,6 +3,7 @@ import { beforeEach, describe, expect, test, vi } from "vitest";
|
|
|
3
3
|
import { expectMap } from "../coValue";
|
|
4
4
|
import {
|
|
5
5
|
SyncMessagesLog,
|
|
6
|
+
blockMessageTypeOnOutgoingPeer,
|
|
6
7
|
loadCoValueOrFail,
|
|
7
8
|
setupTestNode,
|
|
8
9
|
waitFor,
|
|
@@ -322,4 +323,70 @@ describe("multiple clients syncing with the a cloud-like server mesh", () => {
|
|
|
322
323
|
]
|
|
323
324
|
`);
|
|
324
325
|
});
|
|
326
|
+
|
|
327
|
+
test("load returns the coValue as soon as one of the peers return the content", async () => {
|
|
328
|
+
const client = setupTestNode();
|
|
329
|
+
const coreServer = setupTestNode({
|
|
330
|
+
isSyncServer: true,
|
|
331
|
+
});
|
|
332
|
+
|
|
333
|
+
const { peerOnServer } = client.connectToSyncServer({
|
|
334
|
+
syncServerName: "core",
|
|
335
|
+
});
|
|
336
|
+
|
|
337
|
+
const storage = setupTestNode();
|
|
338
|
+
|
|
339
|
+
const { peer: storagePeer } = client.connectToSyncServer({
|
|
340
|
+
syncServerName: "storage",
|
|
341
|
+
syncServer: storage.node,
|
|
342
|
+
});
|
|
343
|
+
|
|
344
|
+
storagePeer.priority = 100;
|
|
345
|
+
|
|
346
|
+
const group = coreServer.node.createGroup();
|
|
347
|
+
const map = group.createMap();
|
|
348
|
+
|
|
349
|
+
map.set("hello", "world", "trusting");
|
|
350
|
+
|
|
351
|
+
const { peerState } = storage.connectToSyncServer({
|
|
352
|
+
ourName: "storage-of-client",
|
|
353
|
+
syncServerName: "core",
|
|
354
|
+
});
|
|
355
|
+
|
|
356
|
+
await loadCoValueOrFail(storage.node, map.id);
|
|
357
|
+
|
|
358
|
+
peerState.gracefulShutdown();
|
|
359
|
+
|
|
360
|
+
SyncMessagesLog.clear();
|
|
361
|
+
|
|
362
|
+
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
363
|
+
|
|
364
|
+
map.set("hello", "updated", "trusting");
|
|
365
|
+
|
|
366
|
+
// Block the content message from the core peer to simulate the delay on response
|
|
367
|
+
blockMessageTypeOnOutgoingPeer(peerOnServer, "content");
|
|
368
|
+
|
|
369
|
+
const mapOnClient = await loadCoValueOrFail(client.node, map.id);
|
|
370
|
+
|
|
371
|
+
expect(
|
|
372
|
+
SyncMessagesLog.getMessages({
|
|
373
|
+
Group: group.core,
|
|
374
|
+
Map: map.core,
|
|
375
|
+
}),
|
|
376
|
+
).toMatchInlineSnapshot(`
|
|
377
|
+
[
|
|
378
|
+
"client -> storage | LOAD Map sessions: empty",
|
|
379
|
+
"storage -> client | CONTENT Group header: true new: After: 0 New: 3",
|
|
380
|
+
"client -> storage | KNOWN Group sessions: header/3",
|
|
381
|
+
"storage -> client | CONTENT Map header: true new: After: 0 New: 1",
|
|
382
|
+
"client -> core | CONTENT Group header: true new: After: 0 New: 3",
|
|
383
|
+
"client -> storage | KNOWN Map sessions: header/1",
|
|
384
|
+
"core -> client | KNOWN Group sessions: header/3",
|
|
385
|
+
"client -> core | LOAD Map sessions: header/1",
|
|
386
|
+
"client -> core | CONTENT Map header: true new: After: 0 New: 1",
|
|
387
|
+
]
|
|
388
|
+
`);
|
|
389
|
+
|
|
390
|
+
expect(mapOnClient.get("hello")).toEqual("world");
|
|
391
|
+
});
|
|
325
392
|
});
|