cojson 0.19.14 → 0.19.16
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 +1 -1
- package/dist/PeerState.d.ts.map +1 -1
- package/dist/PeerState.js.map +1 -1
- package/dist/coValueCore/coValueCore.d.ts +8 -1
- package/dist/coValueCore/coValueCore.d.ts.map +1 -1
- package/dist/coValueCore/coValueCore.js +13 -0
- package/dist/coValueCore/coValueCore.js.map +1 -1
- package/dist/coValues/group.d.ts.map +1 -1
- package/dist/coValues/group.js +16 -4
- package/dist/coValues/group.js.map +1 -1
- package/dist/localNode.d.ts +0 -1
- package/dist/localNode.d.ts.map +1 -1
- package/dist/localNode.js +4 -4
- package/dist/localNode.js.map +1 -1
- package/dist/queue/LocalTransactionsSyncQueue.d.ts +0 -1
- package/dist/queue/LocalTransactionsSyncQueue.d.ts.map +1 -1
- package/dist/queue/LocalTransactionsSyncQueue.js +0 -2
- package/dist/queue/LocalTransactionsSyncQueue.js.map +1 -1
- package/dist/storage/sqlite/client.d.ts.map +1 -1
- package/dist/storage/sqlite/client.js.map +1 -1
- package/dist/storage/sqliteAsync/client.d.ts.map +1 -1
- package/dist/storage/sqliteAsync/client.js.map +1 -1
- package/dist/storage/storageAsync.d.ts +1 -1
- package/dist/storage/storageAsync.js +8 -8
- package/dist/storage/storageSync.d.ts +1 -1
- package/dist/storage/storageSync.js +8 -8
- package/dist/sync.d.ts.map +1 -1
- package/dist/sync.js +13 -2
- package/dist/sync.js.map +1 -1
- package/dist/tests/SyncStateManager.test.js +24 -1
- package/dist/tests/SyncStateManager.test.js.map +1 -1
- package/package.json +4 -4
- package/src/PeerState.ts +1 -1
- package/src/coValueCore/coValueCore.ts +15 -1
- package/src/coValues/group.ts +16 -4
- package/src/localNode.ts +4 -5
- package/src/queue/LocalTransactionsSyncQueue.ts +0 -2
- package/src/storage/sqlite/client.ts +0 -1
- package/src/storage/sqliteAsync/client.ts +0 -1
- package/src/storage/storageAsync.ts +8 -8
- package/src/storage/storageSync.ts +8 -8
- package/src/sync.ts +15 -2
- package/src/tests/SyncStateManager.test.ts +41 -0
|
@@ -315,6 +315,14 @@ export class CoValueCore {
|
|
|
315
315
|
return this.getLoadingStateForPeer(peerId) === "errored";
|
|
316
316
|
}
|
|
317
317
|
|
|
318
|
+
getErroredInPeerError(peerId: PeerID) {
|
|
319
|
+
const loadingState = this.loadingStatuses.get(peerId);
|
|
320
|
+
if (loadingState?.type === "errored") {
|
|
321
|
+
return loadingState.error;
|
|
322
|
+
}
|
|
323
|
+
return undefined;
|
|
324
|
+
}
|
|
325
|
+
|
|
318
326
|
waitFor(opts: {
|
|
319
327
|
predicate: (value: CoValueCore) => boolean;
|
|
320
328
|
onSuccess: (value: CoValueCore) => void;
|
|
@@ -575,6 +583,9 @@ export class CoValueCore {
|
|
|
575
583
|
}
|
|
576
584
|
}
|
|
577
585
|
|
|
586
|
+
/**
|
|
587
|
+
* Apply new transactions that were not generated by the current node to the CoValue
|
|
588
|
+
*/
|
|
578
589
|
tryAddTransactions(
|
|
579
590
|
sessionID: SessionID,
|
|
580
591
|
newTransactions: Transaction[],
|
|
@@ -722,6 +733,9 @@ export class CoValueCore {
|
|
|
722
733
|
};
|
|
723
734
|
}
|
|
724
735
|
|
|
736
|
+
/**
|
|
737
|
+
* Creates a new transaction with local changes and syncs it to all peers
|
|
738
|
+
*/
|
|
725
739
|
makeTransaction(
|
|
726
740
|
changes: JsonValue[],
|
|
727
741
|
privacy: "private" | "trusting",
|
|
@@ -1507,7 +1521,7 @@ export class CoValueCore {
|
|
|
1507
1521
|
}
|
|
1508
1522
|
}
|
|
1509
1523
|
|
|
1510
|
-
internalLoadFromPeer(peer: PeerState) {
|
|
1524
|
+
private internalLoadFromPeer(peer: PeerState) {
|
|
1511
1525
|
if (peer.closed && !peer.persistent) {
|
|
1512
1526
|
this.markNotFoundInPeer(peer.id);
|
|
1513
1527
|
return;
|
package/src/coValues/group.ts
CHANGED
|
@@ -1249,7 +1249,10 @@ export class RawGroup<
|
|
|
1249
1249
|
group: this.id,
|
|
1250
1250
|
},
|
|
1251
1251
|
meta: meta || null,
|
|
1252
|
-
...uniqueness
|
|
1252
|
+
...(uniqueness.createdAt !== undefined
|
|
1253
|
+
? { createdAt: uniqueness.createdAt }
|
|
1254
|
+
: {}),
|
|
1255
|
+
uniqueness: uniqueness.uniqueness,
|
|
1253
1256
|
})
|
|
1254
1257
|
.getCurrentContent() as M;
|
|
1255
1258
|
|
|
@@ -1283,7 +1286,10 @@ export class RawGroup<
|
|
|
1283
1286
|
group: this.id,
|
|
1284
1287
|
},
|
|
1285
1288
|
meta: meta || null,
|
|
1286
|
-
...uniqueness
|
|
1289
|
+
...(uniqueness.createdAt !== undefined
|
|
1290
|
+
? { createdAt: uniqueness.createdAt }
|
|
1291
|
+
: {}),
|
|
1292
|
+
uniqueness: uniqueness.uniqueness,
|
|
1287
1293
|
})
|
|
1288
1294
|
.getCurrentContent() as L;
|
|
1289
1295
|
|
|
@@ -1340,7 +1346,10 @@ export class RawGroup<
|
|
|
1340
1346
|
group: this.id,
|
|
1341
1347
|
},
|
|
1342
1348
|
meta: meta || null,
|
|
1343
|
-
...uniqueness
|
|
1349
|
+
...(uniqueness.createdAt !== undefined
|
|
1350
|
+
? { createdAt: uniqueness.createdAt }
|
|
1351
|
+
: {}),
|
|
1352
|
+
uniqueness: uniqueness.uniqueness,
|
|
1344
1353
|
})
|
|
1345
1354
|
.getCurrentContent() as C;
|
|
1346
1355
|
|
|
@@ -1365,7 +1374,10 @@ export class RawGroup<
|
|
|
1365
1374
|
group: this.id,
|
|
1366
1375
|
},
|
|
1367
1376
|
meta: meta,
|
|
1368
|
-
...uniqueness
|
|
1377
|
+
...(uniqueness.createdAt !== undefined
|
|
1378
|
+
? { createdAt: uniqueness.createdAt }
|
|
1379
|
+
: {}),
|
|
1380
|
+
uniqueness: uniqueness.uniqueness,
|
|
1369
1381
|
})
|
|
1370
1382
|
.getCurrentContent() as C;
|
|
1371
1383
|
}
|
package/src/localNode.ts
CHANGED
|
@@ -395,10 +395,6 @@ export class LocalNode {
|
|
|
395
395
|
return coValue;
|
|
396
396
|
}
|
|
397
397
|
|
|
398
|
-
hasLoadingSources(id: RawCoID) {
|
|
399
|
-
return this.storage || this.syncManager.getServerPeers(id).length > 0;
|
|
400
|
-
}
|
|
401
|
-
|
|
402
398
|
/** @internal */
|
|
403
399
|
async loadCoValueCore(
|
|
404
400
|
id: RawCoID,
|
|
@@ -742,7 +738,10 @@ export class LocalNode {
|
|
|
742
738
|
type: "comap",
|
|
743
739
|
ruleset: { type: "group", initialAdmin: account.id },
|
|
744
740
|
meta: null,
|
|
745
|
-
...uniqueness
|
|
741
|
+
...(uniqueness.createdAt !== undefined
|
|
742
|
+
? { createdAt: uniqueness.createdAt }
|
|
743
|
+
: {}),
|
|
744
|
+
uniqueness: uniqueness.uniqueness,
|
|
746
745
|
});
|
|
747
746
|
|
|
748
747
|
const group = expectGroup(groupCoValue.getCurrentContent());
|
|
@@ -15,7 +15,6 @@ import { NewContentMessage } from "../sync.js";
|
|
|
15
15
|
*/
|
|
16
16
|
export class LocalTransactionsSyncQueue {
|
|
17
17
|
private batch: NewContentMessage[] = [];
|
|
18
|
-
private firstChunks = new Map<RawCoID, NewContentMessage>();
|
|
19
18
|
private lastUpdatedValue: VerifiedState | undefined;
|
|
20
19
|
private lastUpdatedValueKnownState: CoValueKnownState | undefined;
|
|
21
20
|
|
|
@@ -78,7 +77,6 @@ export class LocalTransactionsSyncQueue {
|
|
|
78
77
|
|
|
79
78
|
this.lastUpdatedValue = undefined;
|
|
80
79
|
this.lastUpdatedValueKnownState = undefined;
|
|
81
|
-
this.firstChunks = new Map();
|
|
82
80
|
this.batch = [];
|
|
83
81
|
this.nextBatchScheduled = false;
|
|
84
82
|
|
|
@@ -5,7 +5,6 @@ import type {
|
|
|
5
5
|
import type { Signature } from "../../crypto/crypto.js";
|
|
6
6
|
import type { RawCoID, SessionID } from "../../exports.js";
|
|
7
7
|
import { logger } from "../../logger.js";
|
|
8
|
-
import type { NewContentMessage } from "../../sync.js";
|
|
9
8
|
import type {
|
|
10
9
|
DBClientInterfaceSync,
|
|
11
10
|
DBTransactionInterfaceSync,
|
|
@@ -5,7 +5,6 @@ import type {
|
|
|
5
5
|
import type { Signature } from "../../crypto/crypto.js";
|
|
6
6
|
import type { RawCoID, SessionID } from "../../exports.js";
|
|
7
7
|
import { logger } from "../../logger.js";
|
|
8
|
-
import type { NewContentMessage } from "../../sync.js";
|
|
9
8
|
import type {
|
|
10
9
|
DBClientInterfaceAsync,
|
|
11
10
|
DBTransactionInterfaceAsync,
|
|
@@ -40,10 +40,10 @@ export class StorageApiAsync implements StorageAPI {
|
|
|
40
40
|
this.dbClient = dbClient;
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
-
|
|
43
|
+
knownStates = new StorageKnownState();
|
|
44
44
|
|
|
45
45
|
getKnownState(id: string): CoValueKnownState {
|
|
46
|
-
return this.
|
|
46
|
+
return this.knownStates.getKnownState(id);
|
|
47
47
|
}
|
|
48
48
|
|
|
49
49
|
async load(
|
|
@@ -91,7 +91,7 @@ export class StorageApiAsync implements StorageAPI {
|
|
|
91
91
|
}),
|
|
92
92
|
);
|
|
93
93
|
|
|
94
|
-
const knownState = this.
|
|
94
|
+
const knownState = this.knownStates.getKnownState(coValueRow.id);
|
|
95
95
|
knownState.header = true;
|
|
96
96
|
|
|
97
97
|
for (const sessionRow of allCoValueSessions) {
|
|
@@ -169,7 +169,7 @@ export class StorageApiAsync implements StorageAPI {
|
|
|
169
169
|
);
|
|
170
170
|
}
|
|
171
171
|
|
|
172
|
-
this.
|
|
172
|
+
this.knownStates.handleUpdate(coValueRow.id, knownState);
|
|
173
173
|
done?.(true);
|
|
174
174
|
}
|
|
175
175
|
|
|
@@ -270,12 +270,12 @@ export class StorageApiAsync implements StorageAPI {
|
|
|
270
270
|
|
|
271
271
|
if (!storedCoValueRowID) {
|
|
272
272
|
const knownState = emptyKnownState(id as RawCoID);
|
|
273
|
-
this.
|
|
273
|
+
this.knownStates.setKnownState(id, knownState);
|
|
274
274
|
|
|
275
275
|
return this.handleCorrection(knownState, correctionCallback);
|
|
276
276
|
}
|
|
277
277
|
|
|
278
|
-
const knownState = this.
|
|
278
|
+
const knownState = this.knownStates.getKnownState(id);
|
|
279
279
|
knownState.header = true;
|
|
280
280
|
|
|
281
281
|
let invalidAssumptions = false;
|
|
@@ -313,7 +313,7 @@ export class StorageApiAsync implements StorageAPI {
|
|
|
313
313
|
});
|
|
314
314
|
}
|
|
315
315
|
|
|
316
|
-
this.
|
|
316
|
+
this.knownStates.handleUpdate(id, knownState);
|
|
317
317
|
|
|
318
318
|
if (invalidAssumptions) {
|
|
319
319
|
return this.handleCorrection(knownState, correctionCallback);
|
|
@@ -389,7 +389,7 @@ export class StorageApiAsync implements StorageAPI {
|
|
|
389
389
|
}
|
|
390
390
|
|
|
391
391
|
waitForSync(id: string, coValue: CoValueCore) {
|
|
392
|
-
return this.
|
|
392
|
+
return this.knownStates.waitForSync(id, coValue);
|
|
393
393
|
}
|
|
394
394
|
|
|
395
395
|
close() {
|
|
@@ -48,10 +48,10 @@ export class StorageApiSync implements StorageAPI {
|
|
|
48
48
|
this.streamingCounter.add(0);
|
|
49
49
|
}
|
|
50
50
|
|
|
51
|
-
|
|
51
|
+
knownStates = new StorageKnownState();
|
|
52
52
|
|
|
53
53
|
getKnownState(id: string): CoValueKnownState {
|
|
54
|
-
return this.
|
|
54
|
+
return this.knownStates.getKnownState(id);
|
|
55
55
|
}
|
|
56
56
|
|
|
57
57
|
async load(
|
|
@@ -93,7 +93,7 @@ export class StorageApiSync implements StorageAPI {
|
|
|
93
93
|
}
|
|
94
94
|
}
|
|
95
95
|
|
|
96
|
-
const knownState = this.
|
|
96
|
+
const knownState = this.knownStates.getKnownState(coValueRow.id);
|
|
97
97
|
knownState.header = true;
|
|
98
98
|
|
|
99
99
|
for (const sessionRow of allCoValueSessions) {
|
|
@@ -174,7 +174,7 @@ export class StorageApiSync implements StorageAPI {
|
|
|
174
174
|
this.streamingCounter.add(-1);
|
|
175
175
|
}
|
|
176
176
|
|
|
177
|
-
this.
|
|
177
|
+
this.knownStates.handleUpdate(coValueRow.id, knownState);
|
|
178
178
|
done?.(true);
|
|
179
179
|
}
|
|
180
180
|
|
|
@@ -247,12 +247,12 @@ export class StorageApiSync implements StorageAPI {
|
|
|
247
247
|
|
|
248
248
|
if (!storedCoValueRowID) {
|
|
249
249
|
const knownState = emptyKnownState(id as RawCoID);
|
|
250
|
-
this.
|
|
250
|
+
this.knownStates.setKnownState(id, knownState);
|
|
251
251
|
|
|
252
252
|
return this.handleCorrection(knownState, correctionCallback);
|
|
253
253
|
}
|
|
254
254
|
|
|
255
|
-
const knownState = this.
|
|
255
|
+
const knownState = this.knownStates.getKnownState(id);
|
|
256
256
|
knownState.header = true;
|
|
257
257
|
|
|
258
258
|
let invalidAssumptions = false;
|
|
@@ -287,7 +287,7 @@ export class StorageApiSync implements StorageAPI {
|
|
|
287
287
|
});
|
|
288
288
|
}
|
|
289
289
|
|
|
290
|
-
this.
|
|
290
|
+
this.knownStates.handleUpdate(id, knownState);
|
|
291
291
|
|
|
292
292
|
if (invalidAssumptions) {
|
|
293
293
|
return this.handleCorrection(knownState, correctionCallback);
|
|
@@ -362,7 +362,7 @@ export class StorageApiSync implements StorageAPI {
|
|
|
362
362
|
}
|
|
363
363
|
|
|
364
364
|
waitForSync(id: string, coValue: CoValueCore) {
|
|
365
|
-
return this.
|
|
365
|
+
return this.knownStates.waitForSync(id, coValue);
|
|
366
366
|
}
|
|
367
367
|
|
|
368
368
|
close() {
|
package/src/sync.ts
CHANGED
|
@@ -358,7 +358,7 @@ export class SyncManager {
|
|
|
358
358
|
});
|
|
359
359
|
|
|
360
360
|
if (!skipReconciliation && peerState.role === "server") {
|
|
361
|
-
|
|
361
|
+
this.startPeerReconciliation(peerState);
|
|
362
362
|
}
|
|
363
363
|
|
|
364
364
|
peerState.incoming.onMessage((msg) => {
|
|
@@ -870,7 +870,20 @@ export class SyncManager {
|
|
|
870
870
|
);
|
|
871
871
|
|
|
872
872
|
const timeoutId = setTimeout(() => {
|
|
873
|
-
|
|
873
|
+
const coValue = this.local.getCoValue(id);
|
|
874
|
+
const erroredInPeer = coValue.getErroredInPeerError(peerId);
|
|
875
|
+
const knownState = coValue.knownState().sessions;
|
|
876
|
+
const peerKnownState = peerState.getKnownState(id)?.sessions ?? {};
|
|
877
|
+
let errorMessage = `Timeout on waiting for sync with peer ${peerId} for coValue ${id}:
|
|
878
|
+
Known state: ${JSON.stringify(knownState)}
|
|
879
|
+
Peer state: ${JSON.stringify(peerKnownState)}
|
|
880
|
+
`;
|
|
881
|
+
|
|
882
|
+
if (erroredInPeer) {
|
|
883
|
+
errorMessage += `\nMarked as errored: "${erroredInPeer}"`;
|
|
884
|
+
}
|
|
885
|
+
|
|
886
|
+
reject(new Error(errorMessage));
|
|
874
887
|
unsubscribe?.();
|
|
875
888
|
}, timeout);
|
|
876
889
|
});
|
|
@@ -7,6 +7,7 @@ import { connectedPeers } from "../streamUtils.js";
|
|
|
7
7
|
import { emptyKnownState } from "../exports.js";
|
|
8
8
|
import {
|
|
9
9
|
SyncMessagesLog,
|
|
10
|
+
blockMessageTypeOnOutgoingPeer,
|
|
10
11
|
loadCoValueOrFail,
|
|
11
12
|
setupTestNode,
|
|
12
13
|
waitFor,
|
|
@@ -309,4 +310,44 @@ describe("SyncStateManager", () => {
|
|
|
309
310
|
]
|
|
310
311
|
`);
|
|
311
312
|
});
|
|
313
|
+
|
|
314
|
+
test("should throw if the timeout is reached", async () => {
|
|
315
|
+
const client = setupTestNode();
|
|
316
|
+
|
|
317
|
+
const { peer } = client.connectToSyncServer();
|
|
318
|
+
|
|
319
|
+
const group = client.node.createGroup();
|
|
320
|
+
const map = group.createMap();
|
|
321
|
+
map.set("key1", "value1", "trusting");
|
|
322
|
+
|
|
323
|
+
blockMessageTypeOnOutgoingPeer(peer, "content", {
|
|
324
|
+
id: map.core.id,
|
|
325
|
+
});
|
|
326
|
+
|
|
327
|
+
await expect(map.core.waitForSync({ timeout: 1 })).rejects.toThrow(
|
|
328
|
+
new RegExp(
|
|
329
|
+
`Timeout on waiting for sync with peer ${peer.id} for coValue ${map.core.id}:`,
|
|
330
|
+
),
|
|
331
|
+
);
|
|
332
|
+
});
|
|
333
|
+
|
|
334
|
+
test("should throw if the timeout is reached, reporting the errorInPeer if any", async () => {
|
|
335
|
+
const client = setupTestNode();
|
|
336
|
+
|
|
337
|
+
const { peer } = client.connectToSyncServer();
|
|
338
|
+
|
|
339
|
+
const group = client.node.createGroup();
|
|
340
|
+
const map = group.createMap();
|
|
341
|
+
map.set("key1", "value1", "trusting");
|
|
342
|
+
|
|
343
|
+
map.core.markErrored(peer.id, new Error("test error"));
|
|
344
|
+
|
|
345
|
+
blockMessageTypeOnOutgoingPeer(peer, "content", {
|
|
346
|
+
id: map.core.id,
|
|
347
|
+
});
|
|
348
|
+
|
|
349
|
+
await expect(map.core.waitForSync({ timeout: 1 })).rejects.toThrow(
|
|
350
|
+
new RegExp(`Marked as errored: "Error: test error"`),
|
|
351
|
+
);
|
|
352
|
+
});
|
|
312
353
|
});
|