cojson 0.13.5 → 0.13.10

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 (88) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/CHANGELOG.md +16 -0
  3. package/LICENSE.txt +1 -1
  4. package/dist/PeerState.d.ts +6 -0
  5. package/dist/PeerState.d.ts.map +1 -1
  6. package/dist/PeerState.js +43 -0
  7. package/dist/PeerState.js.map +1 -1
  8. package/dist/coValueCore.d.ts +3 -1
  9. package/dist/coValueCore.d.ts.map +1 -1
  10. package/dist/coValueCore.js +26 -8
  11. package/dist/coValueCore.js.map +1 -1
  12. package/dist/coValueState.d.ts +1 -0
  13. package/dist/coValueState.d.ts.map +1 -1
  14. package/dist/coValueState.js +27 -2
  15. package/dist/coValueState.js.map +1 -1
  16. package/dist/coValues/group.d.ts +1 -0
  17. package/dist/coValues/group.d.ts.map +1 -1
  18. package/dist/coValues/group.js +45 -21
  19. package/dist/coValues/group.js.map +1 -1
  20. package/dist/crypto/crypto.d.ts +2 -2
  21. package/dist/crypto/crypto.d.ts.map +1 -1
  22. package/dist/permissions.d.ts +1 -0
  23. package/dist/permissions.d.ts.map +1 -1
  24. package/dist/permissions.js +19 -3
  25. package/dist/permissions.js.map +1 -1
  26. package/dist/storage/FileSystem.d.ts +2 -2
  27. package/dist/storage/FileSystem.d.ts.map +1 -1
  28. package/dist/sync.d.ts +14 -4
  29. package/dist/sync.d.ts.map +1 -1
  30. package/dist/sync.js +146 -146
  31. package/dist/sync.js.map +1 -1
  32. package/dist/tests/SyncStateManager.test.js +51 -46
  33. package/dist/tests/SyncStateManager.test.js.map +1 -1
  34. package/dist/tests/coValueCore.test.js +66 -4
  35. package/dist/tests/coValueCore.test.js.map +1 -1
  36. package/dist/tests/coValueState.test.js +31 -4
  37. package/dist/tests/coValueState.test.js.map +1 -1
  38. package/dist/tests/group.test.js +135 -2
  39. package/dist/tests/group.test.js.map +1 -1
  40. package/dist/tests/messagesTestUtils.d.ts +13 -0
  41. package/dist/tests/messagesTestUtils.d.ts.map +1 -0
  42. package/dist/tests/messagesTestUtils.js +42 -0
  43. package/dist/tests/messagesTestUtils.js.map +1 -0
  44. package/dist/tests/sync.load.test.d.ts +2 -0
  45. package/dist/tests/sync.load.test.d.ts.map +1 -0
  46. package/dist/tests/sync.load.test.js +249 -0
  47. package/dist/tests/sync.load.test.js.map +1 -0
  48. package/dist/tests/sync.mesh.test.d.ts +2 -0
  49. package/dist/tests/sync.mesh.test.d.ts.map +1 -0
  50. package/dist/tests/sync.mesh.test.js +157 -0
  51. package/dist/tests/sync.mesh.test.js.map +1 -0
  52. package/dist/tests/sync.peerReconciliation.test.d.ts +2 -0
  53. package/dist/tests/sync.peerReconciliation.test.d.ts.map +1 -0
  54. package/dist/tests/sync.peerReconciliation.test.js +166 -0
  55. package/dist/tests/sync.peerReconciliation.test.js.map +1 -0
  56. package/dist/tests/sync.storage.test.d.ts +2 -0
  57. package/dist/tests/sync.storage.test.d.ts.map +1 -0
  58. package/dist/tests/sync.storage.test.js +201 -0
  59. package/dist/tests/sync.storage.test.js.map +1 -0
  60. package/dist/tests/sync.test.js +139 -1048
  61. package/dist/tests/sync.test.js.map +1 -1
  62. package/dist/tests/sync.upload.test.d.ts +2 -0
  63. package/dist/tests/sync.upload.test.d.ts.map +1 -0
  64. package/dist/tests/sync.upload.test.js +156 -0
  65. package/dist/tests/sync.upload.test.js.map +1 -0
  66. package/dist/tests/testUtils.d.ts +76 -33
  67. package/dist/tests/testUtils.d.ts.map +1 -1
  68. package/dist/tests/testUtils.js +154 -47
  69. package/dist/tests/testUtils.js.map +1 -1
  70. package/package.json +2 -2
  71. package/src/PeerState.ts +59 -1
  72. package/src/coValueCore.ts +37 -7
  73. package/src/coValueState.ts +34 -3
  74. package/src/coValues/group.ts +83 -45
  75. package/src/permissions.ts +31 -3
  76. package/src/sync.ts +169 -185
  77. package/src/tests/SyncStateManager.test.ts +58 -70
  78. package/src/tests/coValueCore.test.ts +90 -3
  79. package/src/tests/coValueState.test.ts +59 -5
  80. package/src/tests/group.test.ts +250 -2
  81. package/src/tests/messagesTestUtils.ts +75 -0
  82. package/src/tests/sync.load.test.ts +327 -0
  83. package/src/tests/sync.mesh.test.ts +219 -0
  84. package/src/tests/sync.peerReconciliation.test.ts +251 -0
  85. package/src/tests/sync.storage.test.ts +259 -0
  86. package/src/tests/sync.test.ts +170 -1245
  87. package/src/tests/sync.upload.test.ts +202 -0
  88. package/src/tests/testUtils.ts +215 -61
@@ -0,0 +1,249 @@
1
+ import { beforeEach, describe, expect, test } from "vitest";
2
+ import { expectMap } from "../coValue";
3
+ import { SyncMessagesLog, loadCoValueOrFail, setupTestNode, waitFor, } from "./testUtils";
4
+ let jazzCloud = setupTestNode({ isSyncServer: true });
5
+ beforeEach(async () => {
6
+ SyncMessagesLog.clear();
7
+ jazzCloud = setupTestNode({ isSyncServer: true });
8
+ });
9
+ describe("loading coValues from server", () => {
10
+ test("coValue loading", async () => {
11
+ const { node: client } = setupTestNode({
12
+ connected: true,
13
+ });
14
+ const group = jazzCloud.node.createGroup();
15
+ const map = group.createMap();
16
+ map.set("hello", "world", "trusting");
17
+ const mapOnClient = await loadCoValueOrFail(client, map.id);
18
+ expect(mapOnClient.get("hello")).toEqual("world");
19
+ expect(SyncMessagesLog.getMessages({
20
+ Group: group.core,
21
+ Map: map.core,
22
+ })).toMatchInlineSnapshot(`
23
+ [
24
+ "client -> server | LOAD Map sessions: empty",
25
+ "server -> client | CONTENT Group header: true new: After: 0 New: 3",
26
+ "client -> server | KNOWN Group sessions: header/3",
27
+ "server -> client | CONTENT Map header: true new: After: 0 New: 1",
28
+ "client -> server | KNOWN Map sessions: header/1",
29
+ ]
30
+ `);
31
+ });
32
+ test("coValue with parent groups loading", async () => {
33
+ const client = setupTestNode({
34
+ connected: true,
35
+ });
36
+ const group = jazzCloud.node.createGroup();
37
+ const parentGroup = jazzCloud.node.createGroup();
38
+ parentGroup.addMember("everyone", "reader");
39
+ group.extend(parentGroup);
40
+ const map = group.createMap();
41
+ map.set("hello", "world");
42
+ const mapOnClient = await loadCoValueOrFail(client.node, map.id);
43
+ expect(mapOnClient.get("hello")).toEqual("world");
44
+ expect(SyncMessagesLog.getMessages({
45
+ ParentGroup: parentGroup.core,
46
+ Group: group.core,
47
+ Map: map.core,
48
+ })).toMatchInlineSnapshot(`
49
+ [
50
+ "client -> server | LOAD Map sessions: empty",
51
+ "server -> client | CONTENT ParentGroup header: true new: After: 0 New: 6",
52
+ "client -> server | KNOWN ParentGroup sessions: header/6",
53
+ "server -> client | CONTENT Group header: true new: After: 0 New: 5",
54
+ "server -> client | CONTENT Map header: true new: After: 0 New: 1",
55
+ "client -> server | KNOWN Group sessions: header/5",
56
+ "client -> server | KNOWN Map sessions: header/1",
57
+ ]
58
+ `);
59
+ });
60
+ test("updating a coValue while offline", async () => {
61
+ const client = setupTestNode({
62
+ connected: false,
63
+ });
64
+ const { peerState } = client.connectToSyncServer();
65
+ const group = jazzCloud.node.createGroup();
66
+ const map = group.createMap();
67
+ map.set("hello", "world", "trusting");
68
+ const mapOnClient = await loadCoValueOrFail(client.node, map.id);
69
+ expect(mapOnClient.get("hello")).toEqual("world");
70
+ peerState.gracefulShutdown();
71
+ map.set("hello", "updated", "trusting");
72
+ SyncMessagesLog.clear();
73
+ client.connectToSyncServer();
74
+ await map.core.waitForSync();
75
+ expect(mapOnClient.get("hello")).toEqual("updated");
76
+ expect(SyncMessagesLog.getMessages({
77
+ Group: group.core,
78
+ Map: map.core,
79
+ })).toMatchInlineSnapshot(`
80
+ [
81
+ "client -> server | LOAD Group sessions: header/3",
82
+ "server -> client | KNOWN Group sessions: header/3",
83
+ "client -> server | LOAD Map sessions: header/1",
84
+ "server -> client | CONTENT Map header: false new: After: 1 New: 1",
85
+ "client -> server | KNOWN Map sessions: header/2",
86
+ ]
87
+ `);
88
+ });
89
+ test("updating a coValue on both sides while offline", async () => {
90
+ const client = setupTestNode({});
91
+ const { peerState } = client.connectToSyncServer();
92
+ const group = jazzCloud.node.createGroup();
93
+ group.addMember("everyone", "writer");
94
+ const map = group.createMap({
95
+ fromServer: "initial",
96
+ fromClient: "initial",
97
+ });
98
+ const mapOnClient = await loadCoValueOrFail(client.node, map.id);
99
+ peerState.gracefulShutdown();
100
+ map.set("fromServer", "updated", "trusting");
101
+ mapOnClient.set("fromClient", "updated", "trusting");
102
+ SyncMessagesLog.clear();
103
+ client.connectToSyncServer();
104
+ await map.core.waitForSync();
105
+ await mapOnClient.core.waitForSync();
106
+ expect(mapOnClient.get("fromServer")).toEqual("updated");
107
+ expect(mapOnClient.get("fromClient")).toEqual("updated");
108
+ expect(SyncMessagesLog.getMessages({
109
+ Group: group.core,
110
+ Map: map.core,
111
+ })).toMatchInlineSnapshot(`
112
+ [
113
+ "client -> server | LOAD Group sessions: header/5",
114
+ "server -> client | KNOWN Group sessions: header/5",
115
+ "client -> server | LOAD Map sessions: header/2",
116
+ "server -> client | CONTENT Map header: false new: After: 1 New: 1",
117
+ "client -> server | KNOWN Map sessions: header/3",
118
+ "client -> server | CONTENT Map header: false new: After: 0 New: 1",
119
+ "server -> client | KNOWN Map sessions: header/3",
120
+ ]
121
+ `);
122
+ });
123
+ test("wrong optimistic known state should be corrected", async () => {
124
+ const client = setupTestNode({
125
+ connected: true,
126
+ });
127
+ const group = jazzCloud.node.createGroup();
128
+ group.addMember("everyone", "writer");
129
+ const map = group.createMap({
130
+ fromServer: "initial",
131
+ fromClient: "initial",
132
+ });
133
+ // Load the coValue on the client
134
+ await loadCoValueOrFail(client.node, map.id);
135
+ // Forcefully delete the coValue from the client (simulating some data loss)
136
+ client.node.coValuesStore.coValues.delete(map.id);
137
+ map.set("fromServer", "updated", "trusting");
138
+ await waitFor(() => {
139
+ const coValue = expectMap(client.node.expectCoValueLoaded(map.id).getCurrentContent());
140
+ expect(coValue.get("fromServer")).toEqual("updated");
141
+ });
142
+ expect(SyncMessagesLog.getMessages({
143
+ Group: group.core,
144
+ Map: map.core,
145
+ })).toMatchInlineSnapshot(`
146
+ [
147
+ "client -> server | LOAD Map sessions: empty",
148
+ "server -> client | CONTENT Group header: true new: After: 0 New: 5",
149
+ "client -> server | KNOWN Group sessions: header/5",
150
+ "server -> client | CONTENT Map header: true new: After: 0 New: 1",
151
+ "client -> server | KNOWN Map sessions: header/1",
152
+ "server -> client | CONTENT Map header: false new: After: 1 New: 1",
153
+ "client -> server | KNOWN CORRECTION Map sessions: empty",
154
+ "server -> client | CONTENT Map header: true new: After: 0 New: 2",
155
+ "client -> server | KNOWN Map sessions: header/2",
156
+ ]
157
+ `);
158
+ });
159
+ test("unavailable coValue", async () => {
160
+ const group = jazzCloud.node.createGroup();
161
+ group.addMember("everyone", "writer");
162
+ const map = group.createMap({
163
+ fromServer: "initial",
164
+ fromClient: "initial",
165
+ });
166
+ // Makes the CoValues unavailable on the server
167
+ jazzCloud.restart();
168
+ const client = setupTestNode({
169
+ connected: true,
170
+ });
171
+ // Load the coValue on the client
172
+ const value = await client.node.load(map.id);
173
+ expect(value).toEqual("unavailable");
174
+ expect(SyncMessagesLog.getMessages({
175
+ Group: group.core,
176
+ Map: map.core,
177
+ })).toMatchInlineSnapshot(`
178
+ [
179
+ "client -> server | LOAD Map sessions: empty",
180
+ "server -> client | KNOWN Map sessions: empty",
181
+ "client -> server | LOAD Map sessions: empty",
182
+ "server -> client | KNOWN Map sessions: empty",
183
+ ]
184
+ `);
185
+ });
186
+ test("large coValue streaming", async () => {
187
+ const group = jazzCloud.node.createGroup();
188
+ group.addMember("everyone", "writer");
189
+ const largeMap = group.createMap();
190
+ // Generate a large amount of data (about 100MB)
191
+ const dataSize = 1 * 1024 * 1024;
192
+ const chunkSize = 1024; // 1KB chunks
193
+ const chunks = dataSize / chunkSize;
194
+ const value = Buffer.alloc(chunkSize, `value$`).toString("base64");
195
+ for (let i = 0; i < chunks; i++) {
196
+ const key = `key${i}`;
197
+ largeMap.set(key, value, "trusting");
198
+ }
199
+ const client = setupTestNode({
200
+ connected: true,
201
+ });
202
+ await loadCoValueOrFail(client.node, largeMap.id);
203
+ await largeMap.core.waitForSync();
204
+ expect(SyncMessagesLog.getMessages({
205
+ Group: group.core,
206
+ Map: largeMap.core,
207
+ })).toMatchInlineSnapshot(`
208
+ [
209
+ "client -> server | LOAD Map sessions: empty",
210
+ "server -> client | CONTENT Group header: true new: After: 0 New: 5",
211
+ "client -> server | KNOWN Group sessions: header/5",
212
+ "server -> client | CONTENT Map header: true new: ",
213
+ "server -> client | CONTENT Map header: false new: After: 0 New: 73",
214
+ "client -> server | KNOWN Map sessions: header/0",
215
+ "server -> client | CONTENT Map header: false new: After: 73 New: 73",
216
+ "server -> client | CONTENT Map header: false new: After: 146 New: 73",
217
+ "client -> server | KNOWN Map sessions: header/73",
218
+ "server -> client | CONTENT Map header: false new: After: 219 New: 73",
219
+ "server -> client | CONTENT Map header: false new: After: 292 New: 73",
220
+ "client -> server | KNOWN Map sessions: header/146",
221
+ "server -> client | CONTENT Map header: false new: After: 365 New: 73",
222
+ "server -> client | CONTENT Map header: false new: After: 438 New: 73",
223
+ "client -> server | KNOWN Map sessions: header/219",
224
+ "server -> client | CONTENT Map header: false new: After: 511 New: 73",
225
+ "server -> client | CONTENT Map header: false new: After: 584 New: 73",
226
+ "client -> server | KNOWN Map sessions: header/292",
227
+ "server -> client | CONTENT Map header: false new: After: 657 New: 73",
228
+ "server -> client | CONTENT Map header: false new: After: 730 New: 73",
229
+ "client -> server | KNOWN Map sessions: header/365",
230
+ "server -> client | CONTENT Map header: false new: After: 803 New: 73",
231
+ "server -> client | CONTENT Map header: false new: After: 876 New: 73",
232
+ "client -> server | KNOWN Map sessions: header/438",
233
+ "server -> client | CONTENT Map header: false new: After: 949 New: 73",
234
+ "server -> client | CONTENT Map header: false new: After: 1022 New: 2",
235
+ "client -> server | KNOWN Map sessions: header/511",
236
+ "client -> server | KNOWN Map sessions: header/584",
237
+ "client -> server | KNOWN Map sessions: header/657",
238
+ "client -> server | KNOWN Map sessions: header/730",
239
+ "client -> server | KNOWN Map sessions: header/803",
240
+ "client -> server | KNOWN Map sessions: header/876",
241
+ "client -> server | KNOWN Map sessions: header/949",
242
+ "client -> server | KNOWN Map sessions: header/1022",
243
+ "client -> server | KNOWN Map sessions: header/1024",
244
+ ]
245
+ `);
246
+ });
247
+ test.todo("should mark the coValue as unavailable if the peer is closed");
248
+ });
249
+ //# sourceMappingURL=sync.load.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sync.load.test.js","sourceRoot":"","sources":["../../src/tests/sync.load.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=sync.mesh.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sync.mesh.test.d.ts","sourceRoot":"","sources":["../../src/tests/sync.mesh.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,157 @@
1
+ import { beforeEach, describe, expect, test, vi } from "vitest";
2
+ import { SyncMessagesLog, loadCoValueOrFail, setupTestNode, waitFor, } from "./testUtils";
3
+ function setupMesh() {
4
+ const coreServer = setupTestNode({
5
+ isSyncServer: true,
6
+ });
7
+ coreServer.addStoragePeer({
8
+ ourName: "core",
9
+ });
10
+ const edgeItaly = setupTestNode();
11
+ edgeItaly.connectToSyncServer({
12
+ ourName: "edge-italy",
13
+ syncServerName: "core",
14
+ });
15
+ const edgeFrance = setupTestNode();
16
+ edgeFrance.connectToSyncServer({
17
+ ourName: "edge-france",
18
+ syncServerName: "core",
19
+ });
20
+ return { coreServer, edgeItaly, edgeFrance };
21
+ }
22
+ describe("multiple clients syncing with the a cloud-like server mesh", () => {
23
+ let mesh = setupMesh();
24
+ beforeEach(async () => {
25
+ SyncMessagesLog.clear();
26
+ mesh = setupMesh();
27
+ });
28
+ test("loading a coValue created on a different edge", async () => {
29
+ const client = setupTestNode();
30
+ client.connectToSyncServer({
31
+ syncServerName: "edge-italy",
32
+ syncServer: mesh.edgeItaly.node,
33
+ });
34
+ const group = mesh.edgeFrance.node.createGroup();
35
+ const map = group.createMap();
36
+ map.set("hello", "world", "trusting");
37
+ await map.core.waitForSync();
38
+ const mapOnClient = await loadCoValueOrFail(client.node, map.id);
39
+ expect(mapOnClient.get("hello")).toEqual("world");
40
+ expect(SyncMessagesLog.getMessages({
41
+ Group: group.core,
42
+ Map: map.core,
43
+ })).toMatchInlineSnapshot(`
44
+ [
45
+ "edge-france -> core | CONTENT Group header: true new: After: 0 New: 3",
46
+ "core -> edge-france | KNOWN Group sessions: header/3",
47
+ "core -> storage | CONTENT Group header: true new: After: 0 New: 3",
48
+ "edge-france -> core | CONTENT Map header: true new: After: 0 New: 1",
49
+ "storage -> core | KNOWN Group sessions: header/3",
50
+ "core -> edge-france | KNOWN Map sessions: header/1",
51
+ "core -> storage | CONTENT Map header: true new: After: 0 New: 1",
52
+ "storage -> core | KNOWN Map sessions: header/1",
53
+ "client -> edge-italy | LOAD Map sessions: empty",
54
+ "edge-italy -> core | LOAD Map sessions: empty",
55
+ "core -> edge-italy | CONTENT Group header: true new: After: 0 New: 3",
56
+ "edge-italy -> core | KNOWN Group sessions: header/3",
57
+ "core -> edge-italy | CONTENT Map header: true new: After: 0 New: 1",
58
+ "edge-italy -> client | CONTENT Group header: true new: After: 0 New: 3",
59
+ "client -> edge-italy | KNOWN Group sessions: header/3",
60
+ "edge-italy -> core | KNOWN Map sessions: header/1",
61
+ "edge-italy -> client | CONTENT Map header: true new: After: 0 New: 1",
62
+ "client -> edge-italy | KNOWN Map sessions: header/1",
63
+ ]
64
+ `);
65
+ });
66
+ // FIXME: Expected parent group to be loaded: CoValue co_zEKiodKQprnfsi2qfDtsHGCGDSo not yet loaded
67
+ test.skip("coValue created on a different edge with parent groups loading", async () => {
68
+ const client = setupTestNode();
69
+ client.connectToSyncServer({
70
+ syncServerName: "edge-italy",
71
+ syncServer: mesh.edgeItaly.node,
72
+ });
73
+ const group = mesh.edgeFrance.node.createGroup();
74
+ const parentGroup = mesh.edgeItaly.node.createGroup();
75
+ parentGroup.addMember("everyone", "reader");
76
+ group.extend(parentGroup);
77
+ const map = group.createMap();
78
+ map.set("hello", "world");
79
+ await map.core.waitForSync();
80
+ const mapOnClient = await loadCoValueOrFail(client.node, map.id);
81
+ expect(mapOnClient.get("hello")).toEqual("world");
82
+ expect(SyncMessagesLog.getMessages({
83
+ ParentGroup: parentGroup.core,
84
+ Group: group.core,
85
+ Map: map.core,
86
+ })).toMatchInlineSnapshot();
87
+ });
88
+ test("updating a coValue coming from a different edge", async () => {
89
+ const client = setupTestNode();
90
+ client.connectToSyncServer({
91
+ syncServerName: "edge-italy",
92
+ syncServer: mesh.edgeItaly.node,
93
+ });
94
+ const group = mesh.edgeFrance.node.createGroup();
95
+ group.addMember("everyone", "writer");
96
+ const map = group.createMap();
97
+ map.set("hello", "world", "trusting");
98
+ await map.core.waitForSync();
99
+ const mapOnClient = await loadCoValueOrFail(client.node, map.id);
100
+ expect(mapOnClient.get("hello")).toEqual("world");
101
+ SyncMessagesLog.clear(); // We want to focus on the sync messages happening from now
102
+ mapOnClient.set("hello", "updated", "trusting");
103
+ await waitFor(() => {
104
+ expect(map.get("hello")).toEqual("updated");
105
+ });
106
+ expect(SyncMessagesLog.getMessages({
107
+ Group: group.core,
108
+ Map: map.core,
109
+ })).toMatchInlineSnapshot(`
110
+ [
111
+ "client -> edge-italy | CONTENT Map header: false new: After: 0 New: 1",
112
+ "edge-italy -> client | KNOWN Map sessions: header/2",
113
+ "edge-italy -> core | CONTENT Map header: false new: After: 0 New: 1",
114
+ "core -> edge-italy | KNOWN Map sessions: header/2",
115
+ "core -> storage | CONTENT Map header: false new: After: 0 New: 1",
116
+ "storage -> core | KNOWN Map sessions: header/2",
117
+ "core -> edge-france | CONTENT Map header: false new: After: 0 New: 1",
118
+ "edge-france -> core | KNOWN Map sessions: header/2",
119
+ ]
120
+ `);
121
+ });
122
+ test("sync of changes of a coValue with bad signatures should be blocked", async () => {
123
+ const italianClient = setupTestNode();
124
+ const frenchClient = setupTestNode();
125
+ italianClient.connectToSyncServer({
126
+ syncServerName: "edge-italy",
127
+ syncServer: mesh.edgeItaly.node,
128
+ });
129
+ frenchClient.connectToSyncServer({
130
+ syncServerName: "edge-france",
131
+ syncServer: mesh.edgeFrance.node,
132
+ });
133
+ const group = mesh.edgeFrance.node.createGroup();
134
+ const map = group.createMap();
135
+ map.set("hello", "world", "trusting");
136
+ const mapOnFrenchClient = await loadCoValueOrFail(frenchClient.node, map.id);
137
+ const mapOnItalianClient = await loadCoValueOrFail(italianClient.node, map.id);
138
+ expect(mapOnItalianClient.get("hello")).toEqual("world");
139
+ expect(mapOnFrenchClient.get("hello")).toEqual("world");
140
+ // Return an invalid signature on the next transaction
141
+ vi.spyOn(italianClient.node.crypto, "sign").mockReturnValueOnce("signature_z2jYFqH6hey3Yy8EdgjFxDtD7MJWnNMkhBx5snKsBdFRNJgtPSNK73LrAyCjzMjH5f2nsssT5MbYm8r6tKJJGWDEB");
142
+ SyncMessagesLog.clear(); // We want to focus on the sync messages happening from now
143
+ mapOnItalianClient.set("hello", "updated", "trusting");
144
+ await new Promise((resolve) => setTimeout(resolve, 100));
145
+ expect(mapOnFrenchClient.get("hello")).toEqual("world");
146
+ expect(SyncMessagesLog.getMessages({
147
+ Group: group.core,
148
+ Map: map.core,
149
+ })).toMatchInlineSnapshot(`
150
+ [
151
+ "client -> edge-italy | CONTENT Map header: false new: After: 0 New: 1",
152
+ "edge-italy -> client | KNOWN Map sessions: header/1",
153
+ ]
154
+ `);
155
+ });
156
+ });
157
+ //# sourceMappingURL=sync.mesh.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sync.mesh.test.js","sourceRoot":"","sources":["../../src/tests/sync.mesh.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=sync.peerReconciliation.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sync.peerReconciliation.test.d.ts","sourceRoot":"","sources":["../../src/tests/sync.peerReconciliation.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,166 @@
1
+ import { assert, beforeEach, describe, expect, test } from "vitest";
2
+ import { expectMap } from "../coValue";
3
+ import { WasmCrypto } from "../crypto/WasmCrypto";
4
+ import { SyncMessagesLog, setupTestNode, waitFor, } from "./testUtils";
5
+ const Crypto = await WasmCrypto.create();
6
+ let jazzCloud = setupTestNode({ isSyncServer: true });
7
+ beforeEach(async () => {
8
+ SyncMessagesLog.clear();
9
+ jazzCloud = setupTestNode({ isSyncServer: true });
10
+ });
11
+ describe("peer reconciliation", () => {
12
+ test("handle new peer connections", async () => {
13
+ const client = setupTestNode();
14
+ const group = client.node.createGroup();
15
+ const map = group.createMap();
16
+ map.set("hello", "world", "trusting");
17
+ client.connectToSyncServer();
18
+ await new Promise((resolve) => setTimeout(resolve, 100));
19
+ await map.core.waitForSync();
20
+ expect(SyncMessagesLog.getMessages({
21
+ Group: group.core,
22
+ Map: map.core,
23
+ })).toMatchInlineSnapshot(`
24
+ [
25
+ "client -> server | LOAD Group sessions: header/3",
26
+ "server -> client | KNOWN Group sessions: empty",
27
+ "client -> server | LOAD Map sessions: header/1",
28
+ "server -> client | KNOWN Map sessions: empty",
29
+ "client -> server | CONTENT Group header: true new: After: 0 New: 3",
30
+ "server -> client | KNOWN Group sessions: header/3",
31
+ "client -> server | CONTENT Map header: true new: After: 0 New: 1",
32
+ "server -> client | KNOWN Map sessions: header/1",
33
+ ]
34
+ `);
35
+ });
36
+ test("handle peer reconnections", async () => {
37
+ const client = setupTestNode();
38
+ const group = client.node.createGroup();
39
+ const map = group.createMap();
40
+ map.set("hello", "world", "trusting");
41
+ const { peerState } = client.connectToSyncServer();
42
+ await map.core.waitForSync();
43
+ peerState.gracefulShutdown();
44
+ map.set("hello", "updated", "trusting");
45
+ SyncMessagesLog.clear();
46
+ client.connectToSyncServer();
47
+ await map.core.waitForSync();
48
+ const mapOnSyncServer = jazzCloud.node.coValuesStore.get(map.id);
49
+ assert(mapOnSyncServer.state.type === "available");
50
+ expect(expectMap(mapOnSyncServer.state.coValue.getCurrentContent()).get("hello")).toEqual("updated");
51
+ expect(SyncMessagesLog.getMessages({
52
+ Group: group.core,
53
+ Map: map.core,
54
+ })).toMatchInlineSnapshot(`
55
+ [
56
+ "client -> server | LOAD Group sessions: header/3",
57
+ "server -> client | KNOWN Group sessions: header/3",
58
+ "client -> server | LOAD Map sessions: header/2",
59
+ "server -> client | KNOWN Map sessions: header/1",
60
+ "client -> server | CONTENT Map header: false new: After: 1 New: 1",
61
+ "server -> client | KNOWN Map sessions: header/2",
62
+ ]
63
+ `);
64
+ });
65
+ test("correctly handle concurrent peer reconnections", async () => {
66
+ const client = setupTestNode();
67
+ const group = client.node.createGroup();
68
+ const map = group.createMap();
69
+ map.set("hello", "world", "trusting");
70
+ const { peerState } = client.connectToSyncServer();
71
+ await map.core.waitForSync();
72
+ peerState.gracefulShutdown();
73
+ map.set("hello", "updated", "trusting");
74
+ SyncMessagesLog.clear();
75
+ const { peer } = client.connectToSyncServer();
76
+ const { peer: latestPeer } = client.connectToSyncServer();
77
+ await map.core.waitForSync();
78
+ const mapOnSyncServer = jazzCloud.node.coValuesStore.get(map.id);
79
+ assert(mapOnSyncServer.state.type === "available");
80
+ expect(expectMap(mapOnSyncServer.state.coValue.getCurrentContent()).get("hello")).toEqual("updated");
81
+ expect(peer.outgoing).toMatchObject({
82
+ closed: true,
83
+ });
84
+ expect(latestPeer.outgoing).toMatchObject({
85
+ closed: false,
86
+ });
87
+ expect(SyncMessagesLog.getMessages({
88
+ Group: group.core,
89
+ Map: map.core,
90
+ })).toMatchInlineSnapshot(`
91
+ [
92
+ "client -> server | LOAD Group sessions: header/3",
93
+ "server -> client | KNOWN Group sessions: header/3",
94
+ "client -> server | LOAD Map sessions: header/2",
95
+ "server -> client | KNOWN Map sessions: header/1",
96
+ "client -> server | CONTENT Map header: false new: After: 1 New: 1",
97
+ "server -> client | KNOWN Map sessions: header/2",
98
+ ]
99
+ `);
100
+ });
101
+ test("correctly handle server restarts in the middle of a sync", async () => {
102
+ const client = setupTestNode();
103
+ const group = client.node.createGroup();
104
+ const map = group.createMap();
105
+ map.set("hello", "world", "trusting");
106
+ await map.core.waitForSync();
107
+ jazzCloud.restart();
108
+ SyncMessagesLog.clear();
109
+ client.connectToSyncServer();
110
+ map.set("hello", "updated", "trusting");
111
+ await new Promise((resolve) => setTimeout(resolve, 0));
112
+ client.connectToSyncServer();
113
+ await waitFor(() => {
114
+ const mapOnSyncServer = jazzCloud.node.coValuesStore.get(map.id);
115
+ expect(mapOnSyncServer.state.type).toBe("available");
116
+ });
117
+ expect(SyncMessagesLog.getMessages({
118
+ Group: group.core,
119
+ Map: map.core,
120
+ })).toMatchInlineSnapshot(`
121
+ [
122
+ "client -> server | LOAD Group sessions: header/3",
123
+ "server -> client | KNOWN Group sessions: empty",
124
+ "client -> server | LOAD Map sessions: header/2",
125
+ "server -> client | KNOWN Map sessions: empty",
126
+ "client -> server | CONTENT Group header: true new: After: 0 New: 3",
127
+ "server -> client | KNOWN Group sessions: header/3",
128
+ "client -> server | CONTENT Map header: true new: After: 0 New: 2",
129
+ "server -> client | KNOWN Map sessions: header/2",
130
+ "client -> server | LOAD Group sessions: header/3",
131
+ "server -> client | KNOWN Group sessions: header/3",
132
+ "client -> server | LOAD Map sessions: header/2",
133
+ "server -> client | KNOWN Map sessions: header/2",
134
+ ]
135
+ `);
136
+ });
137
+ test.skip("handle peer reconnections with data loss", async () => {
138
+ const client = setupTestNode();
139
+ const group = client.node.createGroup();
140
+ const map = group.createMap();
141
+ map.set("hello", "world", "trusting");
142
+ client.connectToSyncServer();
143
+ await map.core.waitForSync();
144
+ jazzCloud.restart();
145
+ SyncMessagesLog.clear();
146
+ client.connectToSyncServer();
147
+ const mapOnSyncServer = jazzCloud.node.coValuesStore.get(map.id);
148
+ await waitFor(() => {
149
+ expect(mapOnSyncServer.state.type).toBe("available");
150
+ });
151
+ assert(mapOnSyncServer.state.type === "available");
152
+ expect(SyncMessagesLog.getMessages({
153
+ Group: group.core,
154
+ Map: map.core,
155
+ })).toMatchInlineSnapshot(`
156
+ [
157
+ "client -> LOAD Group sessions: header/3",
158
+ "server -> KNOWN Group sessions: empty",
159
+ "client -> LOAD Map sessions: header/1",
160
+ "server -> KNOWN Map sessions: empty",
161
+ ]
162
+ `);
163
+ expect(expectMap(mapOnSyncServer.state.coValue.getCurrentContent()).get("hello")).toEqual("updated");
164
+ });
165
+ });
166
+ //# sourceMappingURL=sync.peerReconciliation.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sync.peerReconciliation.test.js","sourceRoot":"","sources":["../../src/tests/sync.peerReconciliation.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=sync.storage.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sync.storage.test.d.ts","sourceRoot":"","sources":["../../src/tests/sync.storage.test.ts"],"names":[],"mappings":""}