cojson 0.13.17 → 0.13.20
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 +18 -0
- package/dist/PeerState.d.ts +4 -1
- package/dist/PeerState.d.ts.map +1 -1
- package/dist/PeerState.js +16 -36
- package/dist/PeerState.js.map +1 -1
- package/dist/SyncStateManager.d.ts.map +1 -1
- package/dist/SyncStateManager.js +2 -3
- package/dist/SyncStateManager.js.map +1 -1
- package/dist/coValue.d.ts +4 -4
- package/dist/coValue.d.ts.map +1 -1
- package/dist/coValue.js +4 -4
- package/dist/coValue.js.map +1 -1
- package/dist/coValueCore/coValueCore.d.ts +143 -0
- package/dist/coValueCore/coValueCore.d.ts.map +1 -0
- package/dist/{coValueCore.js → coValueCore/coValueCore.js} +325 -253
- package/dist/coValueCore/coValueCore.js.map +1 -0
- package/dist/coValueCore/verifiedState.d.ts +65 -0
- package/dist/coValueCore/verifiedState.d.ts.map +1 -0
- package/dist/coValueCore/verifiedState.js +210 -0
- package/dist/coValueCore/verifiedState.js.map +1 -0
- package/dist/coValues/account.d.ts +8 -10
- package/dist/coValues/account.d.ts.map +1 -1
- package/dist/coValues/account.js +12 -13
- package/dist/coValues/account.js.map +1 -1
- package/dist/coValues/coList.d.ts +3 -3
- package/dist/coValues/coList.d.ts.map +1 -1
- package/dist/coValues/coList.js +6 -3
- package/dist/coValues/coList.js.map +1 -1
- package/dist/coValues/coMap.d.ts +3 -3
- package/dist/coValues/coMap.d.ts.map +1 -1
- package/dist/coValues/coMap.js +3 -3
- package/dist/coValues/coMap.js.map +1 -1
- package/dist/coValues/coPlainText.d.ts +2 -2
- package/dist/coValues/coPlainText.d.ts.map +1 -1
- package/dist/coValues/coPlainText.js +4 -4
- package/dist/coValues/coPlainText.js.map +1 -1
- package/dist/coValues/coStream.d.ts +3 -3
- package/dist/coValues/coStream.d.ts.map +1 -1
- package/dist/coValues/coStream.js +3 -3
- package/dist/coValues/coStream.js.map +1 -1
- package/dist/coValues/group.d.ts +7 -2
- package/dist/coValues/group.d.ts.map +1 -1
- package/dist/coValues/group.js +29 -26
- package/dist/coValues/group.js.map +1 -1
- package/dist/coreToCoValue.d.ts +2 -2
- package/dist/coreToCoValue.d.ts.map +1 -1
- package/dist/coreToCoValue.js +10 -14
- package/dist/coreToCoValue.js.map +1 -1
- package/dist/exports.d.ts +6 -5
- package/dist/exports.d.ts.map +1 -1
- package/dist/exports.js +3 -4
- package/dist/exports.js.map +1 -1
- package/dist/localNode.d.ts +30 -24
- package/dist/localNode.d.ts.map +1 -1
- package/dist/localNode.js +147 -173
- package/dist/localNode.js.map +1 -1
- package/dist/permissions.d.ts +2 -1
- package/dist/permissions.d.ts.map +1 -1
- package/dist/permissions.js +15 -11
- package/dist/permissions.js.map +1 -1
- package/dist/priority.d.ts +1 -1
- package/dist/priority.d.ts.map +1 -1
- package/dist/streamUtils.d.ts +5 -5
- package/dist/streamUtils.d.ts.map +1 -1
- package/dist/streamUtils.js +5 -20
- package/dist/streamUtils.js.map +1 -1
- package/dist/sync.d.ts +8 -6
- package/dist/sync.d.ts.map +1 -1
- package/dist/sync.js +121 -74
- package/dist/sync.js.map +1 -1
- package/dist/tests/PeerState.test.js +0 -31
- package/dist/tests/PeerState.test.js.map +1 -1
- package/dist/tests/SyncStateManager.test.js +41 -6
- package/dist/tests/SyncStateManager.test.js.map +1 -1
- package/dist/tests/account.test.js +16 -0
- package/dist/tests/account.test.js.map +1 -1
- package/dist/tests/coList.test.js +19 -16
- package/dist/tests/coList.test.js.map +1 -1
- package/dist/tests/coMap.test.js +12 -13
- package/dist/tests/coMap.test.js.map +1 -1
- package/dist/tests/coPlainText.test.js +9 -10
- package/dist/tests/coPlainText.test.js.map +1 -1
- package/dist/tests/coStream.test.js +22 -17
- package/dist/tests/coStream.test.js.map +1 -1
- package/dist/tests/coValueCore.test.js +22 -28
- package/dist/tests/coValueCore.test.js.map +1 -1
- package/dist/tests/coValueCoreLoadingState.test.d.ts +2 -0
- package/dist/tests/coValueCoreLoadingState.test.d.ts.map +1 -0
- package/dist/tests/{coValueState.test.js → coValueCoreLoadingState.test.js} +62 -46
- package/dist/tests/coValueCoreLoadingState.test.js.map +1 -0
- package/dist/tests/group.test.js +42 -43
- package/dist/tests/group.test.js.map +1 -1
- package/dist/tests/messagesTestUtils.d.ts +2 -2
- package/dist/tests/messagesTestUtils.d.ts.map +1 -1
- package/dist/tests/messagesTestUtils.js +1 -1
- package/dist/tests/messagesTestUtils.js.map +1 -1
- package/dist/tests/permissions.test.js +224 -292
- package/dist/tests/permissions.test.js.map +1 -1
- package/dist/tests/priority.test.js +13 -14
- package/dist/tests/priority.test.js.map +1 -1
- package/dist/tests/sync.auth.test.d.ts +2 -0
- package/dist/tests/sync.auth.test.d.ts.map +1 -0
- package/dist/tests/sync.auth.test.js +190 -0
- package/dist/tests/sync.auth.test.js.map +1 -0
- package/dist/tests/sync.load.test.js +6 -6
- package/dist/tests/sync.load.test.js.map +1 -1
- package/dist/tests/sync.mesh.test.js +25 -12
- package/dist/tests/sync.mesh.test.js.map +1 -1
- package/dist/tests/sync.peerReconciliation.test.js +19 -19
- package/dist/tests/sync.peerReconciliation.test.js.map +1 -1
- package/dist/tests/sync.storage.test.js +20 -13
- package/dist/tests/sync.storage.test.js.map +1 -1
- package/dist/tests/sync.test.js +32 -39
- package/dist/tests/sync.test.js.map +1 -1
- package/dist/tests/sync.upload.test.js +126 -37
- package/dist/tests/sync.upload.test.js.map +1 -1
- package/dist/tests/testUtils.d.ts +35 -17
- package/dist/tests/testUtils.d.ts.map +1 -1
- package/dist/tests/testUtils.js +103 -79
- package/dist/tests/testUtils.js.map +1 -1
- package/dist/typeUtils/expectGroup.js +1 -1
- package/dist/typeUtils/expectGroup.js.map +1 -1
- package/package.json +1 -1
- package/src/PeerState.ts +19 -40
- package/src/SyncStateManager.ts +2 -3
- package/src/coValue.ts +11 -8
- package/src/{coValueCore.ts → coValueCore/coValueCore.ts} +478 -422
- package/src/coValueCore/verifiedState.ts +376 -0
- package/src/coValues/account.ts +20 -25
- package/src/coValues/coList.ts +12 -6
- package/src/coValues/coMap.ts +9 -6
- package/src/coValues/coPlainText.ts +9 -6
- package/src/coValues/coStream.ts +9 -6
- package/src/coValues/group.ts +50 -28
- package/src/coreToCoValue.ts +14 -15
- package/src/exports.ts +9 -7
- package/src/localNode.ts +236 -275
- package/src/permissions.ts +18 -12
- package/src/priority.ts +1 -1
- package/src/streamUtils.ts +7 -34
- package/src/sync.ts +146 -84
- package/src/tests/PeerState.test.ts +0 -37
- package/src/tests/SyncStateManager.test.ts +56 -6
- package/src/tests/account.test.ts +24 -0
- package/src/tests/coList.test.ts +21 -15
- package/src/tests/coMap.test.ts +12 -13
- package/src/tests/coPlainText.test.ts +12 -9
- package/src/tests/coStream.test.ts +25 -16
- package/src/tests/coValueCore.test.ts +30 -27
- package/src/tests/{coValueState.test.ts → coValueCoreLoadingState.test.ts} +67 -57
- package/src/tests/group.test.ts +44 -69
- package/src/tests/messagesTestUtils.ts +3 -8
- package/src/tests/permissions.test.ts +283 -449
- package/src/tests/priority.test.ts +17 -13
- package/src/tests/sync.auth.test.ts +246 -0
- package/src/tests/sync.load.test.ts +7 -6
- package/src/tests/sync.mesh.test.ts +25 -12
- package/src/tests/sync.peerReconciliation.test.ts +25 -25
- package/src/tests/sync.storage.test.ts +20 -13
- package/src/tests/sync.test.ts +43 -43
- package/src/tests/sync.upload.test.ts +157 -37
- package/src/tests/testUtils.ts +143 -96
- package/src/typeUtils/expectGroup.ts +1 -1
- package/dist/CoValuesStore.d.ts +0 -14
- package/dist/CoValuesStore.d.ts.map +0 -1
- package/dist/CoValuesStore.js +0 -32
- package/dist/CoValuesStore.js.map +0 -1
- package/dist/coValueCore.d.ts +0 -142
- package/dist/coValueCore.d.ts.map +0 -1
- package/dist/coValueCore.js.map +0 -1
- package/dist/coValueState.d.ts +0 -34
- package/dist/coValueState.d.ts.map +0 -1
- package/dist/coValueState.js +0 -190
- package/dist/coValueState.js.map +0 -1
- package/dist/tests/coValueState.test.d.ts +0 -2
- package/dist/tests/coValueState.test.d.ts.map +0 -1
- package/dist/tests/coValueState.test.js.map +0 -1
- package/src/CoValuesStore.ts +0 -41
- package/src/coValueState.ts +0 -245
|
@@ -39,9 +39,11 @@ describe("client with storage syncs with server", () => {
|
|
|
39
39
|
"client -> server | LOAD Map sessions: empty",
|
|
40
40
|
"server -> client | CONTENT Group header: true new: After: 0 New: 3",
|
|
41
41
|
"client -> server | KNOWN Group sessions: header/3",
|
|
42
|
+
"client -> storage | LOAD Group sessions: header/3",
|
|
42
43
|
"server -> client | CONTENT Map header: true new: After: 0 New: 1",
|
|
43
|
-
"
|
|
44
|
+
"storage -> client | KNOWN Group sessions: empty",
|
|
44
45
|
"client -> server | KNOWN Map sessions: header/1",
|
|
46
|
+
"client -> storage | CONTENT Group header: true new: After: 0 New: 3",
|
|
45
47
|
"storage -> client | KNOWN Group sessions: header/3",
|
|
46
48
|
"client -> storage | CONTENT Map header: true new: After: 0 New: 1",
|
|
47
49
|
"storage -> client | KNOWN Map sessions: header/1",
|
|
@@ -55,7 +57,8 @@ describe("client with storage syncs with server", () => {
|
|
|
55
57
|
client.connectToSyncServer();
|
|
56
58
|
const { storage } = client.addStoragePeer();
|
|
57
59
|
|
|
58
|
-
|
|
60
|
+
// biome-ignore lint/suspicious/noExplicitAny: Super ugly, might have unintended side effects
|
|
61
|
+
(storage as any).coValues = (jazzCloud.node as any).coValues;
|
|
59
62
|
|
|
60
63
|
const group = jazzCloud.node.createGroup();
|
|
61
64
|
const map = group.createMap();
|
|
@@ -74,15 +77,11 @@ describe("client with storage syncs with server", () => {
|
|
|
74
77
|
"client -> storage | LOAD Map sessions: empty",
|
|
75
78
|
"storage -> client | CONTENT Group header: true new: After: 0 New: 3",
|
|
76
79
|
"client -> storage | KNOWN Group sessions: header/3",
|
|
80
|
+
"client -> server | LOAD Group sessions: header/3",
|
|
77
81
|
"storage -> client | CONTENT Map header: true new: After: 0 New: 1",
|
|
78
|
-
"client -> server | CONTENT Group header: true new: After: 0 New: 3",
|
|
79
|
-
"client -> storage | KNOWN Map sessions: header/1",
|
|
80
82
|
"server -> client | KNOWN Group sessions: header/3",
|
|
83
|
+
"client -> storage | KNOWN Map sessions: header/1",
|
|
81
84
|
"client -> server | LOAD Map sessions: header/1",
|
|
82
|
-
"server -> client | CONTENT Group header: true new: After: 0 New: 3",
|
|
83
|
-
"client -> server | CONTENT Map header: true new: After: 0 New: 1",
|
|
84
|
-
"server -> client | KNOWN Map sessions: header/1",
|
|
85
|
-
"client -> server | KNOWN Group sessions: header/3",
|
|
86
85
|
"server -> client | KNOWN Map sessions: header/1",
|
|
87
86
|
]
|
|
88
87
|
`);
|
|
@@ -119,13 +118,17 @@ describe("client with storage syncs with server", () => {
|
|
|
119
118
|
"client -> server | LOAD Map sessions: empty",
|
|
120
119
|
"server -> client | CONTENT ParentGroup header: true new: After: 0 New: 6",
|
|
121
120
|
"client -> server | KNOWN ParentGroup sessions: header/6",
|
|
121
|
+
"client -> storage | LOAD ParentGroup sessions: header/6",
|
|
122
122
|
"server -> client | CONTENT Group header: true new: After: 0 New: 5",
|
|
123
|
-
"
|
|
123
|
+
"storage -> client | KNOWN ParentGroup sessions: empty",
|
|
124
124
|
"client -> server | KNOWN Group sessions: header/5",
|
|
125
|
+
"client -> storage | LOAD Group sessions: header/5",
|
|
125
126
|
"server -> client | CONTENT Map header: true new: After: 0 New: 1",
|
|
127
|
+
"storage -> client | KNOWN Group sessions: empty",
|
|
128
|
+
"client -> storage | CONTENT ParentGroup header: true new: After: 0 New: 6",
|
|
129
|
+
"client -> server | KNOWN Map sessions: header/1",
|
|
126
130
|
"storage -> client | KNOWN ParentGroup sessions: header/6",
|
|
127
131
|
"client -> storage | CONTENT Group header: true new: After: 0 New: 5",
|
|
128
|
-
"client -> server | KNOWN Map sessions: header/1",
|
|
129
132
|
"storage -> client | KNOWN Group sessions: header/5",
|
|
130
133
|
"client -> storage | CONTENT Map header: true new: After: 0 New: 1",
|
|
131
134
|
"storage -> client | KNOWN Map sessions: header/1",
|
|
@@ -169,10 +172,10 @@ describe("client with storage syncs with server", () => {
|
|
|
169
172
|
"client -> server | LOAD Map sessions: header/1",
|
|
170
173
|
"server -> client | CONTENT Map header: false new: After: 1 New: 1",
|
|
171
174
|
"client -> server | KNOWN Map sessions: header/2",
|
|
172
|
-
"server -> client | CONTENT Map header: false new: After: 1 New: 1",
|
|
173
175
|
"client -> storage | CONTENT Map header: false new: After: 1 New: 1",
|
|
174
|
-
"
|
|
176
|
+
"server -> client | CONTENT Map header: false new: After: 1 New: 1",
|
|
175
177
|
"storage -> client | KNOWN Map sessions: header/2",
|
|
178
|
+
"client -> server | KNOWN Map sessions: header/2",
|
|
176
179
|
]
|
|
177
180
|
`);
|
|
178
181
|
});
|
|
@@ -216,9 +219,13 @@ describe("client syncs with a server with storage", () => {
|
|
|
216
219
|
[
|
|
217
220
|
"client -> server | CONTENT Group header: true new: After: 0 New: 3",
|
|
218
221
|
"server -> client | KNOWN Group sessions: header/3",
|
|
222
|
+
"server -> storage | LOAD Group sessions: header/3",
|
|
219
223
|
"client -> server | CONTENT Map header: true new: After: 0 New: 1",
|
|
220
|
-
"
|
|
224
|
+
"storage -> server | KNOWN Group sessions: empty",
|
|
221
225
|
"server -> client | KNOWN Map sessions: header/1",
|
|
226
|
+
"server -> storage | LOAD Map sessions: header/1",
|
|
227
|
+
"storage -> server | KNOWN Map sessions: empty",
|
|
228
|
+
"server -> storage | CONTENT Group header: true new: After: 0 New: 3",
|
|
222
229
|
"storage -> server | KNOWN Group sessions: header/3",
|
|
223
230
|
"server -> storage | CONTENT Map header: true new: After: 0 New: 1",
|
|
224
231
|
"storage -> server | KNOWN Map sessions: header/1",
|
package/src/tests/sync.test.ts
CHANGED
|
@@ -1,4 +1,12 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
assert,
|
|
3
|
+
afterEach,
|
|
4
|
+
beforeEach,
|
|
5
|
+
describe,
|
|
6
|
+
expect,
|
|
7
|
+
test,
|
|
8
|
+
vi,
|
|
9
|
+
} from "vitest";
|
|
2
10
|
import { expectMap } from "../coValue.js";
|
|
3
11
|
import { RawCoMap } from "../coValues/coMap.js";
|
|
4
12
|
import type { RawGroup } from "../coValues/group.js";
|
|
@@ -12,7 +20,8 @@ import {
|
|
|
12
20
|
createTestMetricReader,
|
|
13
21
|
createTestNode,
|
|
14
22
|
loadCoValueOrFail,
|
|
15
|
-
|
|
23
|
+
nodeWithRandomAgentAndSessionID,
|
|
24
|
+
randomAgentAndSessionID,
|
|
16
25
|
setupTestAccount,
|
|
17
26
|
setupTestNode,
|
|
18
27
|
tearDownTestMetricReader,
|
|
@@ -32,8 +41,7 @@ beforeEach(async () => {
|
|
|
32
41
|
});
|
|
33
42
|
|
|
34
43
|
test("If we add a client peer, but it never subscribes to a coValue, it won't get any messages", async () => {
|
|
35
|
-
const
|
|
36
|
-
const node = new LocalNode(admin, session, Crypto);
|
|
44
|
+
const node = nodeWithRandomAgentAndSessionID();
|
|
37
45
|
|
|
38
46
|
const group = node.createGroup();
|
|
39
47
|
|
|
@@ -151,11 +159,8 @@ test("should delete the peer state when the peer closes if deletePeerStateOnClos
|
|
|
151
159
|
describe("sync - extra tests", () => {
|
|
152
160
|
test("Node handles disconnection and reconnection of a peer gracefully", async () => {
|
|
153
161
|
// Create two nodes
|
|
154
|
-
const
|
|
155
|
-
const
|
|
156
|
-
|
|
157
|
-
const [admin2, session2] = randomAnonymousAccountAndSessionID();
|
|
158
|
-
const node2 = new LocalNode(admin2, session2, Crypto);
|
|
162
|
+
const node1 = nodeWithRandomAgentAndSessionID();
|
|
163
|
+
const node2 = nodeWithRandomAgentAndSessionID();
|
|
159
164
|
|
|
160
165
|
// Create a group and a map on node1
|
|
161
166
|
const group = node1.createGroup();
|
|
@@ -177,7 +182,7 @@ describe("sync - extra tests", () => {
|
|
|
177
182
|
|
|
178
183
|
// Verify that node2 has received the map
|
|
179
184
|
const mapOnNode2 = await node2.loadCoValueCore(map.core.id);
|
|
180
|
-
if (mapOnNode2
|
|
185
|
+
if (!mapOnNode2.isAvailable()) {
|
|
181
186
|
throw new Error("Map is unavailable on node2");
|
|
182
187
|
}
|
|
183
188
|
|
|
@@ -211,7 +216,7 @@ describe("sync - extra tests", () => {
|
|
|
211
216
|
|
|
212
217
|
// Verify that node2 has received the changes made during disconnection
|
|
213
218
|
const updatedMapOnNode2 = await node2.loadCoValueCore(map.core.id);
|
|
214
|
-
if (updatedMapOnNode2
|
|
219
|
+
if (!updatedMapOnNode2.isAvailable()) {
|
|
215
220
|
throw new Error("Updated map is unavailable on node2");
|
|
216
221
|
}
|
|
217
222
|
|
|
@@ -221,7 +226,7 @@ describe("sync - extra tests", () => {
|
|
|
221
226
|
|
|
222
227
|
// Make a new change on node2 to verify two-way sync
|
|
223
228
|
const mapOnNode2ForEdit = await node2.loadCoValueCore(map.core.id);
|
|
224
|
-
if (mapOnNode2ForEdit
|
|
229
|
+
if (!mapOnNode2ForEdit.isAvailable()) {
|
|
225
230
|
throw new Error("Updated map is unavailable on node2");
|
|
226
231
|
}
|
|
227
232
|
|
|
@@ -244,7 +249,7 @@ describe("sync - extra tests", () => {
|
|
|
244
249
|
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
245
250
|
|
|
246
251
|
const mapOnNode1 = await node1.loadCoValueCore(map.core.id);
|
|
247
|
-
if (mapOnNode1
|
|
252
|
+
if (!mapOnNode1.isAvailable()) {
|
|
248
253
|
throw new Error("Updated map is unavailable on node1");
|
|
249
254
|
}
|
|
250
255
|
|
|
@@ -255,14 +260,9 @@ describe("sync - extra tests", () => {
|
|
|
255
260
|
});
|
|
256
261
|
test("Concurrent modifications on multiple nodes are resolved correctly", async () => {
|
|
257
262
|
// Create three nodes
|
|
258
|
-
const
|
|
259
|
-
const
|
|
260
|
-
|
|
261
|
-
const [admin2, session2] = randomAnonymousAccountAndSessionID();
|
|
262
|
-
const node2 = new LocalNode(admin2, session2, Crypto);
|
|
263
|
-
|
|
264
|
-
const [admin3, session3] = randomAnonymousAccountAndSessionID();
|
|
265
|
-
const node3 = new LocalNode(admin3, session3, Crypto);
|
|
263
|
+
const node1 = nodeWithRandomAgentAndSessionID();
|
|
264
|
+
const node2 = nodeWithRandomAgentAndSessionID();
|
|
265
|
+
const node3 = nodeWithRandomAgentAndSessionID();
|
|
266
266
|
|
|
267
267
|
// Create a group and a map on node1
|
|
268
268
|
const group = node1.createGroup();
|
|
@@ -316,9 +316,9 @@ describe("sync - extra tests", () => {
|
|
|
316
316
|
const mapOnNode3 = await node3.loadCoValueCore(map.core.id);
|
|
317
317
|
|
|
318
318
|
if (
|
|
319
|
-
mapOnNode1
|
|
320
|
-
mapOnNode2
|
|
321
|
-
mapOnNode3
|
|
319
|
+
!mapOnNode1.isAvailable() ||
|
|
320
|
+
!mapOnNode2.isAvailable() ||
|
|
321
|
+
!mapOnNode3.isAvailable()
|
|
322
322
|
) {
|
|
323
323
|
throw new Error("Map is unavailable on node2 or node3");
|
|
324
324
|
}
|
|
@@ -349,14 +349,9 @@ describe("sync - extra tests", () => {
|
|
|
349
349
|
|
|
350
350
|
test("Node correctly handles and recovers from network partitions", async () => {
|
|
351
351
|
// Create three nodes
|
|
352
|
-
const
|
|
353
|
-
const
|
|
354
|
-
|
|
355
|
-
const [admin2, session2] = randomAnonymousAccountAndSessionID();
|
|
356
|
-
const node2 = new LocalNode(admin2, session2, Crypto);
|
|
357
|
-
|
|
358
|
-
const [admin3, session3] = randomAnonymousAccountAndSessionID();
|
|
359
|
-
const node3 = new LocalNode(admin3, session3, Crypto);
|
|
352
|
+
const node1 = nodeWithRandomAgentAndSessionID();
|
|
353
|
+
const node2 = nodeWithRandomAgentAndSessionID();
|
|
354
|
+
const node3 = nodeWithRandomAgentAndSessionID();
|
|
360
355
|
|
|
361
356
|
// Create a group and a map on node1
|
|
362
357
|
const group = node1.createGroup();
|
|
@@ -411,9 +406,9 @@ describe("sync - extra tests", () => {
|
|
|
411
406
|
const mapOnNode3Core = await node3.loadCoValueCore(map.core.id);
|
|
412
407
|
|
|
413
408
|
if (
|
|
414
|
-
mapOnNode1Core
|
|
415
|
-
mapOnNode2Core
|
|
416
|
-
mapOnNode3Core
|
|
409
|
+
!mapOnNode1Core.isAvailable() ||
|
|
410
|
+
!mapOnNode2Core.isAvailable() ||
|
|
411
|
+
!mapOnNode3Core.isAvailable()
|
|
417
412
|
) {
|
|
418
413
|
throw new Error("Map is unavailable on node2 or node3");
|
|
419
414
|
}
|
|
@@ -528,7 +523,7 @@ describe("sync - extra tests", () => {
|
|
|
528
523
|
});
|
|
529
524
|
});
|
|
530
525
|
|
|
531
|
-
test("a value created on one node can be loaded on
|
|
526
|
+
test("a value created on one node can be loaded on another node even if not directly connected", async () => {
|
|
532
527
|
const userA = createTestNode();
|
|
533
528
|
const userB = createTestNode();
|
|
534
529
|
const serverA = createTestNode();
|
|
@@ -548,6 +543,12 @@ test("a value created on one node can be loaded on anotehr node even if not dire
|
|
|
548
543
|
|
|
549
544
|
const mapOnUserB = await loadCoValueOrFail(userB, map.id);
|
|
550
545
|
expect(mapOnUserB.get("key1")).toBe("value1");
|
|
546
|
+
|
|
547
|
+
map.set("key2", "value2", "trusting");
|
|
548
|
+
|
|
549
|
+
await waitFor(() => {
|
|
550
|
+
expect(mapOnUserB.get("key2")).toBe("value2");
|
|
551
|
+
});
|
|
551
552
|
});
|
|
552
553
|
|
|
553
554
|
describe("SyncManager - knownStates vs optimisticKnownStates", () => {
|
|
@@ -747,7 +748,7 @@ describe("SyncManager.addPeer", () => {
|
|
|
747
748
|
|
|
748
749
|
await map.core.waitForSync();
|
|
749
750
|
|
|
750
|
-
expect(jazzCloud.node.
|
|
751
|
+
expect(jazzCloud.node.getCoValue(map.id).isAvailable()).toBe(true);
|
|
751
752
|
});
|
|
752
753
|
});
|
|
753
754
|
|
|
@@ -802,13 +803,13 @@ describe("loadCoValueCore with retry", () => {
|
|
|
802
803
|
// Start loading before syncing
|
|
803
804
|
const result = await bob.loadCoValueCore(map.id);
|
|
804
805
|
|
|
805
|
-
expect(result).toBe(
|
|
806
|
+
expect(result.isAvailable()).toBe(false);
|
|
806
807
|
|
|
807
808
|
connectTwoPeers(alice, bob, "server", "server");
|
|
808
809
|
|
|
809
810
|
const result2 = await bob.loadCoValueCore(map.id);
|
|
810
811
|
|
|
811
|
-
expect(result2).
|
|
812
|
+
expect(result2.isAvailable()).toBe(true);
|
|
812
813
|
});
|
|
813
814
|
|
|
814
815
|
test("should successfully mark a coValue as unavailable if the server does not have it", async () => {
|
|
@@ -826,7 +827,7 @@ describe("loadCoValueCore with retry", () => {
|
|
|
826
827
|
// Start loading before syncing
|
|
827
828
|
const result = await bob.loadCoValueCore(map.id);
|
|
828
829
|
|
|
829
|
-
expect(result).toBe(
|
|
830
|
+
expect(result.isAvailable()).toBe(false);
|
|
830
831
|
});
|
|
831
832
|
});
|
|
832
833
|
|
|
@@ -910,8 +911,7 @@ describe("metrics", () => {
|
|
|
910
911
|
|
|
911
912
|
test("should correctly track the number of connected peers", async () => {
|
|
912
913
|
const metricReader = createTestMetricReader();
|
|
913
|
-
const
|
|
914
|
-
const node = new LocalNode(admin, session, Crypto);
|
|
914
|
+
const node = nodeWithRandomAgentAndSessionID();
|
|
915
915
|
|
|
916
916
|
let connectedPeers = await metricReader.getMetricValue("jazz.peers", {
|
|
917
917
|
role: "client",
|
|
@@ -1059,7 +1059,7 @@ describe("SyncManager.handleSyncMessage", () => {
|
|
|
1059
1059
|
|
|
1060
1060
|
// Add a coValue to the errored set
|
|
1061
1061
|
const erroredId = "co_z123" as const;
|
|
1062
|
-
client.node.
|
|
1062
|
+
client.node.getCoValue(erroredId).markErrored(peer.id, {
|
|
1063
1063
|
message: "Test error",
|
|
1064
1064
|
} as any);
|
|
1065
1065
|
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { beforeEach, describe, expect, test } from "vitest";
|
|
2
2
|
|
|
3
|
-
import { expectMap } from "../coValue";
|
|
3
|
+
import { expectList, expectMap } from "../coValue";
|
|
4
|
+
import { WasmCrypto } from "../crypto/WasmCrypto";
|
|
4
5
|
import {
|
|
5
6
|
SyncMessagesLog,
|
|
6
7
|
loadCoValueOrFail,
|
|
@@ -8,6 +9,7 @@ import {
|
|
|
8
9
|
waitFor,
|
|
9
10
|
} from "./testUtils";
|
|
10
11
|
|
|
12
|
+
const Crypto = await WasmCrypto.create();
|
|
11
13
|
let jazzCloud = setupTestNode({ isSyncServer: true });
|
|
12
14
|
|
|
13
15
|
beforeEach(async () => {
|
|
@@ -82,6 +84,44 @@ describe("client to server upload", () => {
|
|
|
82
84
|
`);
|
|
83
85
|
});
|
|
84
86
|
|
|
87
|
+
test("coValue uploading with a missing dependency", async () => {
|
|
88
|
+
const client = setupTestNode({
|
|
89
|
+
connected: true,
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
const group = client.node.createGroup();
|
|
93
|
+
const map = group.createMap();
|
|
94
|
+
map.set("hello", "world", "trusting");
|
|
95
|
+
|
|
96
|
+
await group.core.waitForSync();
|
|
97
|
+
await map.core.waitForSync();
|
|
98
|
+
|
|
99
|
+
map.set("hello", "new world", "trusting");
|
|
100
|
+
// Testing that with a missing group the sync will not fail
|
|
101
|
+
client.node.internalDeleteCoValue(group.id);
|
|
102
|
+
|
|
103
|
+
await map.core.waitForSync();
|
|
104
|
+
|
|
105
|
+
const mapOnServer = await loadCoValueOrFail(jazzCloud.node, map.id);
|
|
106
|
+
expect(mapOnServer.get("hello")).toEqual("new world");
|
|
107
|
+
|
|
108
|
+
expect(
|
|
109
|
+
SyncMessagesLog.getMessages({
|
|
110
|
+
Group: group.core,
|
|
111
|
+
Map: map.core,
|
|
112
|
+
}),
|
|
113
|
+
).toMatchInlineSnapshot(`
|
|
114
|
+
[
|
|
115
|
+
"client -> server | CONTENT Group header: true new: After: 0 New: 3",
|
|
116
|
+
"server -> client | KNOWN Group sessions: header/3",
|
|
117
|
+
"client -> server | CONTENT Map header: true new: After: 0 New: 1",
|
|
118
|
+
"server -> client | KNOWN Map sessions: header/1",
|
|
119
|
+
"client -> server | CONTENT Map header: false new: After: 1 New: 1",
|
|
120
|
+
"server -> client | KNOWN Map sessions: header/2",
|
|
121
|
+
]
|
|
122
|
+
`);
|
|
123
|
+
});
|
|
124
|
+
|
|
85
125
|
test("wrong optimistic known state should be corrected", async () => {
|
|
86
126
|
const client = setupTestNode({
|
|
87
127
|
connected: true,
|
|
@@ -99,7 +139,7 @@ describe("client to server upload", () => {
|
|
|
99
139
|
await map.core.waitForSync();
|
|
100
140
|
|
|
101
141
|
// Forcefully delete the coValue from the client (simulating some data loss)
|
|
102
|
-
jazzCloud.node.
|
|
142
|
+
jazzCloud.node.internalDeleteCoValue(map.id);
|
|
103
143
|
|
|
104
144
|
map.set("fromClient", "updated", "trusting");
|
|
105
145
|
|
|
@@ -129,12 +169,91 @@ describe("client to server upload", () => {
|
|
|
129
169
|
`);
|
|
130
170
|
});
|
|
131
171
|
|
|
172
|
+
test("syncing changes between two clients with a sync server in the middle", async () => {
|
|
173
|
+
const client = setupTestNode({
|
|
174
|
+
connected: true,
|
|
175
|
+
});
|
|
176
|
+
const otherClient = setupTestNode({});
|
|
177
|
+
|
|
178
|
+
const otherClientConnection = otherClient.connectToSyncServer({
|
|
179
|
+
ourName: "otherClient",
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
const coValue = client.node.createCoValue({
|
|
183
|
+
type: "colist",
|
|
184
|
+
ruleset: { type: "unsafeAllowAll" },
|
|
185
|
+
meta: null,
|
|
186
|
+
...Crypto.createdNowUnique(),
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
const list = expectList(coValue.getCurrentContent());
|
|
190
|
+
|
|
191
|
+
list.append(1, undefined, "trusting");
|
|
192
|
+
|
|
193
|
+
const listOnOtherClient = await loadCoValueOrFail(
|
|
194
|
+
otherClient.node,
|
|
195
|
+
list.id,
|
|
196
|
+
);
|
|
197
|
+
|
|
198
|
+
otherClientConnection.peerState.gracefulShutdown();
|
|
199
|
+
|
|
200
|
+
listOnOtherClient.append(1, undefined, "trusting");
|
|
201
|
+
|
|
202
|
+
await new Promise((resolve) => setTimeout(resolve, 50));
|
|
203
|
+
|
|
204
|
+
list.append(1, undefined, "trusting");
|
|
205
|
+
|
|
206
|
+
await new Promise((resolve) => setTimeout(resolve, 50));
|
|
207
|
+
|
|
208
|
+
listOnOtherClient.append(1, undefined, "trusting");
|
|
209
|
+
|
|
210
|
+
await new Promise((resolve) => setTimeout(resolve, 50));
|
|
211
|
+
|
|
212
|
+
list.append(1, undefined, "trusting");
|
|
213
|
+
|
|
214
|
+
otherClient.connectToSyncServer({
|
|
215
|
+
ourName: "otherClient",
|
|
216
|
+
});
|
|
217
|
+
|
|
218
|
+
await waitFor(() => {
|
|
219
|
+
expect(list.toJSON()).toEqual([1, 1, 1, 1, 1]);
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
expect(
|
|
223
|
+
SyncMessagesLog.getMessages({
|
|
224
|
+
Colist: coValue,
|
|
225
|
+
}),
|
|
226
|
+
).toMatchInlineSnapshot(`
|
|
227
|
+
[
|
|
228
|
+
"otherClient -> server | LOAD Colist sessions: empty",
|
|
229
|
+
"client -> server | CONTENT Colist header: true new: After: 0 New: 1",
|
|
230
|
+
"server -> otherClient | KNOWN Colist sessions: empty",
|
|
231
|
+
"server -> client | KNOWN Colist sessions: header/1",
|
|
232
|
+
"server -> otherClient | CONTENT Colist header: true new: After: 0 New: 1",
|
|
233
|
+
"otherClient -> server | KNOWN Colist sessions: header/1",
|
|
234
|
+
"client -> server | CONTENT Colist header: false new: After: 1 New: 1",
|
|
235
|
+
"server -> client | KNOWN Colist sessions: header/2",
|
|
236
|
+
"otherClient -> server | LOAD Colist sessions: header/3",
|
|
237
|
+
"client -> server | CONTENT Colist header: false new: After: 2 New: 1",
|
|
238
|
+
"server -> otherClient | CONTENT Colist header: false new: After: 1 New: 1",
|
|
239
|
+
"server -> client | KNOWN Colist sessions: header/3",
|
|
240
|
+
"otherClient -> server | KNOWN Colist sessions: header/4",
|
|
241
|
+
"server -> otherClient | CONTENT Colist header: false new: After: 2 New: 1",
|
|
242
|
+
"otherClient -> server | CONTENT Colist header: false new: After: 0 New: 2",
|
|
243
|
+
"server -> otherClient | KNOWN Colist sessions: header/5",
|
|
244
|
+
"server -> client | CONTENT Colist header: false new: After: 0 New: 2",
|
|
245
|
+
"otherClient -> server | KNOWN Colist sessions: header/5",
|
|
246
|
+
"client -> server | KNOWN Colist sessions: header/5",
|
|
247
|
+
]
|
|
248
|
+
`);
|
|
249
|
+
});
|
|
250
|
+
|
|
132
251
|
test("large coValue upload streaming", async () => {
|
|
133
252
|
const client = setupTestNode({
|
|
134
253
|
connected: true,
|
|
135
254
|
});
|
|
136
255
|
|
|
137
|
-
const group =
|
|
256
|
+
const group = jazzCloud.node.createGroup();
|
|
138
257
|
group.addMember("everyone", "writer");
|
|
139
258
|
|
|
140
259
|
const largeMap = group.createMap();
|
|
@@ -162,40 +281,41 @@ describe("client to server upload", () => {
|
|
|
162
281
|
}),
|
|
163
282
|
).toMatchInlineSnapshot(`
|
|
164
283
|
[
|
|
165
|
-
"client -> server |
|
|
166
|
-
"server -> client |
|
|
167
|
-
"client -> server |
|
|
168
|
-
"server -> client |
|
|
169
|
-
"client -> server |
|
|
170
|
-
"server -> client |
|
|
171
|
-
"client -> server |
|
|
172
|
-
"server -> client |
|
|
173
|
-
"client -> server |
|
|
174
|
-
"server -> client |
|
|
175
|
-
"client -> server |
|
|
176
|
-
"server -> client |
|
|
177
|
-
"client -> server |
|
|
178
|
-
"server -> client |
|
|
179
|
-
"client -> server |
|
|
180
|
-
"server -> client |
|
|
181
|
-
"client -> server |
|
|
182
|
-
"server -> client |
|
|
183
|
-
"client -> server |
|
|
184
|
-
"server -> client |
|
|
185
|
-
"client -> server |
|
|
186
|
-
"server -> client |
|
|
187
|
-
"client -> server |
|
|
188
|
-
"server -> client |
|
|
189
|
-
"client -> server |
|
|
190
|
-
"server -> client |
|
|
191
|
-
"client -> server |
|
|
192
|
-
"server -> client |
|
|
193
|
-
"client -> server |
|
|
194
|
-
"server -> client |
|
|
195
|
-
"client -> server |
|
|
196
|
-
"server -> client |
|
|
197
|
-
"client -> server |
|
|
198
|
-
"server -> client |
|
|
284
|
+
"client -> server | LOAD Map sessions: empty",
|
|
285
|
+
"server -> client | CONTENT Group header: true new: After: 0 New: 5",
|
|
286
|
+
"client -> server | KNOWN Group sessions: header/5",
|
|
287
|
+
"server -> client | CONTENT Map header: true new: ",
|
|
288
|
+
"client -> server | KNOWN Map sessions: header/0",
|
|
289
|
+
"server -> client | CONTENT Map header: false new: After: 0 New: 73",
|
|
290
|
+
"client -> server | KNOWN Map sessions: header/73",
|
|
291
|
+
"server -> client | CONTENT Map header: false new: After: 73 New: 73",
|
|
292
|
+
"client -> server | KNOWN Map sessions: header/146",
|
|
293
|
+
"server -> client | CONTENT Map header: false new: After: 146 New: 73",
|
|
294
|
+
"client -> server | KNOWN Map sessions: header/219",
|
|
295
|
+
"server -> client | CONTENT Map header: false new: After: 219 New: 73",
|
|
296
|
+
"client -> server | KNOWN Map sessions: header/292",
|
|
297
|
+
"server -> client | CONTENT Map header: false new: After: 292 New: 73",
|
|
298
|
+
"client -> server | KNOWN Map sessions: header/365",
|
|
299
|
+
"server -> client | CONTENT Map header: false new: After: 365 New: 73",
|
|
300
|
+
"client -> server | KNOWN Map sessions: header/438",
|
|
301
|
+
"server -> client | CONTENT Map header: false new: After: 438 New: 73",
|
|
302
|
+
"client -> server | KNOWN Map sessions: header/511",
|
|
303
|
+
"server -> client | CONTENT Map header: false new: After: 511 New: 73",
|
|
304
|
+
"client -> server | KNOWN Map sessions: header/584",
|
|
305
|
+
"server -> client | CONTENT Map header: false new: After: 584 New: 73",
|
|
306
|
+
"client -> server | KNOWN Map sessions: header/657",
|
|
307
|
+
"server -> client | CONTENT Map header: false new: After: 657 New: 73",
|
|
308
|
+
"client -> server | KNOWN Map sessions: header/730",
|
|
309
|
+
"server -> client | CONTENT Map header: false new: After: 730 New: 73",
|
|
310
|
+
"client -> server | KNOWN Map sessions: header/803",
|
|
311
|
+
"server -> client | CONTENT Map header: false new: After: 803 New: 73",
|
|
312
|
+
"client -> server | KNOWN Map sessions: header/876",
|
|
313
|
+
"server -> client | CONTENT Map header: false new: After: 876 New: 73",
|
|
314
|
+
"client -> server | KNOWN Map sessions: header/949",
|
|
315
|
+
"server -> client | CONTENT Map header: false new: After: 949 New: 73",
|
|
316
|
+
"client -> server | KNOWN Map sessions: header/1022",
|
|
317
|
+
"server -> client | CONTENT Map header: false new: After: 1022 New: 2",
|
|
318
|
+
"client -> server | KNOWN Map sessions: header/1024",
|
|
199
319
|
]
|
|
200
320
|
`);
|
|
201
321
|
});
|