cojson 0.19.21 → 0.20.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.
- package/.turbo/turbo-build.log +1 -1
- package/CHANGELOG.md +67 -0
- package/dist/CojsonMessageChannel/CojsonMessageChannel.d.ts +42 -0
- package/dist/CojsonMessageChannel/CojsonMessageChannel.d.ts.map +1 -0
- package/dist/CojsonMessageChannel/CojsonMessageChannel.js +261 -0
- package/dist/CojsonMessageChannel/CojsonMessageChannel.js.map +1 -0
- package/dist/CojsonMessageChannel/MessagePortOutgoingChannel.d.ts +18 -0
- package/dist/CojsonMessageChannel/MessagePortOutgoingChannel.d.ts.map +1 -0
- package/dist/CojsonMessageChannel/MessagePortOutgoingChannel.js +37 -0
- package/dist/CojsonMessageChannel/MessagePortOutgoingChannel.js.map +1 -0
- package/dist/CojsonMessageChannel/index.d.ts +3 -0
- package/dist/CojsonMessageChannel/index.d.ts.map +1 -0
- package/dist/CojsonMessageChannel/index.js +2 -0
- package/dist/CojsonMessageChannel/index.js.map +1 -0
- package/dist/CojsonMessageChannel/types.d.ts +149 -0
- package/dist/CojsonMessageChannel/types.d.ts.map +1 -0
- package/dist/CojsonMessageChannel/types.js +36 -0
- package/dist/CojsonMessageChannel/types.js.map +1 -0
- package/dist/GarbageCollector.d.ts +4 -2
- package/dist/GarbageCollector.d.ts.map +1 -1
- package/dist/GarbageCollector.js +5 -3
- package/dist/GarbageCollector.js.map +1 -1
- package/dist/SyncStateManager.d.ts +3 -3
- package/dist/SyncStateManager.d.ts.map +1 -1
- package/dist/SyncStateManager.js +4 -4
- package/dist/SyncStateManager.js.map +1 -1
- package/dist/coValueContentMessage.d.ts +0 -2
- package/dist/coValueContentMessage.d.ts.map +1 -1
- package/dist/coValueContentMessage.js +0 -8
- package/dist/coValueContentMessage.js.map +1 -1
- package/dist/coValueCore/SessionMap.d.ts +4 -2
- package/dist/coValueCore/SessionMap.d.ts.map +1 -1
- package/dist/coValueCore/SessionMap.js +30 -0
- package/dist/coValueCore/SessionMap.js.map +1 -1
- package/dist/coValueCore/coValueCore.d.ts +86 -4
- package/dist/coValueCore/coValueCore.d.ts.map +1 -1
- package/dist/coValueCore/coValueCore.js +318 -17
- package/dist/coValueCore/coValueCore.js.map +1 -1
- package/dist/coValueCore/verifiedState.d.ts +6 -1
- package/dist/coValueCore/verifiedState.d.ts.map +1 -1
- package/dist/coValueCore/verifiedState.js +9 -0
- package/dist/coValueCore/verifiedState.js.map +1 -1
- package/dist/coValues/coList.d.ts +3 -2
- package/dist/coValues/coList.d.ts.map +1 -1
- package/dist/coValues/coList.js.map +1 -1
- package/dist/coValues/group.d.ts.map +1 -1
- package/dist/coValues/group.js +3 -6
- package/dist/coValues/group.js.map +1 -1
- package/dist/config.d.ts +0 -6
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +0 -8
- package/dist/config.js.map +1 -1
- package/dist/crypto/NapiCrypto.d.ts +1 -2
- package/dist/crypto/NapiCrypto.d.ts.map +1 -1
- package/dist/crypto/NapiCrypto.js +19 -4
- package/dist/crypto/NapiCrypto.js.map +1 -1
- package/dist/crypto/RNCrypto.d.ts.map +1 -1
- package/dist/crypto/RNCrypto.js +19 -4
- package/dist/crypto/RNCrypto.js.map +1 -1
- package/dist/crypto/WasmCrypto.d.ts +11 -4
- package/dist/crypto/WasmCrypto.d.ts.map +1 -1
- package/dist/crypto/WasmCrypto.js +52 -10
- package/dist/crypto/WasmCrypto.js.map +1 -1
- package/dist/crypto/WasmCryptoEdge.d.ts +1 -0
- package/dist/crypto/WasmCryptoEdge.d.ts.map +1 -1
- package/dist/crypto/WasmCryptoEdge.js +4 -1
- package/dist/crypto/WasmCryptoEdge.js.map +1 -1
- package/dist/crypto/crypto.d.ts +3 -3
- package/dist/crypto/crypto.d.ts.map +1 -1
- package/dist/crypto/crypto.js +6 -1
- package/dist/crypto/crypto.js.map +1 -1
- package/dist/exports.d.ts +3 -2
- package/dist/exports.d.ts.map +1 -1
- package/dist/exports.js +3 -1
- package/dist/exports.js.map +1 -1
- package/dist/ids.d.ts +4 -1
- package/dist/ids.d.ts.map +1 -1
- package/dist/ids.js +4 -0
- package/dist/ids.js.map +1 -1
- package/dist/knownState.d.ts +2 -0
- package/dist/knownState.d.ts.map +1 -1
- package/dist/localNode.d.ts +13 -3
- package/dist/localNode.d.ts.map +1 -1
- package/dist/localNode.js +17 -2
- package/dist/localNode.js.map +1 -1
- package/dist/platformUtils.d.ts +3 -0
- package/dist/platformUtils.d.ts.map +1 -0
- package/dist/platformUtils.js +24 -0
- package/dist/platformUtils.js.map +1 -0
- package/dist/storage/DeletedCoValuesEraserScheduler.d.ts +30 -0
- package/dist/storage/DeletedCoValuesEraserScheduler.d.ts.map +1 -0
- package/dist/storage/DeletedCoValuesEraserScheduler.js +84 -0
- package/dist/storage/DeletedCoValuesEraserScheduler.js.map +1 -0
- package/dist/storage/sqlite/client.d.ts +3 -0
- package/dist/storage/sqlite/client.d.ts.map +1 -1
- package/dist/storage/sqlite/client.js +44 -0
- package/dist/storage/sqlite/client.js.map +1 -1
- package/dist/storage/sqlite/sqliteMigrations.d.ts.map +1 -1
- package/dist/storage/sqlite/sqliteMigrations.js +7 -0
- package/dist/storage/sqlite/sqliteMigrations.js.map +1 -1
- package/dist/storage/sqliteAsync/client.d.ts +3 -0
- package/dist/storage/sqliteAsync/client.d.ts.map +1 -1
- package/dist/storage/sqliteAsync/client.js +42 -0
- package/dist/storage/sqliteAsync/client.js.map +1 -1
- package/dist/storage/storageAsync.d.ts +15 -3
- package/dist/storage/storageAsync.d.ts.map +1 -1
- package/dist/storage/storageAsync.js +60 -3
- package/dist/storage/storageAsync.js.map +1 -1
- package/dist/storage/storageSync.d.ts +14 -3
- package/dist/storage/storageSync.d.ts.map +1 -1
- package/dist/storage/storageSync.js +54 -3
- package/dist/storage/storageSync.js.map +1 -1
- package/dist/storage/types.d.ts +64 -0
- package/dist/storage/types.d.ts.map +1 -1
- package/dist/storage/types.js +12 -1
- package/dist/storage/types.js.map +1 -1
- package/dist/sync.d.ts +6 -0
- package/dist/sync.d.ts.map +1 -1
- package/dist/sync.js +69 -15
- package/dist/sync.js.map +1 -1
- package/dist/tests/CojsonMessageChannel.test.d.ts +2 -0
- package/dist/tests/CojsonMessageChannel.test.d.ts.map +1 -0
- package/dist/tests/CojsonMessageChannel.test.js +236 -0
- package/dist/tests/CojsonMessageChannel.test.js.map +1 -0
- package/dist/tests/DeletedCoValuesEraserScheduler.test.d.ts +2 -0
- package/dist/tests/DeletedCoValuesEraserScheduler.test.d.ts.map +1 -0
- package/dist/tests/DeletedCoValuesEraserScheduler.test.js +149 -0
- package/dist/tests/DeletedCoValuesEraserScheduler.test.js.map +1 -0
- package/dist/tests/GarbageCollector.test.js +91 -18
- package/dist/tests/GarbageCollector.test.js.map +1 -1
- package/dist/tests/StorageApiAsync.test.js +510 -146
- package/dist/tests/StorageApiAsync.test.js.map +1 -1
- package/dist/tests/StorageApiSync.test.js +531 -130
- package/dist/tests/StorageApiSync.test.js.map +1 -1
- package/dist/tests/SyncManager.processQueues.test.js +1 -1
- package/dist/tests/SyncManager.processQueues.test.js.map +1 -1
- package/dist/tests/SyncStateManager.test.js +1 -1
- package/dist/tests/SyncStateManager.test.js.map +1 -1
- package/dist/tests/WasmCrypto.test.js +6 -3
- package/dist/tests/WasmCrypto.test.js.map +1 -1
- package/dist/tests/coPlainText.test.js +1 -1
- package/dist/tests/coPlainText.test.js.map +1 -1
- package/dist/tests/coValueCore.loadFromStorage.test.js +4 -0
- package/dist/tests/coValueCore.loadFromStorage.test.js.map +1 -1
- package/dist/tests/coValueCore.test.js +34 -13
- package/dist/tests/coValueCore.test.js.map +1 -1
- package/dist/tests/coreWasm.test.js +127 -4
- package/dist/tests/coreWasm.test.js.map +1 -1
- package/dist/tests/crypto.test.js +89 -93
- package/dist/tests/crypto.test.js.map +1 -1
- package/dist/tests/deleteCoValue.test.d.ts +2 -0
- package/dist/tests/deleteCoValue.test.d.ts.map +1 -0
- package/dist/tests/deleteCoValue.test.js +313 -0
- package/dist/tests/deleteCoValue.test.js.map +1 -0
- package/dist/tests/group.removeMember.test.js +18 -30
- package/dist/tests/group.removeMember.test.js.map +1 -1
- package/dist/tests/knownState.lazyLoading.test.js +4 -0
- package/dist/tests/knownState.lazyLoading.test.js.map +1 -1
- package/dist/tests/sync.deleted.test.d.ts +2 -0
- package/dist/tests/sync.deleted.test.d.ts.map +1 -0
- package/dist/tests/sync.deleted.test.js +214 -0
- package/dist/tests/sync.deleted.test.js.map +1 -0
- package/dist/tests/sync.garbageCollection.test.js +56 -32
- package/dist/tests/sync.garbageCollection.test.js.map +1 -1
- package/dist/tests/sync.load.test.js +3 -5
- package/dist/tests/sync.load.test.js.map +1 -1
- package/dist/tests/sync.mesh.test.js +4 -3
- package/dist/tests/sync.mesh.test.js.map +1 -1
- package/dist/tests/sync.peerReconciliation.test.js +3 -3
- package/dist/tests/sync.peerReconciliation.test.js.map +1 -1
- package/dist/tests/sync.storage.test.js +12 -11
- package/dist/tests/sync.storage.test.js.map +1 -1
- package/dist/tests/sync.storageAsync.test.js +7 -7
- package/dist/tests/sync.storageAsync.test.js.map +1 -1
- package/dist/tests/sync.test.js +3 -2
- package/dist/tests/sync.test.js.map +1 -1
- package/dist/tests/sync.tracking.test.js +35 -4
- package/dist/tests/sync.tracking.test.js.map +1 -1
- package/dist/tests/testStorage.d.ts +3 -0
- package/dist/tests/testStorage.d.ts.map +1 -1
- package/dist/tests/testStorage.js +16 -2
- package/dist/tests/testStorage.js.map +1 -1
- package/dist/tests/testUtils.d.ts +29 -4
- package/dist/tests/testUtils.d.ts.map +1 -1
- package/dist/tests/testUtils.js +84 -9
- package/dist/tests/testUtils.js.map +1 -1
- package/package.json +6 -16
- package/src/CojsonMessageChannel/CojsonMessageChannel.ts +332 -0
- package/src/CojsonMessageChannel/MessagePortOutgoingChannel.ts +52 -0
- package/src/CojsonMessageChannel/index.ts +9 -0
- package/src/CojsonMessageChannel/types.ts +200 -0
- package/src/GarbageCollector.ts +5 -5
- package/src/SyncStateManager.ts +6 -6
- package/src/coValueContentMessage.ts +0 -14
- package/src/coValueCore/SessionMap.ts +43 -1
- package/src/coValueCore/coValueCore.ts +430 -15
- package/src/coValueCore/verifiedState.ts +26 -3
- package/src/coValues/coList.ts +5 -3
- package/src/coValues/group.ts +5 -6
- package/src/config.ts +0 -9
- package/src/crypto/NapiCrypto.ts +29 -13
- package/src/crypto/RNCrypto.ts +29 -11
- package/src/crypto/WasmCrypto.ts +67 -20
- package/src/crypto/WasmCryptoEdge.ts +5 -1
- package/src/crypto/crypto.ts +16 -4
- package/src/exports.ts +3 -0
- package/src/ids.ts +11 -1
- package/src/localNode.ts +18 -5
- package/src/platformUtils.ts +26 -0
- package/src/storage/DeletedCoValuesEraserScheduler.ts +124 -0
- package/src/storage/sqlite/client.ts +77 -0
- package/src/storage/sqlite/sqliteMigrations.ts +7 -0
- package/src/storage/sqliteAsync/client.ts +75 -0
- package/src/storage/storageAsync.ts +77 -4
- package/src/storage/storageSync.ts +73 -4
- package/src/storage/types.ts +75 -0
- package/src/sync.ts +84 -15
- package/src/tests/CojsonMessageChannel.test.ts +306 -0
- package/src/tests/DeletedCoValuesEraserScheduler.test.ts +185 -0
- package/src/tests/GarbageCollector.test.ts +119 -22
- package/src/tests/StorageApiAsync.test.ts +615 -156
- package/src/tests/StorageApiSync.test.ts +623 -137
- package/src/tests/SyncManager.processQueues.test.ts +1 -1
- package/src/tests/SyncStateManager.test.ts +1 -1
- package/src/tests/WasmCrypto.test.ts +8 -3
- package/src/tests/coPlainText.test.ts +1 -1
- package/src/tests/coValueCore.loadFromStorage.test.ts +8 -0
- package/src/tests/coValueCore.test.ts +49 -14
- package/src/tests/coreWasm.test.ts +319 -10
- package/src/tests/crypto.test.ts +141 -150
- package/src/tests/deleteCoValue.test.ts +528 -0
- package/src/tests/group.removeMember.test.ts +35 -35
- package/src/tests/knownState.lazyLoading.test.ts +8 -0
- package/src/tests/sync.deleted.test.ts +294 -0
- package/src/tests/sync.garbageCollection.test.ts +69 -36
- package/src/tests/sync.load.test.ts +3 -5
- package/src/tests/sync.mesh.test.ts +6 -3
- package/src/tests/sync.peerReconciliation.test.ts +3 -3
- package/src/tests/sync.storage.test.ts +14 -11
- package/src/tests/sync.storageAsync.test.ts +7 -7
- package/src/tests/sync.test.ts +5 -2
- package/src/tests/sync.tracking.test.ts +54 -4
- package/src/tests/testStorage.ts +30 -3
- package/src/tests/testUtils.ts +113 -15
- package/dist/crypto/PureJSCrypto.d.ts +0 -77
- package/dist/crypto/PureJSCrypto.d.ts.map +0 -1
- package/dist/crypto/PureJSCrypto.js +0 -236
- package/dist/crypto/PureJSCrypto.js.map +0 -1
- package/dist/tests/PureJSCrypto.test.d.ts +0 -2
- package/dist/tests/PureJSCrypto.test.d.ts.map +0 -1
- package/dist/tests/PureJSCrypto.test.js +0 -145
- package/dist/tests/PureJSCrypto.test.js.map +0 -1
- package/src/crypto/PureJSCrypto.ts +0 -429
- package/src/tests/PureJSCrypto.test.ts +0 -217
|
@@ -0,0 +1,294 @@
|
|
|
1
|
+
import { assert, beforeEach, describe, expect, test } from "vitest";
|
|
2
|
+
import { expectMap } from "../coValue";
|
|
3
|
+
import {
|
|
4
|
+
SyncMessagesLog,
|
|
5
|
+
TEST_NODE_CONFIG,
|
|
6
|
+
loadCoValueOrFail,
|
|
7
|
+
setupTestAccount,
|
|
8
|
+
setupTestNode,
|
|
9
|
+
waitFor,
|
|
10
|
+
} from "./testUtils";
|
|
11
|
+
import { isDeleteSessionID, SessionID } from "../ids";
|
|
12
|
+
|
|
13
|
+
let jazzCloud: ReturnType<typeof setupTestNode>;
|
|
14
|
+
|
|
15
|
+
beforeEach(async () => {
|
|
16
|
+
// We want to simulate a real world communication that happens asynchronously
|
|
17
|
+
TEST_NODE_CONFIG.withAsyncPeers = true;
|
|
18
|
+
|
|
19
|
+
SyncMessagesLog.clear();
|
|
20
|
+
jazzCloud = setupTestNode({ isSyncServer: true });
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
describe("syncing deleted coValues", () => {
|
|
24
|
+
test("client loads a deleted coValue from server (tombstone-only)", async () => {
|
|
25
|
+
const { node: client } = setupTestNode({ connected: true });
|
|
26
|
+
|
|
27
|
+
const group = jazzCloud.node.createGroup();
|
|
28
|
+
const map = group.createMap();
|
|
29
|
+
map.set("hello", "world", "trusting");
|
|
30
|
+
|
|
31
|
+
// Delete on the server before the client loads.
|
|
32
|
+
map.core.deleteCoValue();
|
|
33
|
+
expect(map.core.isDeleted).toBe(true);
|
|
34
|
+
|
|
35
|
+
const mapOnClient = await loadCoValueOrFail(client, map.id);
|
|
36
|
+
const mapCoreOnClient = client.expectCoValueLoaded(map.id);
|
|
37
|
+
|
|
38
|
+
expect(mapCoreOnClient.isDeleted).toBe(true);
|
|
39
|
+
// Historical content should not be synced.
|
|
40
|
+
expect(mapOnClient.get("hello")).toBeUndefined();
|
|
41
|
+
|
|
42
|
+
expect(
|
|
43
|
+
SyncMessagesLog.getMessages({
|
|
44
|
+
Group: group.core,
|
|
45
|
+
Map: map.core,
|
|
46
|
+
}),
|
|
47
|
+
).toMatchInlineSnapshot(`
|
|
48
|
+
[
|
|
49
|
+
"client -> server | LOAD Map sessions: empty",
|
|
50
|
+
"server -> client | CONTENT Group header: true new: After: 0 New: 3",
|
|
51
|
+
"server -> client | CONTENT Map header: true new: After: 0 New: 1",
|
|
52
|
+
"client -> server | KNOWN Group sessions: header/3",
|
|
53
|
+
"client -> server | KNOWN Map sessions: header/1",
|
|
54
|
+
]
|
|
55
|
+
`);
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
test("inbound filtering: after deletion, non-delete sessions in the same content message are ignored", async () => {
|
|
59
|
+
const client = setupTestNode({ connected: false });
|
|
60
|
+
|
|
61
|
+
const group = jazzCloud.node.createGroup();
|
|
62
|
+
const map = group.createMap();
|
|
63
|
+
map.set("k", "v", "trusting");
|
|
64
|
+
|
|
65
|
+
const contentBeforeDelete = map.core.newContentSince(undefined)?.[0];
|
|
66
|
+
assert(contentBeforeDelete);
|
|
67
|
+
|
|
68
|
+
// Create a delete marker on the server, but also keep a historical session around.
|
|
69
|
+
map.core.deleteCoValue();
|
|
70
|
+
|
|
71
|
+
const content = map.core.newContentSince(undefined)?.[0];
|
|
72
|
+
assert(content);
|
|
73
|
+
|
|
74
|
+
const groupContent = group.core.newContentSince(undefined)?.[0];
|
|
75
|
+
assert(groupContent);
|
|
76
|
+
|
|
77
|
+
// We merge the content before delete with the content after delete to simulate an older peer that might send extra sessions in the same message
|
|
78
|
+
Object.assign(contentBeforeDelete.new, content.new);
|
|
79
|
+
|
|
80
|
+
client.node.syncManager.handleNewContent(groupContent, "import");
|
|
81
|
+
client.node.syncManager.handleNewContent(content, "import");
|
|
82
|
+
|
|
83
|
+
const coreOnClient = client.node.expectCoValueLoaded(map.id);
|
|
84
|
+
expect(coreOnClient.isDeleted).toBe(true);
|
|
85
|
+
|
|
86
|
+
const contentOnClient = expectMap(coreOnClient.getCurrentContent());
|
|
87
|
+
expect(contentOnClient.get("k")).toBeUndefined();
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
test("should wait for the dependencies to be available before processing the deleted session/transaction", async () => {
|
|
91
|
+
const client = setupTestNode({ connected: false });
|
|
92
|
+
|
|
93
|
+
const group = jazzCloud.node.createGroup();
|
|
94
|
+
const map = group.createMap();
|
|
95
|
+
|
|
96
|
+
// Create a delete marker on the server, but also keep a historical session around.
|
|
97
|
+
map.core.deleteCoValue();
|
|
98
|
+
|
|
99
|
+
const content = map.core.newContentSince(undefined)?.[0];
|
|
100
|
+
assert(content);
|
|
101
|
+
|
|
102
|
+
const groupContent = group.core.newContentSince(undefined)?.[0];
|
|
103
|
+
assert(groupContent);
|
|
104
|
+
|
|
105
|
+
client.node.syncManager.handleNewContent(content, "import");
|
|
106
|
+
client.node.syncManager.handleNewContent(groupContent, "import");
|
|
107
|
+
|
|
108
|
+
await waitFor(() => {
|
|
109
|
+
expect(client.node.expectCoValueLoaded(map.id).isDeleted).toBe(true);
|
|
110
|
+
});
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
test("outbound blocking: post-delete normal writes are ignored and do not produce content uploads", async () => {
|
|
114
|
+
const client = setupTestNode({ connected: true });
|
|
115
|
+
|
|
116
|
+
const group = jazzCloud.node.createGroup();
|
|
117
|
+
group.addMember("everyone", "writer");
|
|
118
|
+
const map = group.createMap();
|
|
119
|
+
map.set("a", 1, "trusting");
|
|
120
|
+
|
|
121
|
+
const mapOnClient = await loadCoValueOrFail(client.node, map.id);
|
|
122
|
+
|
|
123
|
+
// Delete on the server and wait for it to propagate.
|
|
124
|
+
map.core.deleteCoValue();
|
|
125
|
+
await waitFor(() => {
|
|
126
|
+
expect(mapOnClient.core.isDeleted).toBe(true);
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
SyncMessagesLog.clear();
|
|
130
|
+
|
|
131
|
+
mapOnClient.set("x", "y", "trusting");
|
|
132
|
+
|
|
133
|
+
await new Promise((resolve) => setTimeout(resolve, 10));
|
|
134
|
+
|
|
135
|
+
// Ensure we didn't produce outgoing content uploads as a result of the rejected write.
|
|
136
|
+
const messages = SyncMessagesLog.getMessages({
|
|
137
|
+
Group: group.core,
|
|
138
|
+
Map: map.core,
|
|
139
|
+
});
|
|
140
|
+
expect(messages.some((m) => m.includes("CONTENT Map"))).toBe(false);
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
test("delete should be propagated to client-to-client sync", async () => {
|
|
144
|
+
const alice = setupTestNode();
|
|
145
|
+
alice.connectToSyncServer({
|
|
146
|
+
ourName: "alice",
|
|
147
|
+
});
|
|
148
|
+
const bob = setupTestNode();
|
|
149
|
+
bob.connectToSyncServer({
|
|
150
|
+
ourName: "bob",
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
const group = alice.node.createGroup();
|
|
154
|
+
const map = group.createMap();
|
|
155
|
+
map.set("hello", "world", "trusting");
|
|
156
|
+
map.core.deleteCoValue();
|
|
157
|
+
|
|
158
|
+
await loadCoValueOrFail(bob.node, map.id);
|
|
159
|
+
|
|
160
|
+
await waitFor(() => {
|
|
161
|
+
expect(bob.node.expectCoValueLoaded(map.id).isDeleted).toBe(true);
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
expect(
|
|
165
|
+
SyncMessagesLog.getMessages({
|
|
166
|
+
Group: group.core,
|
|
167
|
+
Map: map.core,
|
|
168
|
+
}),
|
|
169
|
+
).toMatchInlineSnapshot(`
|
|
170
|
+
[
|
|
171
|
+
"bob -> server | LOAD Map sessions: empty",
|
|
172
|
+
"alice -> server | CONTENT Group header: true new: After: 0 New: 3",
|
|
173
|
+
"alice -> server | CONTENT Map header: true new: After: 0 New: 1",
|
|
174
|
+
"server -> bob | KNOWN Map sessions: empty",
|
|
175
|
+
"server -> alice | KNOWN Group sessions: header/3",
|
|
176
|
+
"server -> alice | KNOWN Map sessions: header/1",
|
|
177
|
+
"server -> bob | CONTENT Group header: true new: After: 0 New: 3",
|
|
178
|
+
"server -> bob | CONTENT Map header: true new: After: 0 New: 1",
|
|
179
|
+
"bob -> server | KNOWN Group sessions: header/3",
|
|
180
|
+
"bob -> server | KNOWN Map sessions: header/1",
|
|
181
|
+
]
|
|
182
|
+
`);
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
test("content synced after deletion should be ignored", async () => {
|
|
186
|
+
const alice = setupTestNode({ connected: true });
|
|
187
|
+
const bob = setupTestNode();
|
|
188
|
+
|
|
189
|
+
const { peerState: bobConnection } = bob.connectToSyncServer({
|
|
190
|
+
ourName: "bob",
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
const group = alice.node.createGroup();
|
|
194
|
+
group.addMember("everyone", "writer");
|
|
195
|
+
const map = group.createMap();
|
|
196
|
+
map.set("hello", "world", "trusting");
|
|
197
|
+
|
|
198
|
+
const mapOnBob = await loadCoValueOrFail(bob.node, map.id);
|
|
199
|
+
|
|
200
|
+
SyncMessagesLog.clear();
|
|
201
|
+
|
|
202
|
+
bobConnection.gracefulShutdown();
|
|
203
|
+
|
|
204
|
+
map.core.deleteCoValue();
|
|
205
|
+
|
|
206
|
+
await map.core.waitForSync();
|
|
207
|
+
|
|
208
|
+
mapOnBob.set("hello", "updated", "trusting");
|
|
209
|
+
|
|
210
|
+
bob.connectToSyncServer({
|
|
211
|
+
ourName: "bob",
|
|
212
|
+
});
|
|
213
|
+
|
|
214
|
+
await mapOnBob.core.waitForSync();
|
|
215
|
+
|
|
216
|
+
expect(
|
|
217
|
+
SyncMessagesLog.getMessages({
|
|
218
|
+
Group: group.core,
|
|
219
|
+
Map: map.core,
|
|
220
|
+
}),
|
|
221
|
+
).toMatchInlineSnapshot(`
|
|
222
|
+
[
|
|
223
|
+
"client -> server | CONTENT Map header: false new: After: 0 New: 1",
|
|
224
|
+
"server -> client | KNOWN Map sessions: header/2",
|
|
225
|
+
"server -> bob | CONTENT Map header: false new: After: 0 New: 1",
|
|
226
|
+
"bob -> server | LOAD Group sessions: header/5",
|
|
227
|
+
"bob -> server | LOAD Map sessions: header/2",
|
|
228
|
+
"bob -> server | CONTENT Map header: false new: After: 0 New: 1",
|
|
229
|
+
"server -> bob | KNOWN Group sessions: header/5",
|
|
230
|
+
"server -> bob | CONTENT Map header: false new: After: 0 New: 1",
|
|
231
|
+
"server -> bob | KNOWN Map sessions: header/3",
|
|
232
|
+
"bob -> server | KNOWN Map sessions: header/2",
|
|
233
|
+
]
|
|
234
|
+
`);
|
|
235
|
+
});
|
|
236
|
+
|
|
237
|
+
test("should handle concurrent delete operations", async () => {
|
|
238
|
+
const alice = await setupTestAccount();
|
|
239
|
+
alice.connectToSyncServer({
|
|
240
|
+
ourName: "alice",
|
|
241
|
+
});
|
|
242
|
+
const bob = await setupTestAccount();
|
|
243
|
+
bob.connectToSyncServer({
|
|
244
|
+
ourName: "bob",
|
|
245
|
+
});
|
|
246
|
+
|
|
247
|
+
const group = jazzCloud.node.createGroup();
|
|
248
|
+
group.addMemberInternal(alice.account, "admin");
|
|
249
|
+
group.addMemberInternal(bob.account, "admin");
|
|
250
|
+
|
|
251
|
+
const map = group.createMap();
|
|
252
|
+
map.set("counter", 0, "trusting");
|
|
253
|
+
map.set("counter", 1, "trusting");
|
|
254
|
+
|
|
255
|
+
const mapOnAlice = await loadCoValueOrFail(alice.node, map.id);
|
|
256
|
+
const mapOnBob = await loadCoValueOrFail(bob.node, map.id);
|
|
257
|
+
|
|
258
|
+
SyncMessagesLog.clear();
|
|
259
|
+
|
|
260
|
+
mapOnAlice.core.deleteCoValue();
|
|
261
|
+
mapOnBob.core.deleteCoValue();
|
|
262
|
+
|
|
263
|
+
await mapOnAlice.core.waitForSync();
|
|
264
|
+
await mapOnBob.core.waitForSync();
|
|
265
|
+
|
|
266
|
+
expect(
|
|
267
|
+
SyncMessagesLog.getMessages({
|
|
268
|
+
Group: group.core,
|
|
269
|
+
Map: map.core,
|
|
270
|
+
}),
|
|
271
|
+
).toMatchInlineSnapshot(`
|
|
272
|
+
[
|
|
273
|
+
"alice -> server | CONTENT Map header: false new: After: 0 New: 1",
|
|
274
|
+
"bob -> server | CONTENT Map header: false new: After: 0 New: 1",
|
|
275
|
+
"server -> alice | KNOWN Map sessions: header/3",
|
|
276
|
+
"server -> bob | CONTENT Map header: false new: After: 0 New: 1",
|
|
277
|
+
"server -> bob | KNOWN Map sessions: header/4",
|
|
278
|
+
"server -> alice | CONTENT Map header: false new: After: 0 New: 1",
|
|
279
|
+
"bob -> server | KNOWN Map sessions: header/4",
|
|
280
|
+
]
|
|
281
|
+
`);
|
|
282
|
+
|
|
283
|
+
expect(map.core.isDeleted).toBe(true);
|
|
284
|
+
|
|
285
|
+
const sessions = map.core.knownState().sessions;
|
|
286
|
+
|
|
287
|
+
expect(Object.keys(sessions)).toHaveLength(2);
|
|
288
|
+
expect(
|
|
289
|
+
Object.keys(sessions).every((sessionID) =>
|
|
290
|
+
isDeleteSessionID(sessionID as SessionID),
|
|
291
|
+
),
|
|
292
|
+
).toBe(true);
|
|
293
|
+
});
|
|
294
|
+
});
|
|
@@ -50,6 +50,47 @@ describe("sync after the garbage collector has run", () => {
|
|
|
50
50
|
const mapOnClient = await loadCoValueOrFail(client.node, map.id);
|
|
51
51
|
expect(mapOnClient.get("hello")).toEqual("world");
|
|
52
52
|
|
|
53
|
+
expect(
|
|
54
|
+
SyncMessagesLog.getMessages({
|
|
55
|
+
Group: group.core,
|
|
56
|
+
Map: map.core,
|
|
57
|
+
}),
|
|
58
|
+
).toMatchInlineSnapshot(`
|
|
59
|
+
[
|
|
60
|
+
"client -> server | LOAD Map sessions: empty",
|
|
61
|
+
"server -> storage | LOAD Map sessions: empty",
|
|
62
|
+
"storage -> server | CONTENT Map header: true new: After: 0 New: 1",
|
|
63
|
+
"server -> client | CONTENT Group header: true new: After: 0 New: 3",
|
|
64
|
+
"server -> client | CONTENT Map header: true new: After: 0 New: 1",
|
|
65
|
+
"client -> server | KNOWN Group sessions: header/3",
|
|
66
|
+
"client -> server | KNOWN Map sessions: header/1",
|
|
67
|
+
]
|
|
68
|
+
`);
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
test("loading a coValue from the sync server that was removed by the garbage collector along with its owner", async () => {
|
|
72
|
+
const client = setupTestNode();
|
|
73
|
+
|
|
74
|
+
client.connectToSyncServer();
|
|
75
|
+
|
|
76
|
+
const group = jazzCloud.node.createGroup();
|
|
77
|
+
const map = group.createMap();
|
|
78
|
+
map.set("hello", "world", "trusting");
|
|
79
|
+
|
|
80
|
+
await map.core.waitForSync();
|
|
81
|
+
|
|
82
|
+
// force the garbage collector to run twice to remove the map and its group
|
|
83
|
+
jazzCloud.node.garbageCollector?.collect();
|
|
84
|
+
jazzCloud.node.garbageCollector?.collect();
|
|
85
|
+
|
|
86
|
+
expect(jazzCloud.node.getCoValue(group.id).isAvailable()).toBe(false);
|
|
87
|
+
expect(jazzCloud.node.getCoValue(map.id).isAvailable()).toBe(false);
|
|
88
|
+
|
|
89
|
+
SyncMessagesLog.clear();
|
|
90
|
+
|
|
91
|
+
const mapOnClient = await loadCoValueOrFail(client.node, map.id);
|
|
92
|
+
expect(mapOnClient.get("hello")).toEqual("world");
|
|
93
|
+
|
|
53
94
|
expect(
|
|
54
95
|
SyncMessagesLog.getMessages({
|
|
55
96
|
Group: group.core,
|
|
@@ -103,7 +144,6 @@ describe("sync after the garbage collector has run", () => {
|
|
|
103
144
|
[
|
|
104
145
|
"client -> server | CONTENT Map header: false new: After: 0 New: 1",
|
|
105
146
|
"server -> storage | LOAD Map sessions: empty",
|
|
106
|
-
"storage -> server | CONTENT Group header: true new: After: 0 New: 5",
|
|
107
147
|
"storage -> server | CONTENT Map header: true new: After: 0 New: 1",
|
|
108
148
|
"server -> client | KNOWN Map sessions: header/2",
|
|
109
149
|
"server -> storage | CONTENT Map header: false new: After: 0 New: 1",
|
|
@@ -112,41 +152,30 @@ describe("sync after the garbage collector has run", () => {
|
|
|
112
152
|
});
|
|
113
153
|
|
|
114
154
|
test("syncing a coValue that was removed by the garbage collector", async () => {
|
|
115
|
-
const edge = setupTestNode();
|
|
116
|
-
edge.addStorage({
|
|
117
|
-
ourName: "edge",
|
|
118
|
-
});
|
|
119
|
-
edge.connectToSyncServer({
|
|
120
|
-
syncServer: jazzCloud.node,
|
|
121
|
-
syncServerName: "server",
|
|
122
|
-
ourName: "edge",
|
|
123
|
-
});
|
|
124
|
-
edge.node.enableGarbageCollector();
|
|
125
155
|
const client = setupTestNode();
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
syncServer: edge.node,
|
|
129
|
-
syncServerName: "edge",
|
|
156
|
+
client.addStorage({
|
|
157
|
+
ourName: "client",
|
|
130
158
|
});
|
|
159
|
+
client.node.enableGarbageCollector();
|
|
131
160
|
|
|
132
|
-
const group =
|
|
133
|
-
group.addMember("everyone", "writer");
|
|
134
|
-
|
|
135
|
-
await group.core.waitForSync();
|
|
136
|
-
|
|
161
|
+
const group = client.node.createGroup();
|
|
137
162
|
const map = group.createMap();
|
|
138
|
-
|
|
139
163
|
map.set("hello", "updated", "trusting");
|
|
140
164
|
|
|
141
165
|
// force the garbage collector to run before the transaction is synced
|
|
142
|
-
|
|
143
|
-
expect(
|
|
166
|
+
client.node.garbageCollector?.collect();
|
|
167
|
+
expect(client.node.getCoValue(map.id).isAvailable()).toBe(false);
|
|
144
168
|
|
|
145
169
|
SyncMessagesLog.clear();
|
|
146
170
|
|
|
171
|
+
client.connectToSyncServer();
|
|
172
|
+
|
|
173
|
+
// Wait for unsynced coValues to be resumed and synced after connecting to server
|
|
174
|
+
await client.node.syncManager.waitForAllCoValuesSync();
|
|
175
|
+
|
|
147
176
|
// The storage should work even after the coValue is unmounted, so the load should be successful
|
|
148
|
-
const
|
|
149
|
-
expect(
|
|
177
|
+
const mapOnServer = await loadCoValueOrFail(jazzCloud.node, map.id);
|
|
178
|
+
expect(mapOnServer.get("hello")).toEqual("updated");
|
|
150
179
|
|
|
151
180
|
expect(
|
|
152
181
|
SyncMessagesLog.getMessages({
|
|
@@ -155,18 +184,22 @@ describe("sync after the garbage collector has run", () => {
|
|
|
155
184
|
}),
|
|
156
185
|
).toMatchInlineSnapshot(`
|
|
157
186
|
[
|
|
158
|
-
"client ->
|
|
159
|
-
"
|
|
160
|
-
"
|
|
161
|
-
"
|
|
162
|
-
"
|
|
163
|
-
"
|
|
164
|
-
"
|
|
165
|
-
"
|
|
166
|
-
"server ->
|
|
187
|
+
"client -> server | LOAD Map sessions: empty",
|
|
188
|
+
"client -> server | LOAD Group sessions: header/3",
|
|
189
|
+
"client -> storage | CONTENT Group header: true new: After: 0 New: 3",
|
|
190
|
+
"client -> server | CONTENT Group header: true new: After: 0 New: 3",
|
|
191
|
+
"client -> storage | CONTENT Map header: true new: After: 0 New: 1",
|
|
192
|
+
"client -> server | CONTENT Map header: true new: After: 0 New: 1",
|
|
193
|
+
"server -> storage | LOAD Map sessions: empty",
|
|
194
|
+
"storage -> server | KNOWN Map sessions: empty",
|
|
195
|
+
"server -> client | KNOWN Map sessions: empty",
|
|
196
|
+
"server -> storage | GET_KNOWN_STATE Group",
|
|
197
|
+
"storage -> server | GET_KNOWN_STATE_RESULT Group sessions: empty",
|
|
198
|
+
"server -> client | KNOWN Group sessions: empty",
|
|
199
|
+
"server -> client | KNOWN Group sessions: header/3",
|
|
200
|
+
"server -> storage | CONTENT Group header: true new: After: 0 New: 3",
|
|
201
|
+
"server -> client | KNOWN Map sessions: header/1",
|
|
167
202
|
"server -> storage | CONTENT Map header: true new: After: 0 New: 1",
|
|
168
|
-
"client -> edge | KNOWN Group sessions: header/5",
|
|
169
|
-
"client -> edge | KNOWN Map sessions: header/1",
|
|
170
203
|
]
|
|
171
204
|
`);
|
|
172
205
|
});
|
|
@@ -514,7 +514,7 @@ describe("loading coValues from server", () => {
|
|
|
514
514
|
});
|
|
515
515
|
|
|
516
516
|
// Makes the CoValues unavailable on the server
|
|
517
|
-
jazzCloud.restart();
|
|
517
|
+
await jazzCloud.restart();
|
|
518
518
|
|
|
519
519
|
const client = setupTestNode({
|
|
520
520
|
connected: true,
|
|
@@ -1476,7 +1476,7 @@ describe("lazy storage load optimization", () => {
|
|
|
1476
1476
|
|
|
1477
1477
|
// Restart the server to clear memory (keeping storage)
|
|
1478
1478
|
// Now the server has no CoValues in memory, only in storage
|
|
1479
|
-
jazzCloud.restart();
|
|
1479
|
+
await jazzCloud.restart();
|
|
1480
1480
|
jazzCloud.node.setStorage(storage);
|
|
1481
1481
|
|
|
1482
1482
|
SyncMessagesLog.clear();
|
|
@@ -1519,7 +1519,7 @@ describe("lazy storage load optimization", () => {
|
|
|
1519
1519
|
await map.core.waitForSync();
|
|
1520
1520
|
|
|
1521
1521
|
// Restart the server to clear memory (keeping storage)
|
|
1522
|
-
jazzCloud.restart();
|
|
1522
|
+
await jazzCloud.restart();
|
|
1523
1523
|
jazzCloud.node.setStorage(storage);
|
|
1524
1524
|
|
|
1525
1525
|
SyncMessagesLog.clear();
|
|
@@ -1643,7 +1643,6 @@ describe("lazy storage load optimization", () => {
|
|
|
1643
1643
|
[
|
|
1644
1644
|
"client -> server | CONTENT Map header: false new: After: 0 New: 1",
|
|
1645
1645
|
"server -> storage | LOAD Map sessions: empty",
|
|
1646
|
-
"storage -> server | CONTENT Group header: true new: After: 0 New: 5",
|
|
1647
1646
|
"storage -> server | CONTENT Map header: true new: After: 0 New: 1",
|
|
1648
1647
|
"server -> client | KNOWN Map sessions: header/2",
|
|
1649
1648
|
"server -> storage | CONTENT Map header: false new: After: 0 New: 1",
|
|
@@ -1702,7 +1701,6 @@ describe("lazy storage load optimization", () => {
|
|
|
1702
1701
|
[
|
|
1703
1702
|
"client -> server | CONTENT Map header: false new: After: 0 New: 1",
|
|
1704
1703
|
"server -> storage | LOAD Map sessions: empty",
|
|
1705
|
-
"storage -> server | CONTENT Group header: true new: After: 0 New: 5",
|
|
1706
1704
|
"storage -> server | CONTENT Map header: true new: After: 0 New: 73 expectContentUntil: header/201",
|
|
1707
1705
|
"server -> client | KNOWN Map sessions: header/74",
|
|
1708
1706
|
"server -> storage | CONTENT Map header: false new: After: 0 New: 1",
|
|
@@ -11,7 +11,8 @@ import {
|
|
|
11
11
|
setupTestNode,
|
|
12
12
|
waitFor,
|
|
13
13
|
} from "./testUtils";
|
|
14
|
-
import {
|
|
14
|
+
import { Stringified } from "../jsonStringify";
|
|
15
|
+
import { JsonValue } from "../jsonValue";
|
|
15
16
|
|
|
16
17
|
// We want to simulate a real world communication that happens asynchronously
|
|
17
18
|
TEST_NODE_CONFIG.withAsyncPeers = true;
|
|
@@ -325,7 +326,9 @@ describe("multiple clients syncing with the a cloud-like server mesh", () => {
|
|
|
325
326
|
|
|
326
327
|
msg.new[mesh.edgeFrance.node.currentSessionID]!.newTransactions.push({
|
|
327
328
|
privacy: "trusting",
|
|
328
|
-
changes:
|
|
329
|
+
changes: JSON.stringify([
|
|
330
|
+
{ op: "set", key: "hello", value: "updated" },
|
|
331
|
+
]) as Stringified<JsonValue[]>,
|
|
329
332
|
madeAt: Date.now(),
|
|
330
333
|
});
|
|
331
334
|
|
|
@@ -506,7 +509,7 @@ describe("multiple clients syncing with the a cloud-like server mesh", () => {
|
|
|
506
509
|
]
|
|
507
510
|
`);
|
|
508
511
|
|
|
509
|
-
edge.restart();
|
|
512
|
+
await edge.restart();
|
|
510
513
|
|
|
511
514
|
edge.connectToSyncServer({
|
|
512
515
|
syncServerName: "core",
|
|
@@ -167,7 +167,7 @@ describe("peer reconciliation", () => {
|
|
|
167
167
|
|
|
168
168
|
await map.core.waitForSync();
|
|
169
169
|
|
|
170
|
-
jazzCloud.restart();
|
|
170
|
+
await jazzCloud.restart();
|
|
171
171
|
SyncMessagesLog.clear();
|
|
172
172
|
client.connectToSyncServer();
|
|
173
173
|
|
|
@@ -222,7 +222,7 @@ describe("peer reconciliation", () => {
|
|
|
222
222
|
|
|
223
223
|
await map.core.waitForSync();
|
|
224
224
|
|
|
225
|
-
jazzCloud.restart();
|
|
225
|
+
await jazzCloud.restart();
|
|
226
226
|
SyncMessagesLog.clear();
|
|
227
227
|
client.connectToSyncServer();
|
|
228
228
|
|
|
@@ -305,7 +305,7 @@ describe("peer reconciliation", () => {
|
|
|
305
305
|
|
|
306
306
|
await map.core.waitForSync();
|
|
307
307
|
|
|
308
|
-
jazzCloud.restart();
|
|
308
|
+
await jazzCloud.restart();
|
|
309
309
|
|
|
310
310
|
SyncMessagesLog.clear();
|
|
311
311
|
client.connectToSyncServer();
|
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
vi,
|
|
9
9
|
} from "vitest";
|
|
10
10
|
|
|
11
|
+
import type { JsonValue } from "../exports";
|
|
11
12
|
import { cojsonInternals, emptyKnownState } from "../exports";
|
|
12
13
|
import {
|
|
13
14
|
SyncMessagesLog,
|
|
@@ -19,7 +20,7 @@ import {
|
|
|
19
20
|
tearDownTestMetricReader,
|
|
20
21
|
waitFor,
|
|
21
22
|
} from "./testUtils";
|
|
22
|
-
import {
|
|
23
|
+
import { Stringified } from "../jsonStringify";
|
|
23
24
|
|
|
24
25
|
// We want to simulate a real world communication that happens asynchronously
|
|
25
26
|
TEST_NODE_CONFIG.withAsyncPeers = true;
|
|
@@ -83,7 +84,7 @@ describe("client with storage syncs with server", () => {
|
|
|
83
84
|
|
|
84
85
|
await loadCoValueOrFail(client.node, map.id);
|
|
85
86
|
|
|
86
|
-
client.restart();
|
|
87
|
+
await client.restart();
|
|
87
88
|
|
|
88
89
|
client.connectToSyncServer();
|
|
89
90
|
client.addStorage({
|
|
@@ -167,7 +168,7 @@ describe("client with storage syncs with server", () => {
|
|
|
167
168
|
|
|
168
169
|
await map.core.waitForSync();
|
|
169
170
|
|
|
170
|
-
client.restart();
|
|
171
|
+
await client.restart();
|
|
171
172
|
|
|
172
173
|
client.addStorage({
|
|
173
174
|
storage,
|
|
@@ -217,7 +218,7 @@ describe("client with storage syncs with server", () => {
|
|
|
217
218
|
branch.set("branchKey", "branchValue");
|
|
218
219
|
await branch.core.waitForSync();
|
|
219
220
|
|
|
220
|
-
client.restart();
|
|
221
|
+
await client.restart();
|
|
221
222
|
client.addStorage({
|
|
222
223
|
storage,
|
|
223
224
|
});
|
|
@@ -388,7 +389,7 @@ describe("client syncs with a server with storage", () => {
|
|
|
388
389
|
|
|
389
390
|
SyncMessagesLog.clear();
|
|
390
391
|
|
|
391
|
-
client.restart();
|
|
392
|
+
await client.restart();
|
|
392
393
|
|
|
393
394
|
client.connectToSyncServer({
|
|
394
395
|
ourName: "client",
|
|
@@ -457,7 +458,7 @@ describe("client syncs with a server with storage", () => {
|
|
|
457
458
|
|
|
458
459
|
expect(correctionSpy).not.toHaveBeenCalled();
|
|
459
460
|
|
|
460
|
-
client.restart();
|
|
461
|
+
await client.restart();
|
|
461
462
|
|
|
462
463
|
client.connectToSyncServer({
|
|
463
464
|
ourName: "client",
|
|
@@ -572,7 +573,9 @@ describe("client syncs with a server with storage", () => {
|
|
|
572
573
|
const invalidMapContent = structuredClone(mapContent);
|
|
573
574
|
invalidMapContent.new[bob.node.currentSessionID]!.newTransactions.push({
|
|
574
575
|
privacy: "trusting",
|
|
575
|
-
changes:
|
|
576
|
+
changes: JSON.stringify([
|
|
577
|
+
{ op: "set", key: "hello", value: "updated" },
|
|
578
|
+
]) as Stringified<JsonValue[]>,
|
|
576
579
|
madeAt: Date.now(),
|
|
577
580
|
});
|
|
578
581
|
client.node.syncManager.handleNewContent(invalidMapContent, "import");
|
|
@@ -771,7 +774,7 @@ describe("client syncs with a server with storage", () => {
|
|
|
771
774
|
|
|
772
775
|
SyncMessagesLog.clear();
|
|
773
776
|
|
|
774
|
-
syncServer.restart();
|
|
777
|
+
await syncServer.restart();
|
|
775
778
|
syncServer.addStorage({
|
|
776
779
|
ourName: "syncServer",
|
|
777
780
|
storage,
|
|
@@ -848,7 +851,7 @@ describe("client syncs with a server with storage", () => {
|
|
|
848
851
|
]);
|
|
849
852
|
|
|
850
853
|
// Restart to load from storage
|
|
851
|
-
client.restart();
|
|
854
|
+
await client.restart();
|
|
852
855
|
client.addStorage({ storage });
|
|
853
856
|
|
|
854
857
|
// Load all maps concurrently from storage
|
|
@@ -892,7 +895,7 @@ describe("client syncs with a server with storage", () => {
|
|
|
892
895
|
SyncMessagesLog.clear();
|
|
893
896
|
|
|
894
897
|
// Restart client with storage
|
|
895
|
-
client.restart();
|
|
898
|
+
await client.restart();
|
|
896
899
|
client.connectToSyncServer();
|
|
897
900
|
client.addStorage({ storage });
|
|
898
901
|
|
|
@@ -985,7 +988,7 @@ describe("client syncs with a server with storage", () => {
|
|
|
985
988
|
|
|
986
989
|
SyncMessagesLog.clear();
|
|
987
990
|
|
|
988
|
-
syncServer.restart();
|
|
991
|
+
await syncServer.restart();
|
|
989
992
|
syncServer.addStorage({
|
|
990
993
|
ourName: "syncServer",
|
|
991
994
|
storage,
|