cojson 0.19.2 → 0.19.4
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 +14 -0
- package/dist/coValues/coList.d.ts +10 -4
- package/dist/coValues/coList.d.ts.map +1 -1
- package/dist/coValues/coList.js +30 -4
- package/dist/coValues/coList.js.map +1 -1
- package/dist/coValues/coPlainText.d.ts +2 -1
- package/dist/coValues/coPlainText.d.ts.map +1 -1
- package/dist/coValues/coPlainText.js +5 -2
- package/dist/coValues/coPlainText.js.map +1 -1
- package/dist/storage/sqlite/client.d.ts +3 -3
- package/dist/storage/sqlite/client.d.ts.map +1 -1
- package/dist/storage/sqlite/client.js +1 -1
- package/dist/storage/sqlite/client.js.map +1 -1
- package/dist/storage/sqliteAsync/client.d.ts +3 -3
- package/dist/storage/sqliteAsync/client.d.ts.map +1 -1
- package/dist/storage/sqliteAsync/client.js +1 -1
- package/dist/storage/sqliteAsync/client.js.map +1 -1
- package/dist/storage/storageAsync.d.ts.map +1 -1
- package/dist/storage/storageAsync.js +7 -7
- package/dist/storage/storageAsync.js.map +1 -1
- package/dist/storage/storageSync.d.ts.map +1 -1
- package/dist/storage/storageSync.js +7 -7
- package/dist/storage/storageSync.js.map +1 -1
- package/dist/storage/types.d.ts +18 -14
- package/dist/storage/types.d.ts.map +1 -1
- package/dist/tests/coList.test.js +28 -1
- package/dist/tests/coList.test.js.map +1 -1
- package/dist/tests/sync.multipleServers.test.d.ts +2 -0
- package/dist/tests/sync.multipleServers.test.d.ts.map +1 -0
- package/dist/tests/sync.multipleServers.test.js +399 -0
- package/dist/tests/sync.multipleServers.test.js.map +1 -0
- package/package.json +3 -3
- package/src/coValues/coList.ts +41 -8
- package/src/coValues/coPlainText.ts +6 -2
- package/src/storage/sqlite/client.ts +6 -3
- package/src/storage/sqliteAsync/client.ts +8 -3
- package/src/storage/storageAsync.ts +8 -5
- package/src/storage/storageSync.ts +8 -5
- package/src/storage/types.ts +43 -37
- package/src/tests/coList.test.ts +36 -3
- package/src/tests/sync.multipleServers.test.ts +491 -0
|
@@ -0,0 +1,399 @@
|
|
|
1
|
+
import { beforeEach, describe, expect, test } from "vitest";
|
|
2
|
+
import { WasmCrypto } from "../crypto/WasmCrypto";
|
|
3
|
+
import { SyncMessagesLog, TEST_NODE_CONFIG, fillCoMapWithLargeData, loadCoValueOrFail, setupTestNode, waitFor, } from "./testUtils";
|
|
4
|
+
// We want to simulate a real world communication that happens asynchronously
|
|
5
|
+
TEST_NODE_CONFIG.withAsyncPeers = true;
|
|
6
|
+
const Crypto = await WasmCrypto.create();
|
|
7
|
+
let server1;
|
|
8
|
+
let server2;
|
|
9
|
+
beforeEach(async () => {
|
|
10
|
+
SyncMessagesLog.clear();
|
|
11
|
+
server1 = setupTestNode();
|
|
12
|
+
server2 = setupTestNode();
|
|
13
|
+
});
|
|
14
|
+
function connectServers(client) {
|
|
15
|
+
client.connectToSyncServer({
|
|
16
|
+
ourName: "client",
|
|
17
|
+
syncServerName: "server1",
|
|
18
|
+
syncServer: server1.node,
|
|
19
|
+
});
|
|
20
|
+
client.connectToSyncServer({
|
|
21
|
+
ourName: "client",
|
|
22
|
+
syncServerName: "server2",
|
|
23
|
+
syncServer: server2.node,
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
describe("multiple servers peers", () => {
|
|
27
|
+
test("coValue uploading", async () => {
|
|
28
|
+
const client = setupTestNode();
|
|
29
|
+
connectServers(client);
|
|
30
|
+
const group = client.node.createGroup();
|
|
31
|
+
const map = group.createMap();
|
|
32
|
+
map.set("hello", "world", "trusting");
|
|
33
|
+
await map.core.waitForSync();
|
|
34
|
+
expect(SyncMessagesLog.getMessages({
|
|
35
|
+
Group: group.core,
|
|
36
|
+
Map: map.core,
|
|
37
|
+
})).toMatchInlineSnapshot(`
|
|
38
|
+
[
|
|
39
|
+
"client -> server1 | CONTENT Group header: true new: After: 0 New: 3",
|
|
40
|
+
"client -> server2 | CONTENT Group header: true new: After: 0 New: 3",
|
|
41
|
+
"client -> server1 | CONTENT Map header: true new: After: 0 New: 1",
|
|
42
|
+
"client -> server2 | CONTENT Map header: true new: After: 0 New: 1",
|
|
43
|
+
"server1 -> client | KNOWN Group sessions: header/3",
|
|
44
|
+
"server2 -> client | KNOWN Group sessions: header/3",
|
|
45
|
+
"server1 -> client | KNOWN Map sessions: header/1",
|
|
46
|
+
"server2 -> client | KNOWN Map sessions: header/1",
|
|
47
|
+
]
|
|
48
|
+
`);
|
|
49
|
+
const mapOnServer1 = server1.node.getCoValue(map.id);
|
|
50
|
+
const mapOnServer2 = server2.node.getCoValue(map.id);
|
|
51
|
+
expect(mapOnServer1.knownState()).toEqual(map.core.knownState());
|
|
52
|
+
expect(mapOnServer2.knownState()).toEqual(map.core.knownState());
|
|
53
|
+
});
|
|
54
|
+
test("coValue sync across clients", async () => {
|
|
55
|
+
const client = setupTestNode();
|
|
56
|
+
connectServers(client);
|
|
57
|
+
const group = client.node.createGroup();
|
|
58
|
+
const map = group.createMap();
|
|
59
|
+
map.set("count", 1, "trusting");
|
|
60
|
+
const session2 = client.spawnNewSession();
|
|
61
|
+
connectServers(session2);
|
|
62
|
+
const mapOnSession2 = await loadCoValueOrFail(session2.node, map.id);
|
|
63
|
+
mapOnSession2.set("count", 2, "trusting");
|
|
64
|
+
map.set("count", 3, "trusting");
|
|
65
|
+
await new Promise((resolve) => setTimeout(resolve, 10));
|
|
66
|
+
mapOnSession2.set("count", 4, "trusting");
|
|
67
|
+
await waitFor(() => {
|
|
68
|
+
expect(map.get("count")).toEqual(4);
|
|
69
|
+
expect(mapOnSession2.get("count")).toEqual(4);
|
|
70
|
+
});
|
|
71
|
+
expect(SyncMessagesLog.getMessages({
|
|
72
|
+
Group: group.core,
|
|
73
|
+
Map: map.core,
|
|
74
|
+
})).toMatchInlineSnapshot(`
|
|
75
|
+
[
|
|
76
|
+
"client -> server1 | LOAD Map sessions: empty",
|
|
77
|
+
"client -> server2 | LOAD Map sessions: empty",
|
|
78
|
+
"client -> server1 | CONTENT Group header: true new: After: 0 New: 3",
|
|
79
|
+
"client -> server2 | CONTENT Group header: true new: After: 0 New: 3",
|
|
80
|
+
"client -> server1 | CONTENT Map header: true new: After: 0 New: 1",
|
|
81
|
+
"client -> server2 | CONTENT Map header: true new: After: 0 New: 1",
|
|
82
|
+
"server1 -> client | KNOWN Map sessions: empty",
|
|
83
|
+
"server2 -> client | KNOWN Map sessions: empty",
|
|
84
|
+
"server1 -> client | KNOWN Group sessions: header/3",
|
|
85
|
+
"server2 -> client | KNOWN Group sessions: header/3",
|
|
86
|
+
"server1 -> client | KNOWN Map sessions: header/1",
|
|
87
|
+
"server1 -> client | CONTENT Group header: true new: After: 0 New: 3",
|
|
88
|
+
"server1 -> client | CONTENT Map header: true new: After: 0 New: 1",
|
|
89
|
+
"server2 -> client | KNOWN Map sessions: header/1",
|
|
90
|
+
"server2 -> client | CONTENT Group header: true new: After: 0 New: 3",
|
|
91
|
+
"server2 -> client | CONTENT Map header: true new: After: 0 New: 1",
|
|
92
|
+
"client -> server1 | KNOWN Group sessions: header/3",
|
|
93
|
+
"client -> server2 | LOAD Group sessions: header/3",
|
|
94
|
+
"client -> server1 | KNOWN Map sessions: header/1",
|
|
95
|
+
"client -> server2 | CONTENT Map header: true new: After: 0 New: 1",
|
|
96
|
+
"client -> server1 | CONTENT Map header: false new: After: 0 New: 1",
|
|
97
|
+
"client -> server2 | CONTENT Map header: false new: After: 0 New: 1",
|
|
98
|
+
"client -> server1 | CONTENT Map header: false new: After: 1 New: 1",
|
|
99
|
+
"client -> server2 | CONTENT Map header: false new: After: 1 New: 1",
|
|
100
|
+
"client -> server2 | KNOWN Group sessions: header/3",
|
|
101
|
+
"client -> server2 | CONTENT Group header: false new: After: 0 New: 3",
|
|
102
|
+
"client -> server2 | KNOWN Map sessions: header/2",
|
|
103
|
+
"server2 -> client | KNOWN Map sessions: header/1",
|
|
104
|
+
"server1 -> client | KNOWN Map sessions: header/2",
|
|
105
|
+
"server1 -> client | CONTENT Map header: false new: After: 0 New: 1",
|
|
106
|
+
"server2 -> client | KNOWN Map sessions: header/2",
|
|
107
|
+
"server2 -> client | CONTENT Map header: false new: After: 0 New: 1",
|
|
108
|
+
"server1 -> client | KNOWN Map sessions: header/3",
|
|
109
|
+
"server1 -> client | CONTENT Map header: false new: After: 1 New: 1",
|
|
110
|
+
"server2 -> client | KNOWN Map sessions: header/3",
|
|
111
|
+
"server2 -> client | CONTENT Map header: false new: After: 1 New: 1",
|
|
112
|
+
"server2 -> client | KNOWN Group sessions: header/3",
|
|
113
|
+
"client -> server1 | KNOWN Map sessions: header/3",
|
|
114
|
+
"client -> server2 | CONTENT Map header: false new: After: 0 New: 1",
|
|
115
|
+
"client -> server2 | KNOWN Map sessions: header/3",
|
|
116
|
+
"client -> server1 | KNOWN Map sessions: header/3",
|
|
117
|
+
"client -> server2 | CONTENT Map header: false new: After: 1 New: 1",
|
|
118
|
+
"client -> server2 | KNOWN Map sessions: header/3",
|
|
119
|
+
"server2 -> client | KNOWN Map sessions: header/3",
|
|
120
|
+
"server2 -> client | KNOWN Map sessions: header/3",
|
|
121
|
+
"client -> server1 | CONTENT Map header: false new: After: 1 New: 1",
|
|
122
|
+
"client -> server2 | CONTENT Map header: false new: After: 1 New: 1",
|
|
123
|
+
"server1 -> client | KNOWN Map sessions: header/4",
|
|
124
|
+
"server1 -> client | CONTENT Map header: false new: After: 1 New: 1",
|
|
125
|
+
"server2 -> client | KNOWN Map sessions: header/4",
|
|
126
|
+
"server2 -> client | CONTENT Map header: false new: After: 1 New: 1",
|
|
127
|
+
"client -> server1 | KNOWN Map sessions: header/4",
|
|
128
|
+
"client -> server2 | CONTENT Map header: false new: After: 1 New: 1",
|
|
129
|
+
"client -> server2 | KNOWN Map sessions: header/4",
|
|
130
|
+
"server2 -> client | KNOWN Map sessions: header/4",
|
|
131
|
+
]
|
|
132
|
+
`);
|
|
133
|
+
const mapOnServer1 = server1.node.getCoValue(map.id);
|
|
134
|
+
const mapOnServer2 = server2.node.getCoValue(map.id);
|
|
135
|
+
expect(mapOnServer1.knownState()).toEqual(map.core.knownState());
|
|
136
|
+
expect(mapOnServer2.knownState()).toEqual(map.core.knownState());
|
|
137
|
+
});
|
|
138
|
+
test("coValue with parent groups uploading", async () => {
|
|
139
|
+
const client = setupTestNode();
|
|
140
|
+
connectServers(client);
|
|
141
|
+
const group = client.node.createGroup();
|
|
142
|
+
const parentGroup = client.node.createGroup();
|
|
143
|
+
parentGroup.addMember("everyone", "reader");
|
|
144
|
+
group.extend(parentGroup);
|
|
145
|
+
const map = group.createMap();
|
|
146
|
+
map.set("hello", "world", "trusting");
|
|
147
|
+
await map.core.waitForSync();
|
|
148
|
+
expect(SyncMessagesLog.getMessages({
|
|
149
|
+
ParentGroup: parentGroup.core,
|
|
150
|
+
Group: group.core,
|
|
151
|
+
Map: map.core,
|
|
152
|
+
})).toMatchInlineSnapshot(`
|
|
153
|
+
[
|
|
154
|
+
"client -> server1 | CONTENT Group header: true new: After: 0 New: 3",
|
|
155
|
+
"client -> server2 | CONTENT Group header: true new: After: 0 New: 3",
|
|
156
|
+
"client -> server1 | CONTENT ParentGroup header: true new: After: 0 New: 5",
|
|
157
|
+
"client -> server2 | CONTENT ParentGroup header: true new: After: 0 New: 5",
|
|
158
|
+
"client -> server1 | CONTENT Group header: false new: After: 3 New: 2",
|
|
159
|
+
"client -> server2 | CONTENT Group header: false new: After: 3 New: 2",
|
|
160
|
+
"client -> server1 | CONTENT Map header: true new: After: 0 New: 1",
|
|
161
|
+
"client -> server2 | CONTENT Map header: true new: After: 0 New: 1",
|
|
162
|
+
"server1 -> client | KNOWN Group sessions: header/3",
|
|
163
|
+
"server2 -> client | KNOWN Group sessions: header/3",
|
|
164
|
+
"server1 -> client | KNOWN ParentGroup sessions: header/5",
|
|
165
|
+
"server2 -> client | KNOWN ParentGroup sessions: header/5",
|
|
166
|
+
"server1 -> client | KNOWN Group sessions: header/5",
|
|
167
|
+
"server2 -> client | KNOWN Group sessions: header/5",
|
|
168
|
+
"server1 -> client | KNOWN Map sessions: header/1",
|
|
169
|
+
"server2 -> client | KNOWN Map sessions: header/1",
|
|
170
|
+
]
|
|
171
|
+
`);
|
|
172
|
+
const mapOnServer1 = server1.node.getCoValue(map.id);
|
|
173
|
+
const mapOnServer2 = server2.node.getCoValue(map.id);
|
|
174
|
+
expect(mapOnServer1.knownState()).toEqual(map.core.knownState());
|
|
175
|
+
expect(mapOnServer2.knownState()).toEqual(map.core.knownState());
|
|
176
|
+
});
|
|
177
|
+
test("wrong optimistic known state should be corrected", async () => {
|
|
178
|
+
const client = setupTestNode();
|
|
179
|
+
connectServers(client);
|
|
180
|
+
const group = client.node.createGroup();
|
|
181
|
+
group.addMember("everyone", "writer");
|
|
182
|
+
const map = group.createMap({
|
|
183
|
+
fromServer: "initial",
|
|
184
|
+
fromClient: "initial",
|
|
185
|
+
});
|
|
186
|
+
// Load the coValue on the client
|
|
187
|
+
await map.core.waitForSync();
|
|
188
|
+
// Forcefully delete the coValue from server1 (simulating some data loss)
|
|
189
|
+
server1.node.internalDeleteCoValue(map.id);
|
|
190
|
+
map.set("fromClient", "updated", "trusting");
|
|
191
|
+
await waitFor(() => {
|
|
192
|
+
const mapOnServer1 = server1.node.getCoValue(map.id);
|
|
193
|
+
const mapOnServer2 = server2.node.getCoValue(map.id);
|
|
194
|
+
expect(mapOnServer1.knownState()).toEqual(map.core.knownState());
|
|
195
|
+
expect(mapOnServer2.knownState()).toEqual(map.core.knownState());
|
|
196
|
+
});
|
|
197
|
+
expect(SyncMessagesLog.getMessages({
|
|
198
|
+
Group: group.core,
|
|
199
|
+
Map: map.core,
|
|
200
|
+
})).toMatchInlineSnapshot(`
|
|
201
|
+
[
|
|
202
|
+
"client -> server1 | CONTENT Group header: true new: After: 0 New: 5",
|
|
203
|
+
"client -> server2 | CONTENT Group header: true new: After: 0 New: 5",
|
|
204
|
+
"client -> server1 | CONTENT Map header: true new: After: 0 New: 1",
|
|
205
|
+
"client -> server2 | CONTENT Map header: true new: After: 0 New: 1",
|
|
206
|
+
"server1 -> client | KNOWN Group sessions: header/5",
|
|
207
|
+
"server2 -> client | KNOWN Group sessions: header/5",
|
|
208
|
+
"server1 -> client | KNOWN Map sessions: header/1",
|
|
209
|
+
"server2 -> client | KNOWN Map sessions: header/1",
|
|
210
|
+
"client -> server1 | CONTENT Map header: false new: After: 1 New: 1",
|
|
211
|
+
"client -> server2 | CONTENT Map header: false new: After: 1 New: 1",
|
|
212
|
+
"server1 -> client | KNOWN CORRECTION Map sessions: empty",
|
|
213
|
+
"server2 -> client | KNOWN Map sessions: header/2",
|
|
214
|
+
"client -> server1 | CONTENT Map header: true new: After: 0 New: 2",
|
|
215
|
+
"server1 -> client | KNOWN Map sessions: header/2",
|
|
216
|
+
]
|
|
217
|
+
`);
|
|
218
|
+
});
|
|
219
|
+
test("local updates batching", async () => {
|
|
220
|
+
const client = setupTestNode();
|
|
221
|
+
connectServers(client);
|
|
222
|
+
const group = client.node.createGroup();
|
|
223
|
+
const initialMap = group.createMap();
|
|
224
|
+
const child = group.createMap();
|
|
225
|
+
child.set("parent", initialMap.id);
|
|
226
|
+
initialMap.set("child", child.id);
|
|
227
|
+
await initialMap.core.waitForSync();
|
|
228
|
+
expect(SyncMessagesLog.getMessages({
|
|
229
|
+
Group: group.core,
|
|
230
|
+
InitialMap: initialMap.core,
|
|
231
|
+
ChildMap: child.core,
|
|
232
|
+
})).toMatchInlineSnapshot(`
|
|
233
|
+
[
|
|
234
|
+
"client -> server1 | CONTENT Group header: true new: After: 0 New: 3",
|
|
235
|
+
"client -> server2 | CONTENT Group header: true new: After: 0 New: 3",
|
|
236
|
+
"client -> server1 | CONTENT InitialMap header: true new: ",
|
|
237
|
+
"client -> server2 | CONTENT InitialMap header: true new: ",
|
|
238
|
+
"client -> server1 | CONTENT ChildMap header: true new: After: 0 New: 1",
|
|
239
|
+
"client -> server2 | CONTENT ChildMap header: true new: After: 0 New: 1",
|
|
240
|
+
"client -> server1 | CONTENT InitialMap header: false new: After: 0 New: 1",
|
|
241
|
+
"client -> server2 | CONTENT InitialMap header: false new: After: 0 New: 1",
|
|
242
|
+
"server1 -> client | KNOWN Group sessions: header/3",
|
|
243
|
+
"server2 -> client | KNOWN Group sessions: header/3",
|
|
244
|
+
"server1 -> client | KNOWN InitialMap sessions: header/0",
|
|
245
|
+
"server2 -> client | KNOWN InitialMap sessions: header/0",
|
|
246
|
+
"server1 -> client | KNOWN ChildMap sessions: header/1",
|
|
247
|
+
"server2 -> client | KNOWN ChildMap sessions: header/1",
|
|
248
|
+
"server1 -> client | KNOWN InitialMap sessions: header/1",
|
|
249
|
+
"server2 -> client | KNOWN InitialMap sessions: header/1",
|
|
250
|
+
]
|
|
251
|
+
`);
|
|
252
|
+
});
|
|
253
|
+
test("large coValue upload streaming", async () => {
|
|
254
|
+
const client = setupTestNode();
|
|
255
|
+
connectServers(client);
|
|
256
|
+
const group = client.node.createGroup();
|
|
257
|
+
group.addMember("everyone", "writer");
|
|
258
|
+
const largeMap = group.createMap();
|
|
259
|
+
fillCoMapWithLargeData(largeMap);
|
|
260
|
+
await largeMap.core.waitForSync();
|
|
261
|
+
expect(SyncMessagesLog.getMessages({
|
|
262
|
+
Group: group.core,
|
|
263
|
+
Map: largeMap.core,
|
|
264
|
+
})).toMatchInlineSnapshot(`
|
|
265
|
+
[
|
|
266
|
+
"client -> server1 | CONTENT Group header: true new: After: 0 New: 5",
|
|
267
|
+
"client -> server2 | CONTENT Group header: true new: After: 0 New: 5",
|
|
268
|
+
"client -> server1 | CONTENT Map header: true new: After: 0 New: 73 expectContentUntil: header/200",
|
|
269
|
+
"client -> server2 | CONTENT Map header: true new: After: 0 New: 73 expectContentUntil: header/200",
|
|
270
|
+
"client -> server1 | CONTENT Map header: false new: After: 73 New: 73",
|
|
271
|
+
"client -> server2 | CONTENT Map header: false new: After: 73 New: 73",
|
|
272
|
+
"client -> server1 | CONTENT Map header: false new: After: 146 New: 54",
|
|
273
|
+
"client -> server2 | CONTENT Map header: false new: After: 146 New: 54",
|
|
274
|
+
"server1 -> client | KNOWN Group sessions: header/5",
|
|
275
|
+
"server2 -> client | KNOWN Group sessions: header/5",
|
|
276
|
+
"server1 -> client | KNOWN Map sessions: header/73",
|
|
277
|
+
"server2 -> client | KNOWN Map sessions: header/73",
|
|
278
|
+
"server1 -> client | KNOWN Map sessions: header/146",
|
|
279
|
+
"server2 -> client | KNOWN Map sessions: header/146",
|
|
280
|
+
"server1 -> client | KNOWN Map sessions: header/200",
|
|
281
|
+
"server2 -> client | KNOWN Map sessions: header/200",
|
|
282
|
+
]
|
|
283
|
+
`);
|
|
284
|
+
});
|
|
285
|
+
test("uploading a large update", async () => {
|
|
286
|
+
const client = setupTestNode();
|
|
287
|
+
connectServers(client);
|
|
288
|
+
const group = client.node.createGroup();
|
|
289
|
+
group.addMember("everyone", "writer");
|
|
290
|
+
const largeMap = group.createMap();
|
|
291
|
+
await largeMap.core.waitForSync();
|
|
292
|
+
fillCoMapWithLargeData(largeMap);
|
|
293
|
+
await largeMap.core.waitForSync();
|
|
294
|
+
expect(SyncMessagesLog.getMessages({
|
|
295
|
+
Group: group.core,
|
|
296
|
+
Map: largeMap.core,
|
|
297
|
+
})).toMatchInlineSnapshot(`
|
|
298
|
+
[
|
|
299
|
+
"client -> server1 | CONTENT Group header: true new: After: 0 New: 5",
|
|
300
|
+
"client -> server2 | CONTENT Group header: true new: After: 0 New: 5",
|
|
301
|
+
"client -> server1 | CONTENT Map header: true new: ",
|
|
302
|
+
"client -> server2 | CONTENT Map header: true new: ",
|
|
303
|
+
"client -> server1 | CONTENT Map header: false new: After: 0 New: 73 expectContentUntil: header/200",
|
|
304
|
+
"client -> server2 | CONTENT Map header: false new: After: 0 New: 73 expectContentUntil: header/200",
|
|
305
|
+
"client -> server1 | CONTENT Map header: false new: After: 73 New: 73",
|
|
306
|
+
"client -> server2 | CONTENT Map header: false new: After: 73 New: 73",
|
|
307
|
+
"client -> server1 | CONTENT Map header: false new: After: 146 New: 54",
|
|
308
|
+
"client -> server2 | CONTENT Map header: false new: After: 146 New: 54",
|
|
309
|
+
"server1 -> client | KNOWN Group sessions: header/5",
|
|
310
|
+
"server2 -> client | KNOWN Group sessions: header/5",
|
|
311
|
+
"server1 -> client | KNOWN Map sessions: header/0",
|
|
312
|
+
"server2 -> client | KNOWN Map sessions: header/0",
|
|
313
|
+
"server1 -> client | KNOWN Map sessions: header/73",
|
|
314
|
+
"server2 -> client | KNOWN Map sessions: header/73",
|
|
315
|
+
"server1 -> client | KNOWN Map sessions: header/146",
|
|
316
|
+
"server2 -> client | KNOWN Map sessions: header/146",
|
|
317
|
+
"server1 -> client | KNOWN Map sessions: header/200",
|
|
318
|
+
"server2 -> client | KNOWN Map sessions: header/200",
|
|
319
|
+
]
|
|
320
|
+
`);
|
|
321
|
+
});
|
|
322
|
+
test("uploading a large update between two clients", async () => {
|
|
323
|
+
const client = setupTestNode();
|
|
324
|
+
connectServers(client);
|
|
325
|
+
const client2 = setupTestNode();
|
|
326
|
+
connectServers(client2);
|
|
327
|
+
const group = client.node.createGroup();
|
|
328
|
+
group.addMember("everyone", "writer");
|
|
329
|
+
const largeMap = group.createMap();
|
|
330
|
+
const largeMapOnClient2 = await loadCoValueOrFail(client2.node, largeMap.id);
|
|
331
|
+
fillCoMapWithLargeData(largeMap);
|
|
332
|
+
await waitFor(() => {
|
|
333
|
+
expect(largeMapOnClient2.core.knownState()).toEqual(largeMap.core.knownState());
|
|
334
|
+
});
|
|
335
|
+
expect(SyncMessagesLog.getMessages({
|
|
336
|
+
Group: group.core,
|
|
337
|
+
Map: largeMap.core,
|
|
338
|
+
})).toMatchInlineSnapshot(`
|
|
339
|
+
[
|
|
340
|
+
"client -> server1 | LOAD Map sessions: empty",
|
|
341
|
+
"client -> server2 | LOAD Map sessions: empty",
|
|
342
|
+
"client -> server1 | CONTENT Group header: true new: After: 0 New: 5",
|
|
343
|
+
"client -> server2 | CONTENT Group header: true new: After: 0 New: 5",
|
|
344
|
+
"client -> server1 | CONTENT Map header: true new: ",
|
|
345
|
+
"client -> server2 | CONTENT Map header: true new: ",
|
|
346
|
+
"server1 -> client | KNOWN Map sessions: empty",
|
|
347
|
+
"server2 -> client | KNOWN Map sessions: empty",
|
|
348
|
+
"server1 -> client | KNOWN Group sessions: header/5",
|
|
349
|
+
"server2 -> client | KNOWN Group sessions: header/5",
|
|
350
|
+
"server1 -> client | KNOWN Map sessions: header/0",
|
|
351
|
+
"server1 -> client | CONTENT Group header: true new: After: 0 New: 5",
|
|
352
|
+
"server1 -> client | CONTENT Map header: true new: ",
|
|
353
|
+
"server2 -> client | KNOWN Map sessions: header/0",
|
|
354
|
+
"server2 -> client | CONTENT Group header: true new: After: 0 New: 5",
|
|
355
|
+
"server2 -> client | CONTENT Map header: true new: ",
|
|
356
|
+
"client -> server1 | KNOWN Group sessions: header/5",
|
|
357
|
+
"client -> server2 | LOAD Group sessions: header/5",
|
|
358
|
+
"client -> server1 | KNOWN Map sessions: header/0",
|
|
359
|
+
"client -> server2 | CONTENT Map header: true new: ",
|
|
360
|
+
"client -> server1 | CONTENT Map header: false new: After: 0 New: 73 expectContentUntil: header/200",
|
|
361
|
+
"client -> server2 | CONTENT Map header: false new: After: 0 New: 73 expectContentUntil: header/200",
|
|
362
|
+
"client -> server1 | CONTENT Map header: false new: After: 73 New: 73",
|
|
363
|
+
"client -> server2 | CONTENT Map header: false new: After: 73 New: 73",
|
|
364
|
+
"client -> server1 | CONTENT Map header: false new: After: 146 New: 54",
|
|
365
|
+
"client -> server2 | CONTENT Map header: false new: After: 146 New: 54",
|
|
366
|
+
"client -> server2 | KNOWN Group sessions: header/5",
|
|
367
|
+
"client -> server2 | CONTENT Group header: false new: After: 0 New: 5",
|
|
368
|
+
"client -> server2 | KNOWN Map sessions: header/0",
|
|
369
|
+
"server2 -> client | KNOWN Map sessions: header/0",
|
|
370
|
+
"server1 -> client | KNOWN Map sessions: header/73",
|
|
371
|
+
"server1 -> client | CONTENT Map header: false new: After: 0 New: 73",
|
|
372
|
+
"server2 -> client | KNOWN Map sessions: header/73",
|
|
373
|
+
"server2 -> client | CONTENT Map header: false new: After: 0 New: 73",
|
|
374
|
+
"server1 -> client | KNOWN Map sessions: header/146",
|
|
375
|
+
"server1 -> client | CONTENT Map header: false new: After: 73 New: 73",
|
|
376
|
+
"server2 -> client | KNOWN Map sessions: header/146",
|
|
377
|
+
"server2 -> client | CONTENT Map header: false new: After: 73 New: 73",
|
|
378
|
+
"server1 -> client | KNOWN Map sessions: header/200",
|
|
379
|
+
"server1 -> client | CONTENT Map header: false new: After: 146 New: 54",
|
|
380
|
+
"server2 -> client | KNOWN Map sessions: header/200",
|
|
381
|
+
"server2 -> client | CONTENT Map header: false new: After: 146 New: 54",
|
|
382
|
+
"server2 -> client | KNOWN Group sessions: header/5",
|
|
383
|
+
"client -> server1 | KNOWN Map sessions: header/73",
|
|
384
|
+
"client -> server2 | CONTENT Map header: false new: After: 0 New: 73",
|
|
385
|
+
"client -> server2 | KNOWN Map sessions: header/73",
|
|
386
|
+
"client -> server1 | KNOWN Map sessions: header/146",
|
|
387
|
+
"client -> server2 | CONTENT Map header: false new: After: 73 New: 73",
|
|
388
|
+
"client -> server2 | KNOWN Map sessions: header/146",
|
|
389
|
+
"client -> server1 | KNOWN Map sessions: header/200",
|
|
390
|
+
"client -> server2 | CONTENT Map header: false new: After: 146 New: 54",
|
|
391
|
+
"client -> server2 | KNOWN Map sessions: header/200",
|
|
392
|
+
"server2 -> client | KNOWN Map sessions: header/200",
|
|
393
|
+
"server2 -> client | KNOWN Map sessions: header/200",
|
|
394
|
+
"server2 -> client | KNOWN Map sessions: header/200",
|
|
395
|
+
]
|
|
396
|
+
`);
|
|
397
|
+
});
|
|
398
|
+
});
|
|
399
|
+
//# sourceMappingURL=sync.multipleServers.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sync.multipleServers.test.js","sourceRoot":"","sources":["../../src/tests/sync.multipleServers.test.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
},
|
|
34
34
|
"type": "module",
|
|
35
35
|
"license": "MIT",
|
|
36
|
-
"version": "0.19.
|
|
36
|
+
"version": "0.19.4",
|
|
37
37
|
"devDependencies": {
|
|
38
38
|
"@opentelemetry/sdk-metrics": "^2.0.0",
|
|
39
39
|
"libsql": "^0.5.13",
|
|
@@ -46,8 +46,8 @@
|
|
|
46
46
|
"@opentelemetry/api": "^1.9.0",
|
|
47
47
|
"@scure/base": "1.2.1",
|
|
48
48
|
"unicode-segmenter": "^0.12.0",
|
|
49
|
-
"cojson-core-wasm": "0.19.
|
|
50
|
-
"cojson-core-napi": "0.19.
|
|
49
|
+
"cojson-core-wasm": "0.19.4",
|
|
50
|
+
"cojson-core-napi": "0.19.4"
|
|
51
51
|
},
|
|
52
52
|
"gitHead": "33c27053293b4801b968c61d5c4c989f93a67d13",
|
|
53
53
|
"scripts": {
|
package/src/coValues/coList.ts
CHANGED
|
@@ -6,7 +6,6 @@ import { accountOrAgentIDfromSessionID } from "../typeUtils/accountOrAgentIDfrom
|
|
|
6
6
|
import { isCoValue } from "../typeUtils/isCoValue.js";
|
|
7
7
|
import { RawAccountID } from "./account.js";
|
|
8
8
|
import { RawGroup } from "./group.js";
|
|
9
|
-
import { Transaction } from "../coValueCore/verifiedState.js";
|
|
10
9
|
|
|
11
10
|
export type OpID = TransactionID & { changeIdx: number };
|
|
12
11
|
|
|
@@ -73,6 +72,14 @@ export class RawCoList<
|
|
|
73
72
|
};
|
|
74
73
|
};
|
|
75
74
|
} = {};
|
|
75
|
+
|
|
76
|
+
/** @internal */
|
|
77
|
+
atTimeFilter?: number = undefined;
|
|
78
|
+
|
|
79
|
+
/** @category 6. Meta */
|
|
80
|
+
readonly _item!: Item;
|
|
81
|
+
|
|
82
|
+
/** @internal */
|
|
76
83
|
_cachedEntries?: {
|
|
77
84
|
value: Item;
|
|
78
85
|
madeAt: number;
|
|
@@ -94,14 +101,19 @@ export class RawCoList<
|
|
|
94
101
|
this.totalValidTransactions = 0;
|
|
95
102
|
}
|
|
96
103
|
|
|
97
|
-
/** @category 6. Meta */
|
|
98
|
-
readonly _item!: Item;
|
|
99
|
-
|
|
100
104
|
/** @internal */
|
|
101
|
-
constructor(core: AvailableCoValueCore) {
|
|
105
|
+
constructor(core: AvailableCoValueCore, atTimeFilter?: number) {
|
|
102
106
|
this.id = core.id as CoID<this>;
|
|
103
107
|
this.core = core;
|
|
104
|
-
|
|
108
|
+
|
|
109
|
+
this.insertions = {};
|
|
110
|
+
this.deletionsByInsertion = {};
|
|
111
|
+
this.afterStart = [];
|
|
112
|
+
this.beforeEnd = [];
|
|
113
|
+
this.knownTransactions = { [core.id]: 0 };
|
|
114
|
+
this.atTimeFilter = atTimeFilter;
|
|
115
|
+
|
|
116
|
+
this._processNewTransactions();
|
|
105
117
|
}
|
|
106
118
|
|
|
107
119
|
private getInsertionsEntry(opID: OpID) {
|
|
@@ -188,6 +200,13 @@ export class RawCoList<
|
|
|
188
200
|
}
|
|
189
201
|
|
|
190
202
|
processNewTransactions() {
|
|
203
|
+
if (this.isTimeTravelEntity()) {
|
|
204
|
+
throw new Error("Cannot process transactions on a time travel entity");
|
|
205
|
+
}
|
|
206
|
+
this._processNewTransactions();
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
private _processNewTransactions() {
|
|
191
210
|
const transactions = this.core.getValidSortedTransactions({
|
|
192
211
|
ignorePrivateTransactions: false,
|
|
193
212
|
knownTransactions: this.knownTransactions,
|
|
@@ -202,6 +221,9 @@ export class RawCoList<
|
|
|
202
221
|
this._cachedEntries = undefined;
|
|
203
222
|
|
|
204
223
|
for (const { txID, changes, madeAt } of transactions) {
|
|
224
|
+
if (this.isFilteredOut(madeAt)) {
|
|
225
|
+
continue;
|
|
226
|
+
}
|
|
205
227
|
lastValidTransaction = Math.max(lastValidTransaction ?? 0, madeAt);
|
|
206
228
|
oldestValidTransaction = Math.min(
|
|
207
229
|
oldestValidTransaction ?? Infinity,
|
|
@@ -290,6 +312,17 @@ export class RawCoList<
|
|
|
290
312
|
this.processNewTransactions();
|
|
291
313
|
}
|
|
292
314
|
|
|
315
|
+
isTimeTravelEntity() {
|
|
316
|
+
return Boolean(this.atTimeFilter);
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
private isFilteredOut(time: number): boolean {
|
|
320
|
+
if (this.atTimeFilter === undefined) {
|
|
321
|
+
return false;
|
|
322
|
+
}
|
|
323
|
+
return time > this.atTimeFilter;
|
|
324
|
+
}
|
|
325
|
+
|
|
293
326
|
/** @category 6. Meta */
|
|
294
327
|
get headerMeta(): Meta {
|
|
295
328
|
return this.core.verified.header.meta as Meta;
|
|
@@ -305,8 +338,8 @@ export class RawCoList<
|
|
|
305
338
|
*
|
|
306
339
|
* @category 4. Time travel
|
|
307
340
|
*/
|
|
308
|
-
atTime(
|
|
309
|
-
|
|
341
|
+
atTime(time: number): this {
|
|
342
|
+
return new RawCoList(this.core, time) as this;
|
|
310
343
|
}
|
|
311
344
|
|
|
312
345
|
/**
|
|
@@ -55,8 +55,8 @@ export class RawCoPlainText<
|
|
|
55
55
|
PlaintextIdxMapping
|
|
56
56
|
>;
|
|
57
57
|
|
|
58
|
-
constructor(core: AvailableCoValueCore) {
|
|
59
|
-
super(core);
|
|
58
|
+
constructor(core: AvailableCoValueCore, atTimeFilter?: number) {
|
|
59
|
+
super(core, atTimeFilter);
|
|
60
60
|
this._cachedMapping = new WeakMap();
|
|
61
61
|
}
|
|
62
62
|
|
|
@@ -97,6 +97,10 @@ export class RawCoPlainText<
|
|
|
97
97
|
.join("");
|
|
98
98
|
}
|
|
99
99
|
|
|
100
|
+
atTime(time: number): this {
|
|
101
|
+
return new RawCoPlainText(this.core, time) as this;
|
|
102
|
+
}
|
|
103
|
+
|
|
100
104
|
/**
|
|
101
105
|
* Inserts `text` before the character at index `idx`.
|
|
102
106
|
* If idx is 0, inserts at the start of the text.
|
|
@@ -8,6 +8,7 @@ import { logger } from "../../logger.js";
|
|
|
8
8
|
import type { NewContentMessage } from "../../sync.js";
|
|
9
9
|
import type {
|
|
10
10
|
DBClientInterfaceSync,
|
|
11
|
+
DBTransactionInterfaceSync,
|
|
11
12
|
SessionRow,
|
|
12
13
|
SignatureAfterRow,
|
|
13
14
|
StoredCoValueRow,
|
|
@@ -31,7 +32,9 @@ export function getErrorMessage(error: unknown) {
|
|
|
31
32
|
return error instanceof Error ? error.message : "Unknown error";
|
|
32
33
|
}
|
|
33
34
|
|
|
34
|
-
export class SQLiteClient
|
|
35
|
+
export class SQLiteClient
|
|
36
|
+
implements DBClientInterfaceSync, DBTransactionInterfaceSync
|
|
37
|
+
{
|
|
35
38
|
private readonly db: SQLiteDatabaseDriver;
|
|
36
39
|
|
|
37
40
|
constructor(db: SQLiteDatabaseDriver) {
|
|
@@ -187,8 +190,8 @@ export class SQLiteClient implements DBClientInterfaceSync {
|
|
|
187
190
|
);
|
|
188
191
|
}
|
|
189
192
|
|
|
190
|
-
transaction(operationsCallback: () => unknown) {
|
|
191
|
-
this.db.transaction(operationsCallback);
|
|
193
|
+
transaction(operationsCallback: (tx: DBTransactionInterfaceSync) => unknown) {
|
|
194
|
+
this.db.transaction(() => operationsCallback(this));
|
|
192
195
|
return undefined;
|
|
193
196
|
}
|
|
194
197
|
}
|
|
@@ -8,6 +8,7 @@ import { logger } from "../../logger.js";
|
|
|
8
8
|
import type { NewContentMessage } from "../../sync.js";
|
|
9
9
|
import type {
|
|
10
10
|
DBClientInterfaceAsync,
|
|
11
|
+
DBTransactionInterfaceAsync,
|
|
11
12
|
SessionRow,
|
|
12
13
|
SignatureAfterRow,
|
|
13
14
|
StoredCoValueRow,
|
|
@@ -31,7 +32,9 @@ export function getErrorMessage(error: unknown) {
|
|
|
31
32
|
return error instanceof Error ? error.message : "Unknown error";
|
|
32
33
|
}
|
|
33
34
|
|
|
34
|
-
export class SQLiteClientAsync
|
|
35
|
+
export class SQLiteClientAsync
|
|
36
|
+
implements DBClientInterfaceAsync, DBTransactionInterfaceAsync
|
|
37
|
+
{
|
|
35
38
|
private readonly db: SQLiteDatabaseDriverAsync;
|
|
36
39
|
|
|
37
40
|
constructor(db: SQLiteDatabaseDriverAsync) {
|
|
@@ -194,7 +197,9 @@ export class SQLiteClientAsync implements DBClientInterfaceAsync {
|
|
|
194
197
|
);
|
|
195
198
|
}
|
|
196
199
|
|
|
197
|
-
async transaction(
|
|
198
|
-
|
|
200
|
+
async transaction(
|
|
201
|
+
operationsCallback: (tx: DBTransactionInterfaceAsync) => Promise<unknown>,
|
|
202
|
+
) {
|
|
203
|
+
return this.db.transaction(() => operationsCallback(this));
|
|
199
204
|
}
|
|
200
205
|
}
|