cojson 0.15.8 → 0.15.9
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 +10 -0
- package/dist/IncomingMessagesQueue.d.ts +27 -0
- package/dist/IncomingMessagesQueue.d.ts.map +1 -0
- package/dist/IncomingMessagesQueue.js +114 -0
- package/dist/IncomingMessagesQueue.js.map +1 -0
- package/dist/PeerState.d.ts +2 -10
- package/dist/PeerState.d.ts.map +1 -1
- package/dist/PeerState.js +9 -90
- package/dist/PeerState.js.map +1 -1
- package/dist/PriorityBasedMessageQueue.d.ts +2 -1
- package/dist/PriorityBasedMessageQueue.d.ts.map +1 -1
- package/dist/PriorityBasedMessageQueue.js +9 -6
- package/dist/PriorityBasedMessageQueue.js.map +1 -1
- package/dist/SyncStateManager.d.ts +1 -0
- package/dist/SyncStateManager.d.ts.map +1 -1
- package/dist/SyncStateManager.js +1 -1
- package/dist/SyncStateManager.js.map +1 -1
- package/dist/coValue.d.ts +1 -1
- package/dist/coValueCore/coValueCore.d.ts +9 -17
- package/dist/coValueCore/coValueCore.d.ts.map +1 -1
- package/dist/coValueCore/coValueCore.js +75 -50
- package/dist/coValueCore/coValueCore.js.map +1 -1
- package/dist/coValueCore/verifiedState.d.ts +10 -3
- package/dist/coValueCore/verifiedState.d.ts.map +1 -1
- package/dist/coValueCore/verifiedState.js +73 -14
- package/dist/coValueCore/verifiedState.js.map +1 -1
- package/dist/coValues/coMap.d.ts +3 -3
- package/dist/coValues/coStream.d.ts +2 -2
- package/dist/coValues/group.d.ts +1 -1
- package/dist/coValues/group.d.ts.map +1 -1
- package/dist/coValues/group.js +2 -4
- package/dist/coValues/group.js.map +1 -1
- package/dist/config.d.ts +19 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +23 -0
- package/dist/config.js.map +1 -0
- package/dist/crypto/WasmCrypto.d.ts.map +1 -1
- package/dist/crypto/WasmCrypto.js +2 -1
- package/dist/crypto/WasmCrypto.js.map +1 -1
- package/dist/exports.d.ts +18 -7
- package/dist/exports.d.ts.map +1 -1
- package/dist/exports.js +11 -8
- package/dist/exports.js.map +1 -1
- package/dist/localNode.d.ts +8 -2
- package/dist/localNode.d.ts.map +1 -1
- package/dist/localNode.js +19 -12
- package/dist/localNode.js.map +1 -1
- package/dist/storage/StoreQueue.d.ts +15 -0
- package/dist/storage/StoreQueue.d.ts.map +1 -0
- package/dist/storage/StoreQueue.js +35 -0
- package/dist/storage/StoreQueue.js.map +1 -0
- package/dist/storage/index.d.ts +6 -0
- package/dist/storage/index.d.ts.map +1 -0
- package/dist/storage/index.js +6 -0
- package/dist/storage/index.js.map +1 -0
- package/dist/storage/knownState.d.ts +18 -0
- package/dist/storage/knownState.d.ts.map +1 -0
- package/dist/storage/knownState.js +63 -0
- package/dist/storage/knownState.js.map +1 -0
- package/dist/storage/sqlite/client.d.ts +37 -0
- package/dist/storage/sqlite/client.d.ts.map +1 -0
- package/dist/storage/sqlite/client.js +89 -0
- package/dist/storage/sqlite/client.js.map +1 -0
- package/dist/storage/sqlite/index.d.ts +5 -0
- package/dist/storage/sqlite/index.d.ts.map +1 -0
- package/dist/storage/sqlite/index.js +13 -0
- package/dist/storage/sqlite/index.js.map +1 -0
- package/dist/storage/sqlite/sqliteMigrations.d.ts +3 -0
- package/dist/storage/sqlite/sqliteMigrations.d.ts.map +1 -0
- package/dist/storage/sqlite/sqliteMigrations.js +44 -0
- package/dist/storage/sqlite/sqliteMigrations.js.map +1 -0
- package/dist/storage/sqlite/types.d.ts +8 -0
- package/dist/storage/sqlite/types.d.ts.map +1 -0
- package/dist/storage/sqlite/types.js +2 -0
- package/dist/storage/sqlite/types.js.map +1 -0
- package/dist/storage/sqliteAsync/client.d.ts +37 -0
- package/dist/storage/sqliteAsync/client.d.ts.map +1 -0
- package/dist/storage/sqliteAsync/client.js +88 -0
- package/dist/storage/sqliteAsync/client.js.map +1 -0
- package/dist/storage/sqliteAsync/index.d.ts +6 -0
- package/dist/storage/sqliteAsync/index.d.ts.map +1 -0
- package/dist/storage/sqliteAsync/index.js +15 -0
- package/dist/storage/sqliteAsync/index.js.map +1 -0
- package/dist/storage/sqliteAsync/types.d.ts +9 -0
- package/dist/storage/sqliteAsync/types.d.ts.map +1 -0
- package/dist/storage/sqliteAsync/types.js +2 -0
- package/dist/storage/sqliteAsync/types.js.map +1 -0
- package/dist/storage/storageAsync.d.ts +22 -0
- package/dist/storage/storageAsync.d.ts.map +1 -0
- package/dist/storage/storageAsync.js +214 -0
- package/dist/storage/storageAsync.js.map +1 -0
- package/dist/storage/storageSync.d.ts +21 -0
- package/dist/storage/storageSync.d.ts.map +1 -0
- package/dist/storage/storageSync.js +206 -0
- package/dist/storage/storageSync.js.map +1 -0
- package/dist/storage/syncUtils.d.ts +13 -0
- package/dist/storage/syncUtils.d.ts.map +1 -0
- package/dist/storage/syncUtils.js +25 -0
- package/dist/storage/syncUtils.js.map +1 -0
- package/dist/storage/types.d.ts +82 -0
- package/dist/storage/types.d.ts.map +1 -0
- package/dist/storage/types.js +2 -0
- package/dist/storage/types.js.map +1 -0
- package/dist/streamUtils.d.ts +13 -9
- package/dist/streamUtils.d.ts.map +1 -1
- package/dist/streamUtils.js +46 -13
- package/dist/streamUtils.js.map +1 -1
- package/dist/sync.d.ts +22 -14
- package/dist/sync.d.ts.map +1 -1
- package/dist/sync.js +143 -125
- package/dist/sync.js.map +1 -1
- package/dist/tests/IncomingMessagesQueue.test.d.ts +2 -0
- package/dist/tests/IncomingMessagesQueue.test.d.ts.map +1 -0
- package/dist/tests/IncomingMessagesQueue.test.js +437 -0
- package/dist/tests/IncomingMessagesQueue.test.js.map +1 -0
- package/dist/tests/PeerState.test.js +6 -94
- package/dist/tests/PeerState.test.js.map +1 -1
- package/dist/tests/PriorityBasedMessageQueue.test.js +14 -14
- package/dist/tests/PriorityBasedMessageQueue.test.js.map +1 -1
- package/dist/tests/StoreQueue.test.d.ts +2 -0
- package/dist/tests/StoreQueue.test.d.ts.map +1 -0
- package/dist/tests/StoreQueue.test.js +208 -0
- package/dist/tests/StoreQueue.test.js.map +1 -0
- package/dist/tests/SyncStateManager.test.js +3 -1
- package/dist/tests/SyncStateManager.test.js.map +1 -1
- package/dist/tests/account.test.js +9 -9
- package/dist/tests/account.test.js.map +1 -1
- package/dist/tests/coStream.test.js +1 -1
- package/dist/tests/coStream.test.js.map +1 -1
- package/dist/tests/coValueCore.test.js +208 -1
- package/dist/tests/coValueCore.test.js.map +1 -1
- package/dist/tests/coValueCoreLoadingState.test.js +2 -2
- package/dist/tests/coValueCoreLoadingState.test.js.map +1 -1
- package/dist/tests/group.addMember.test.js.map +1 -1
- package/dist/tests/group.removeMember.test.js +1 -1
- package/dist/tests/group.removeMember.test.js.map +1 -1
- package/dist/tests/messagesTestUtils.js +1 -1
- package/dist/tests/messagesTestUtils.js.map +1 -1
- package/dist/tests/sync.auth.test.js +23 -15
- package/dist/tests/sync.auth.test.js.map +1 -1
- package/dist/tests/sync.invite.test.js +10 -16
- package/dist/tests/sync.invite.test.js.map +1 -1
- package/dist/tests/sync.load.test.js +52 -50
- package/dist/tests/sync.load.test.js.map +1 -1
- package/dist/tests/sync.mesh.test.js +173 -56
- package/dist/tests/sync.mesh.test.js.map +1 -1
- package/dist/tests/sync.peerReconciliation.test.js +42 -32
- package/dist/tests/sync.peerReconciliation.test.js.map +1 -1
- package/dist/tests/sync.storage.test.js +162 -62
- package/dist/tests/sync.storage.test.js.map +1 -1
- package/dist/tests/sync.storageAsync.test.d.ts +2 -0
- package/dist/tests/sync.storageAsync.test.d.ts.map +1 -0
- package/dist/tests/sync.storageAsync.test.js +361 -0
- package/dist/tests/sync.storageAsync.test.js.map +1 -0
- package/dist/tests/sync.test.js +16 -21
- package/dist/tests/sync.test.js.map +1 -1
- package/dist/tests/sync.upload.test.js +28 -25
- package/dist/tests/sync.upload.test.js.map +1 -1
- package/dist/tests/testStorage.d.ts +12 -0
- package/dist/tests/testStorage.d.ts.map +1 -0
- package/dist/tests/testStorage.js +151 -0
- package/dist/tests/testStorage.js.map +1 -0
- package/dist/tests/testUtils.d.ts +20 -15
- package/dist/tests/testUtils.d.ts.map +1 -1
- package/dist/tests/testUtils.js +79 -45
- package/dist/tests/testUtils.js.map +1 -1
- package/package.json +2 -2
- package/src/IncomingMessagesQueue.ts +142 -0
- package/src/PeerState.ts +11 -110
- package/src/PriorityBasedMessageQueue.ts +13 -5
- package/src/SyncStateManager.ts +1 -1
- package/src/coValueCore/coValueCore.ts +100 -66
- package/src/coValueCore/verifiedState.ts +91 -21
- package/src/coValues/group.ts +2 -4
- package/src/config.ts +26 -0
- package/src/crypto/WasmCrypto.ts +3 -1
- package/src/exports.ts +20 -27
- package/src/localNode.ts +27 -12
- package/src/storage/StoreQueue.ts +56 -0
- package/src/storage/index.ts +5 -0
- package/src/storage/knownState.ts +88 -0
- package/src/storage/sqlite/client.ts +180 -0
- package/src/storage/sqlite/index.ts +19 -0
- package/src/storage/sqlite/sqliteMigrations.ts +44 -0
- package/src/storage/sqlite/types.ts +7 -0
- package/src/storage/sqliteAsync/client.ts +179 -0
- package/src/storage/sqliteAsync/index.ts +25 -0
- package/src/storage/sqliteAsync/types.ts +8 -0
- package/src/storage/storageAsync.ts +367 -0
- package/src/storage/storageSync.ts +343 -0
- package/src/storage/syncUtils.ts +50 -0
- package/src/storage/types.ts +162 -0
- package/src/streamUtils.ts +61 -19
- package/src/sync.ts +191 -160
- package/src/tests/IncomingMessagesQueue.test.ts +626 -0
- package/src/tests/PeerState.test.ts +6 -118
- package/src/tests/PriorityBasedMessageQueue.test.ts +18 -14
- package/src/tests/StoreQueue.test.ts +283 -0
- package/src/tests/SyncStateManager.test.ts +4 -1
- package/src/tests/account.test.ts +11 -12
- package/src/tests/coStream.test.ts +1 -3
- package/src/tests/coValueCore.test.ts +270 -1
- package/src/tests/coValueCoreLoadingState.test.ts +2 -2
- package/src/tests/group.addMember.test.ts +1 -0
- package/src/tests/group.removeMember.test.ts +2 -8
- package/src/tests/messagesTestUtils.ts +2 -2
- package/src/tests/sync.auth.test.ts +24 -14
- package/src/tests/sync.invite.test.ts +11 -17
- package/src/tests/sync.load.test.ts +53 -49
- package/src/tests/sync.mesh.test.ts +198 -56
- package/src/tests/sync.peerReconciliation.test.ts +44 -34
- package/src/tests/sync.storage.test.ts +231 -64
- package/src/tests/sync.storageAsync.test.ts +486 -0
- package/src/tests/sync.test.ts +17 -23
- package/src/tests/sync.upload.test.ts +29 -24
- package/src/tests/testStorage.ts +216 -0
- package/src/tests/testUtils.ts +89 -54
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/storage/types.ts"],"names":[],"mappings":""}
|
package/dist/streamUtils.d.ts
CHANGED
|
@@ -1,13 +1,17 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
export { Channel } from "queueueue";
|
|
4
|
-
export declare function connectedPeers(peer1id: PeerID, peer2id: PeerID, { peer1role, peer2role, crashOnClose, }?: {
|
|
1
|
+
import { DisconnectedError, IncomingPeerChannel, OutgoingPeerChannel, Peer, PeerID, SyncMessage } from "./sync.js";
|
|
2
|
+
export declare function connectedPeers(peer1id: PeerID, peer2id: PeerID, { peer1role, peer2role, }?: {
|
|
5
3
|
peer1role?: Peer["role"];
|
|
6
4
|
peer2role?: Peer["role"];
|
|
7
|
-
crashOnClose?: boolean;
|
|
8
5
|
}): [Peer, Peer];
|
|
9
|
-
export declare function newQueuePair(): [
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
6
|
+
export declare function newQueuePair(): [ConnectedPeerChannel, ConnectedPeerChannel];
|
|
7
|
+
export declare class ConnectedPeerChannel implements IncomingPeerChannel, OutgoingPeerChannel {
|
|
8
|
+
buffer: (SyncMessage | DisconnectedError)[];
|
|
9
|
+
push(msg: SyncMessage | DisconnectedError): void;
|
|
10
|
+
close(): void;
|
|
11
|
+
listeners: Set<(msg: SyncMessage | DisconnectedError) => void>;
|
|
12
|
+
onMessage(callback: (msg: SyncMessage | DisconnectedError) => void): void;
|
|
13
|
+
closed: boolean;
|
|
14
|
+
closeListeners: Set<() => void>;
|
|
15
|
+
onClose(callback: () => void): void;
|
|
16
|
+
}
|
|
13
17
|
//# sourceMappingURL=streamUtils.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"streamUtils.d.ts","sourceRoot":"","sources":["../src/streamUtils.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"streamUtils.d.ts","sourceRoot":"","sources":["../src/streamUtils.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,iBAAiB,EACjB,mBAAmB,EACnB,mBAAmB,EACnB,IAAI,EACJ,MAAM,EACN,WAAW,EACZ,MAAM,WAAW,CAAC;AAEnB,wBAAgB,cAAc,CAC5B,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,EACf,EACE,SAAoB,EACpB,SAAoB,GACrB,GAAE;IACD,SAAS,CAAC,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;IACzB,SAAS,CAAC,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;CACrB,GACL,CAAC,IAAI,EAAE,IAAI,CAAC,CAmBd;AAED,wBAAgB,YAAY,IAAI,CAAC,oBAAoB,EAAE,oBAAoB,CAAC,CAI3E;AAED,qBAAa,oBACX,YAAW,mBAAmB,EAAE,mBAAmB;IAEnD,MAAM,EAAE,CAAC,WAAW,GAAG,iBAAiB,CAAC,EAAE,CAAM;IAEjD,IAAI,CAAC,GAAG,EAAE,WAAW,GAAG,iBAAiB;IAWzC,KAAK;IASL,SAAS,YAAiB,WAAW,GAAG,iBAAiB,KAAK,IAAI,EAAI;IACtE,SAAS,CAAC,QAAQ,EAAE,CAAC,GAAG,EAAE,WAAW,GAAG,iBAAiB,KAAK,IAAI;IAWlE,MAAM,UAAS;IACf,cAAc,YAAiB,IAAI,EAAI;IACvC,OAAO,CAAC,QAAQ,EAAE,MAAM,IAAI;CAG7B"}
|
package/dist/streamUtils.js
CHANGED
|
@@ -1,26 +1,59 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
const [from1to2Rx, from1to2Tx] = newQueuePair();
|
|
5
|
-
const [from2to1Rx, from2to1Tx] = newQueuePair();
|
|
1
|
+
export function connectedPeers(peer1id, peer2id, { peer1role = "client", peer2role = "client", } = {}) {
|
|
2
|
+
const from1to2 = new ConnectedPeerChannel();
|
|
3
|
+
const from2to1 = new ConnectedPeerChannel();
|
|
6
4
|
const peer2AsPeer = {
|
|
7
5
|
id: peer2id,
|
|
8
|
-
incoming:
|
|
9
|
-
outgoing:
|
|
6
|
+
incoming: from2to1,
|
|
7
|
+
outgoing: from1to2,
|
|
10
8
|
role: peer2role,
|
|
11
|
-
crashOnClose: crashOnClose,
|
|
12
9
|
};
|
|
13
10
|
const peer1AsPeer = {
|
|
14
11
|
id: peer1id,
|
|
15
|
-
incoming:
|
|
16
|
-
outgoing:
|
|
12
|
+
incoming: from1to2,
|
|
13
|
+
outgoing: from2to1,
|
|
17
14
|
role: peer1role,
|
|
18
|
-
crashOnClose: crashOnClose,
|
|
19
15
|
};
|
|
20
16
|
return [peer1AsPeer, peer2AsPeer];
|
|
21
17
|
}
|
|
22
18
|
export function newQueuePair() {
|
|
23
|
-
const channel = new
|
|
24
|
-
return [channel
|
|
19
|
+
const channel = new ConnectedPeerChannel();
|
|
20
|
+
return [channel, channel];
|
|
21
|
+
}
|
|
22
|
+
export class ConnectedPeerChannel {
|
|
23
|
+
constructor() {
|
|
24
|
+
this.buffer = [];
|
|
25
|
+
this.listeners = new Set();
|
|
26
|
+
this.closed = false;
|
|
27
|
+
this.closeListeners = new Set();
|
|
28
|
+
}
|
|
29
|
+
push(msg) {
|
|
30
|
+
if (!this.listeners.size) {
|
|
31
|
+
this.buffer.push(msg);
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
for (const listener of this.listeners) {
|
|
35
|
+
listener(msg);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
close() {
|
|
39
|
+
this.closed = true;
|
|
40
|
+
for (const listener of this.closeListeners) {
|
|
41
|
+
listener();
|
|
42
|
+
}
|
|
43
|
+
this.closeListeners.clear();
|
|
44
|
+
this.listeners.clear();
|
|
45
|
+
}
|
|
46
|
+
onMessage(callback) {
|
|
47
|
+
if (this.buffer.length) {
|
|
48
|
+
for (const msg of this.buffer) {
|
|
49
|
+
callback(msg);
|
|
50
|
+
}
|
|
51
|
+
this.buffer = [];
|
|
52
|
+
}
|
|
53
|
+
this.listeners.add(callback);
|
|
54
|
+
}
|
|
55
|
+
onClose(callback) {
|
|
56
|
+
this.closeListeners.add(callback);
|
|
57
|
+
}
|
|
25
58
|
}
|
|
26
59
|
//# sourceMappingURL=streamUtils.js.map
|
package/dist/streamUtils.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"streamUtils.js","sourceRoot":"","sources":["../src/streamUtils.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"streamUtils.js","sourceRoot":"","sources":["../src/streamUtils.ts"],"names":[],"mappings":"AASA,MAAM,UAAU,cAAc,CAC5B,OAAe,EACf,OAAe,EACf,EACE,SAAS,GAAG,QAAQ,EACpB,SAAS,GAAG,QAAQ,MAIlB,EAAE;IAEN,MAAM,QAAQ,GAAG,IAAI,oBAAoB,EAAE,CAAC;IAC5C,MAAM,QAAQ,GAAG,IAAI,oBAAoB,EAAE,CAAC;IAE5C,MAAM,WAAW,GAAS;QACxB,EAAE,EAAE,OAAO;QACX,QAAQ,EAAE,QAAQ;QAClB,QAAQ,EAAE,QAAQ;QAClB,IAAI,EAAE,SAAS;KAChB,CAAC;IAEF,MAAM,WAAW,GAAS;QACxB,EAAE,EAAE,OAAO;QACX,QAAQ,EAAE,QAAQ;QAClB,QAAQ,EAAE,QAAQ;QAClB,IAAI,EAAE,SAAS;KAChB,CAAC;IAEF,OAAO,CAAC,WAAW,EAAE,WAAW,CAAC,CAAC;AACpC,CAAC;AAED,MAAM,UAAU,YAAY;IAC1B,MAAM,OAAO,GAAG,IAAI,oBAAoB,EAAE,CAAC;IAE3C,OAAO,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;AAC5B,CAAC;AAED,MAAM,OAAO,oBAAoB;IAAjC;QAGE,WAAM,GAAwC,EAAE,CAAC;QAsBjD,cAAS,GAAG,IAAI,GAAG,EAAkD,CAAC;QAYtE,WAAM,GAAG,KAAK,CAAC;QACf,mBAAc,GAAG,IAAI,GAAG,EAAc,CAAC;IAIzC,CAAC;IArCC,IAAI,CAAC,GAAoC;QACvC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC;YACzB,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YACtB,OAAO;QACT,CAAC;QAED,KAAK,MAAM,QAAQ,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;YACtC,QAAQ,CAAC,GAAG,CAAC,CAAC;QAChB,CAAC;IACH,CAAC;IAED,KAAK;QACH,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;QACnB,KAAK,MAAM,QAAQ,IAAI,IAAI,CAAC,cAAc,EAAE,CAAC;YAC3C,QAAQ,EAAE,CAAC;QACb,CAAC;QACD,IAAI,CAAC,cAAc,CAAC,KAAK,EAAE,CAAC;QAC5B,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,CAAC;IACzB,CAAC;IAGD,SAAS,CAAC,QAAwD;QAChE,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;YACvB,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;gBAC9B,QAAQ,CAAC,GAAG,CAAC,CAAC;YAChB,CAAC;YACD,IAAI,CAAC,MAAM,GAAG,EAAE,CAAC;QACnB,CAAC;QAED,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IAC/B,CAAC;IAID,OAAO,CAAC,QAAoB;QAC1B,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IACpC,CAAC;CACF"}
|
package/dist/sync.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { IncomingMessagesQueue } from "./IncomingMessagesQueue.js";
|
|
1
2
|
import { PeerState } from "./PeerState.js";
|
|
2
3
|
import { SyncStateManager } from "./SyncStateManager.js";
|
|
3
4
|
import { CoValueCore } from "./coValueCore/coValueCore.js";
|
|
@@ -31,6 +32,9 @@ export type NewContentMessage = {
|
|
|
31
32
|
new: {
|
|
32
33
|
[sessionID: SessionID]: SessionNewContent;
|
|
33
34
|
};
|
|
35
|
+
expectContentUntil?: {
|
|
36
|
+
[sessionID: SessionID]: number;
|
|
37
|
+
};
|
|
34
38
|
};
|
|
35
39
|
export type SessionNewContent = {
|
|
36
40
|
after: number;
|
|
@@ -43,19 +47,22 @@ export type DoneMessage = {
|
|
|
43
47
|
};
|
|
44
48
|
export type PeerID = string;
|
|
45
49
|
export type DisconnectedError = "Disconnected";
|
|
46
|
-
export
|
|
47
|
-
export type IncomingSyncStream = AsyncIterable<SyncMessage | DisconnectedError | PingTimeoutError>;
|
|
48
|
-
export type OutgoingSyncQueue = {
|
|
49
|
-
push: (msg: SyncMessage) => Promise<unknown>;
|
|
50
|
+
export interface IncomingPeerChannel {
|
|
50
51
|
close: () => void;
|
|
51
|
-
|
|
52
|
+
onMessage: (callback: (msg: SyncMessage | DisconnectedError) => void) => void;
|
|
53
|
+
onClose: (callback: () => void) => void;
|
|
54
|
+
}
|
|
55
|
+
export interface OutgoingPeerChannel {
|
|
56
|
+
push: (msg: SyncMessage | DisconnectedError) => void;
|
|
57
|
+
close: () => void;
|
|
58
|
+
onClose: (callback: () => void) => void;
|
|
59
|
+
}
|
|
52
60
|
export interface Peer {
|
|
53
61
|
id: PeerID;
|
|
54
|
-
incoming:
|
|
55
|
-
outgoing:
|
|
56
|
-
role: "server" | "client"
|
|
62
|
+
incoming: IncomingPeerChannel;
|
|
63
|
+
outgoing: OutgoingPeerChannel;
|
|
64
|
+
role: "server" | "client";
|
|
57
65
|
priority?: number;
|
|
58
|
-
crashOnClose: boolean;
|
|
59
66
|
deletePeerStateOnClose?: boolean;
|
|
60
67
|
}
|
|
61
68
|
export declare function combinedKnownStates(stateA: CoValueKnownState, stateB: CoValueKnownState): CoValueKnownState;
|
|
@@ -70,11 +77,12 @@ export declare class SyncManager {
|
|
|
70
77
|
syncState: SyncStateManager;
|
|
71
78
|
peersInPriorityOrder(): PeerState[];
|
|
72
79
|
getPeers(): PeerState[];
|
|
73
|
-
|
|
74
|
-
hasStoragePeers(): boolean;
|
|
80
|
+
getServerPeers(excludePeerId?: PeerID): PeerState[];
|
|
75
81
|
handleSyncMessage(msg: SyncMessage, peer: PeerState): void;
|
|
76
82
|
sendNewContentIncludingDependencies(id: RawCoID, peer: PeerState, seen?: Set<RawCoID>): void;
|
|
77
83
|
startPeerReconciliation(peer: PeerState): void;
|
|
84
|
+
messagesQueue: IncomingMessagesQueue;
|
|
85
|
+
pushMessage(incoming: SyncMessage, peer: PeerState): void;
|
|
78
86
|
addPeer(peer: Peer): void;
|
|
79
87
|
trySendToPeer(peer: PeerState, msg: SyncMessage): void;
|
|
80
88
|
/**
|
|
@@ -88,14 +96,14 @@ export declare class SyncManager {
|
|
|
88
96
|
handleLoad(msg: LoadMessage, peer: PeerState): void;
|
|
89
97
|
handleKnownState(msg: KnownStateMessage, peer: PeerState): void;
|
|
90
98
|
recordTransactionsSize(newTransactions: Transaction[], source: string): void;
|
|
91
|
-
handleNewContent(msg: NewContentMessage,
|
|
99
|
+
handleNewContent(msg: NewContentMessage, from: PeerState | "storage"): void;
|
|
92
100
|
handleCorrection(msg: KnownStateMessage, peer: PeerState): void;
|
|
93
|
-
handleUnsubscribe(_msg: DoneMessage): void;
|
|
94
101
|
requestedSyncs: Set<`co_z${string}`>;
|
|
95
102
|
requestCoValueSync(coValue: CoValueCore): void;
|
|
103
|
+
storeCoValue(coValue: CoValueCore, data: NewContentMessage[] | undefined): void;
|
|
96
104
|
syncCoValue(coValue: CoValueCore): void;
|
|
97
105
|
waitForSyncWithPeer(peerId: PeerID, id: RawCoID, timeout: number): Promise<unknown> | undefined;
|
|
98
|
-
waitForStorageSync(id: RawCoID
|
|
106
|
+
waitForStorageSync(id: RawCoID): Promise<void> | undefined;
|
|
99
107
|
waitForSync(id: RawCoID, timeout?: number): Promise<unknown[]>;
|
|
100
108
|
waitForAllCoValuesSync(timeout?: number): Promise<unknown[][]>;
|
|
101
109
|
gracefulShutdown(): void;
|
package/dist/sync.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sync.d.ts","sourceRoot":"","sources":["../src/sync.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,
|
|
1
|
+
{"version":3,"file":"sync.d.ts","sourceRoot":"","sources":["../src/sync.ts"],"names":[],"mappings":"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"}
|
package/dist/sync.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { ValueType, metrics } from "@opentelemetry/api";
|
|
2
|
+
import { IncomingMessagesQueue } from "./IncomingMessagesQueue.js";
|
|
2
3
|
import { PeerState } from "./PeerState.js";
|
|
3
4
|
import { SyncStateManager } from "./SyncStateManager.js";
|
|
4
5
|
import { getDependedOnCoValuesFromRawData } from "./coValueCore/utils.js";
|
|
@@ -37,6 +38,7 @@ export class SyncManager {
|
|
|
37
38
|
valueType: ValueType.INT,
|
|
38
39
|
unit: "peer",
|
|
39
40
|
});
|
|
41
|
+
this.messagesQueue = new IncomingMessagesQueue();
|
|
40
42
|
this.requestedSyncs = new Set();
|
|
41
43
|
this.local = local;
|
|
42
44
|
this.syncState = new SyncStateManager(this);
|
|
@@ -58,13 +60,8 @@ export class SyncManager {
|
|
|
58
60
|
getPeers() {
|
|
59
61
|
return Object.values(this.peers);
|
|
60
62
|
}
|
|
61
|
-
|
|
62
|
-
return this.
|
|
63
|
-
peer.id !== excludePeerId &&
|
|
64
|
-
!peer.closed);
|
|
65
|
-
}
|
|
66
|
-
hasStoragePeers() {
|
|
67
|
-
return this.getPeers().some((peer) => peer.role === "storage" && !peer.closed);
|
|
63
|
+
getServerPeers(excludePeerId) {
|
|
64
|
+
return this.getPeers().filter((peer) => peer.role === "server" && peer.id !== excludePeerId && !peer.closed);
|
|
68
65
|
}
|
|
69
66
|
handleSyncMessage(msg, peer) {
|
|
70
67
|
if (msg.id === undefined || msg.id === null) {
|
|
@@ -97,7 +94,7 @@ export class SyncManager {
|
|
|
97
94
|
case "content":
|
|
98
95
|
return this.handleNewContent(msg, peer);
|
|
99
96
|
case "done":
|
|
100
|
-
return
|
|
97
|
+
return;
|
|
101
98
|
default:
|
|
102
99
|
throw new Error(`Unknown message type ${msg.action}`);
|
|
103
100
|
}
|
|
@@ -124,7 +121,7 @@ export class SyncManager {
|
|
|
124
121
|
else if (!peer.toldKnownState.has(id)) {
|
|
125
122
|
this.trySendToPeer(peer, {
|
|
126
123
|
action: "known",
|
|
127
|
-
...coValue.
|
|
124
|
+
...coValue.knownStateWithStreaming(),
|
|
128
125
|
});
|
|
129
126
|
}
|
|
130
127
|
peer.trackToldKnownState(id);
|
|
@@ -183,6 +180,15 @@ export class SyncManager {
|
|
|
183
180
|
});
|
|
184
181
|
}
|
|
185
182
|
}
|
|
183
|
+
pushMessage(incoming, peer) {
|
|
184
|
+
this.messagesQueue.push(incoming, peer);
|
|
185
|
+
if (this.messagesQueue.processing) {
|
|
186
|
+
return;
|
|
187
|
+
}
|
|
188
|
+
this.messagesQueue.processQueue((msg, peer) => {
|
|
189
|
+
this.handleSyncMessage(msg, peer);
|
|
190
|
+
});
|
|
191
|
+
}
|
|
186
192
|
addPeer(peer) {
|
|
187
193
|
const prevPeer = this.peers[peer.id];
|
|
188
194
|
if (prevPeer && !prevPeer.closed) {
|
|
@@ -194,36 +200,17 @@ export class SyncManager {
|
|
|
194
200
|
const unsubscribeFromKnownStatesUpdates = peerState.knownStates.subscribe((id) => {
|
|
195
201
|
this.syncState.triggerUpdate(peer.id, id);
|
|
196
202
|
});
|
|
197
|
-
if (peerState.
|
|
203
|
+
if (peerState.role === "server") {
|
|
198
204
|
void this.startPeerReconciliation(peerState);
|
|
199
205
|
}
|
|
200
|
-
peerState
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
.then(() => {
|
|
205
|
-
if (peer.crashOnClose) {
|
|
206
|
-
logger.error("Unexepcted close from peer", {
|
|
207
|
-
peerId: peer.id,
|
|
208
|
-
peerRole: peer.role,
|
|
209
|
-
});
|
|
210
|
-
this.local.crashed = new Error("Unexpected close from peer");
|
|
211
|
-
throw new Error("Unexpected close from peer");
|
|
212
|
-
}
|
|
213
|
-
})
|
|
214
|
-
.catch((e) => {
|
|
215
|
-
logger.error("Error processing messages from peer", {
|
|
216
|
-
err: e,
|
|
217
|
-
peerId: peer.id,
|
|
218
|
-
peerRole: peer.role,
|
|
219
|
-
});
|
|
220
|
-
if (peer.crashOnClose) {
|
|
221
|
-
this.local.crashed = e;
|
|
222
|
-
throw new Error(e);
|
|
206
|
+
peerState.incoming.onMessage((msg) => {
|
|
207
|
+
if (msg === "Disconnected") {
|
|
208
|
+
peerState.gracefulShutdown();
|
|
209
|
+
return;
|
|
223
210
|
}
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
211
|
+
this.pushMessage(msg, peerState);
|
|
212
|
+
});
|
|
213
|
+
peerState.addCloseListener(() => {
|
|
227
214
|
unsubscribeFromKnownStatesUpdates();
|
|
228
215
|
this.peersCounter.add(-1, { role: peer.role });
|
|
229
216
|
if (peer.deletePeerStateOnClose && this.peers[peer.id] === peerState) {
|
|
@@ -255,11 +242,13 @@ export class SyncManager {
|
|
|
255
242
|
this.sendNewContentIncludingDependencies(msg.id, peer);
|
|
256
243
|
return;
|
|
257
244
|
}
|
|
258
|
-
const
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
245
|
+
const peers = this.getServerPeers(peer.id);
|
|
246
|
+
coValue.load(peers);
|
|
247
|
+
const handleLoadResult = () => {
|
|
248
|
+
if (coValue.isAvailable()) {
|
|
249
|
+
this.sendNewContentIncludingDependencies(msg.id, peer);
|
|
250
|
+
return;
|
|
251
|
+
}
|
|
263
252
|
peer.trackToldKnownState(msg.id);
|
|
264
253
|
this.trySendToPeer(peer, {
|
|
265
254
|
action: "known",
|
|
@@ -267,35 +256,13 @@ export class SyncManager {
|
|
|
267
256
|
header: false,
|
|
268
257
|
sessions: {},
|
|
269
258
|
});
|
|
270
|
-
|
|
259
|
+
};
|
|
260
|
+
if (peers.length > 0 || this.local.storage) {
|
|
261
|
+
coValue.waitForAvailableOrUnavailable().then(handleLoadResult);
|
|
262
|
+
}
|
|
263
|
+
else {
|
|
264
|
+
handleLoadResult();
|
|
271
265
|
}
|
|
272
|
-
coValue.loadFromPeers(eligiblePeers).catch((e) => {
|
|
273
|
-
logger.error("Error loading coValue in handleLoad", { err: e });
|
|
274
|
-
});
|
|
275
|
-
// We need to return from handleLoad immediately and wait for the CoValue to be loaded
|
|
276
|
-
// in a new task, otherwise we might block further incoming content messages that would
|
|
277
|
-
// resolve the CoValue as available. This can happen when we receive fresh
|
|
278
|
-
// content from a client, but we are a server with our own upstream server(s)
|
|
279
|
-
coValue
|
|
280
|
-
.waitForAvailableOrUnavailable()
|
|
281
|
-
.then((value) => {
|
|
282
|
-
if (!value.isAvailable()) {
|
|
283
|
-
peer.trackToldKnownState(msg.id);
|
|
284
|
-
this.trySendToPeer(peer, {
|
|
285
|
-
action: "known",
|
|
286
|
-
id: msg.id,
|
|
287
|
-
header: false,
|
|
288
|
-
sessions: {},
|
|
289
|
-
});
|
|
290
|
-
return;
|
|
291
|
-
}
|
|
292
|
-
this.sendNewContentIncludingDependencies(msg.id, peer);
|
|
293
|
-
})
|
|
294
|
-
.catch((e) => {
|
|
295
|
-
logger.error("Error loading coValue in handleLoad loading state", {
|
|
296
|
-
err: e,
|
|
297
|
-
});
|
|
298
|
-
});
|
|
299
266
|
}
|
|
300
267
|
handleKnownState(msg, peer) {
|
|
301
268
|
const coValue = this.local.getCoValue(msg.id);
|
|
@@ -320,40 +287,56 @@ export class SyncManager {
|
|
|
320
287
|
});
|
|
321
288
|
}
|
|
322
289
|
}
|
|
323
|
-
handleNewContent(msg,
|
|
290
|
+
handleNewContent(msg, from) {
|
|
324
291
|
const coValue = this.local.getCoValue(msg.id);
|
|
325
|
-
|
|
292
|
+
const peer = from === "storage" ? undefined : from;
|
|
293
|
+
if (!coValue.hasVerifiedContent()) {
|
|
326
294
|
if (!msg.header) {
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
295
|
+
if (peer) {
|
|
296
|
+
this.trySendToPeer(peer, {
|
|
297
|
+
action: "known",
|
|
298
|
+
isCorrection: true,
|
|
299
|
+
id: msg.id,
|
|
300
|
+
header: false,
|
|
301
|
+
sessions: {},
|
|
302
|
+
});
|
|
303
|
+
}
|
|
304
|
+
else {
|
|
305
|
+
logger.error("Received new content with no header on a missing CoValue", {
|
|
306
|
+
id: msg.id,
|
|
307
|
+
});
|
|
308
|
+
}
|
|
334
309
|
return;
|
|
335
310
|
}
|
|
336
311
|
const sessionIDs = Object.keys(msg.new);
|
|
337
312
|
const transactions = Object.values(msg.new).map((content) => content.newTransactions);
|
|
338
313
|
for (const dependency of getDependedOnCoValuesFromRawData(msg.id, msg.header, sessionIDs, transactions)) {
|
|
339
314
|
const dependencyCoValue = this.local.getCoValue(dependency);
|
|
340
|
-
if (!dependencyCoValue.
|
|
315
|
+
if (!dependencyCoValue.hasVerifiedContent()) {
|
|
341
316
|
coValue.markMissingDependency(dependency);
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
peers.push(peer);
|
|
348
|
-
}
|
|
349
|
-
dependencyCoValue.loadFromPeers(peers);
|
|
317
|
+
const peers = this.getServerPeers();
|
|
318
|
+
// if the peer that sent the content is a client, we add it to the list of peers
|
|
319
|
+
// to also ask them for the dependency
|
|
320
|
+
if (peer?.role === "client") {
|
|
321
|
+
peers.push(peer);
|
|
350
322
|
}
|
|
323
|
+
dependencyCoValue.load(peers);
|
|
324
|
+
}
|
|
325
|
+
else if (!dependencyCoValue.isAvailable()) {
|
|
326
|
+
coValue.markMissingDependency(dependency);
|
|
351
327
|
}
|
|
352
328
|
}
|
|
353
|
-
peer
|
|
354
|
-
coValue.provideHeader(msg.header, peer.
|
|
329
|
+
peer?.updateHeader(msg.id, true);
|
|
330
|
+
coValue.provideHeader(msg.header, peer?.id ?? "storage", msg.expectContentUntil);
|
|
331
|
+
if (msg.expectContentUntil) {
|
|
332
|
+
peer?.combineWith(msg.id, {
|
|
333
|
+
id: msg.id,
|
|
334
|
+
header: true,
|
|
335
|
+
sessions: msg.expectContentUntil,
|
|
336
|
+
});
|
|
337
|
+
}
|
|
355
338
|
}
|
|
356
|
-
if (!coValue.
|
|
339
|
+
if (!coValue.hasVerifiedContent()) {
|
|
357
340
|
throw new Error("Unreachable: CoValue should always have a verified state at this point");
|
|
358
341
|
}
|
|
359
342
|
let invalidStateAssumed = false;
|
|
@@ -379,13 +362,13 @@ export class SyncManager {
|
|
|
379
362
|
// This covers the case where we are getting a new session on an already loaded coValue
|
|
380
363
|
// where we need to load the account to get their public key
|
|
381
364
|
if (!coValue.missingDependencies.has(accountId)) {
|
|
382
|
-
const peers = this.
|
|
383
|
-
if (peer
|
|
365
|
+
const peers = this.getServerPeers();
|
|
366
|
+
if (peer?.role === "client") {
|
|
384
367
|
// if the peer that sent the content is a client, we add it to the list of peers
|
|
385
368
|
// to also ask them for the dependency
|
|
386
369
|
peers.push(peer);
|
|
387
370
|
}
|
|
388
|
-
account.
|
|
371
|
+
account.load(peers);
|
|
389
372
|
}
|
|
390
373
|
// We need to wait for the account to be available before we can verify the transaction
|
|
391
374
|
// Currently doing this by delaying the handleNewContent for the session to when we have the account
|
|
@@ -405,35 +388,50 @@ export class SyncManager {
|
|
|
405
388
|
[sessionID]: newContentForSession,
|
|
406
389
|
},
|
|
407
390
|
priority: msg.priority,
|
|
408
|
-
},
|
|
391
|
+
}, from);
|
|
409
392
|
});
|
|
410
393
|
continue;
|
|
411
394
|
}
|
|
412
395
|
}
|
|
413
396
|
const result = coValue.tryAddTransactions(sessionID, newTransactions, undefined, newContentForSession.lastSignature, "immediate");
|
|
414
397
|
if (result.isErr()) {
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
398
|
+
if (peer) {
|
|
399
|
+
logger.error("Failed to add transactions", {
|
|
400
|
+
peerId: peer.id,
|
|
401
|
+
peerRole: peer.role,
|
|
402
|
+
id: msg.id,
|
|
403
|
+
err: result.error,
|
|
404
|
+
});
|
|
405
|
+
coValue.markErrored(peer.id, result.error);
|
|
406
|
+
}
|
|
407
|
+
else {
|
|
408
|
+
logger.error("Failed to add transactions from storage", {
|
|
409
|
+
id: msg.id,
|
|
410
|
+
err: result.error,
|
|
411
|
+
});
|
|
412
|
+
}
|
|
422
413
|
continue;
|
|
423
414
|
}
|
|
424
|
-
this.recordTransactionsSize(newTransactions, peer
|
|
425
|
-
peer
|
|
415
|
+
this.recordTransactionsSize(newTransactions, peer?.role ?? "storage");
|
|
416
|
+
peer?.updateSessionCounter(msg.id, sessionID, newContentForSession.after +
|
|
426
417
|
newContentForSession.newTransactions.length);
|
|
427
418
|
}
|
|
428
419
|
if (invalidStateAssumed) {
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
420
|
+
if (peer) {
|
|
421
|
+
this.trySendToPeer(peer, {
|
|
422
|
+
action: "known",
|
|
423
|
+
isCorrection: true,
|
|
424
|
+
...coValue.knownState(),
|
|
425
|
+
});
|
|
426
|
+
peer.trackToldKnownState(msg.id);
|
|
427
|
+
}
|
|
428
|
+
else {
|
|
429
|
+
logger.error("Invalid state assumed when handling new content from storage", {
|
|
430
|
+
id: msg.id,
|
|
431
|
+
});
|
|
432
|
+
}
|
|
435
433
|
}
|
|
436
|
-
else {
|
|
434
|
+
else if (peer) {
|
|
437
435
|
/**
|
|
438
436
|
* We are sending a known state message to the peer to acknowledge the
|
|
439
437
|
* receipt of the new content.
|
|
@@ -447,18 +445,15 @@ export class SyncManager {
|
|
|
447
445
|
});
|
|
448
446
|
peer.trackToldKnownState(msg.id);
|
|
449
447
|
}
|
|
450
|
-
const sourcePeer = peer;
|
|
451
448
|
const syncedPeers = [];
|
|
449
|
+
if (from !== "storage") {
|
|
450
|
+
this.storeCoValue(coValue, [msg]);
|
|
451
|
+
}
|
|
452
452
|
for (const peer of this.peersInPriorityOrder()) {
|
|
453
453
|
/**
|
|
454
454
|
* We sync the content against the source peer if it is a client or server peers
|
|
455
455
|
* to upload any content that is available on the current node and not on the source peer.
|
|
456
|
-
*
|
|
457
|
-
* We don't need to do this with storage peers because we don't get updates from those peers,
|
|
458
|
-
* only load and store content.
|
|
459
456
|
*/
|
|
460
|
-
if (peer.id === sourcePeer.id && sourcePeer.role === "storage")
|
|
461
|
-
continue;
|
|
462
457
|
if (peer.closed)
|
|
463
458
|
continue;
|
|
464
459
|
if (coValue.isErroredInPeer(peer.id))
|
|
@@ -468,7 +463,7 @@ export class SyncManager {
|
|
|
468
463
|
this.sendNewContentIncludingDependencies(coValue.id, peer);
|
|
469
464
|
syncedPeers.push(peer);
|
|
470
465
|
}
|
|
471
|
-
else if (peer.
|
|
466
|
+
else if (peer.role === "server" &&
|
|
472
467
|
!peer.loadRequestSent.has(coValue.id)) {
|
|
473
468
|
const state = coValue.getStateForPeer(peer.id)?.type;
|
|
474
469
|
// Check if there is a inflight load operation and we
|
|
@@ -478,7 +473,7 @@ export class SyncManager {
|
|
|
478
473
|
// before sending the new content
|
|
479
474
|
this.trySendToPeer(peer, {
|
|
480
475
|
action: "load",
|
|
481
|
-
...coValue.
|
|
476
|
+
...coValue.knownStateWithStreaming(),
|
|
482
477
|
});
|
|
483
478
|
peer.trackLoadRequestSent(coValue.id);
|
|
484
479
|
syncedPeers.push(peer);
|
|
@@ -493,7 +488,6 @@ export class SyncManager {
|
|
|
493
488
|
peer.setKnownState(msg.id, knownStateIn(msg));
|
|
494
489
|
return this.sendNewContentIncludingDependencies(msg.id, peer);
|
|
495
490
|
}
|
|
496
|
-
handleUnsubscribe(_msg) { }
|
|
497
491
|
requestCoValueSync(coValue) {
|
|
498
492
|
if (this.requestedSyncs.has(coValue.id)) {
|
|
499
493
|
return;
|
|
@@ -505,8 +499,33 @@ export class SyncManager {
|
|
|
505
499
|
});
|
|
506
500
|
this.requestedSyncs.add(coValue.id);
|
|
507
501
|
}
|
|
502
|
+
storeCoValue(coValue, data) {
|
|
503
|
+
const storage = this.local.storage;
|
|
504
|
+
if (!storage || !data)
|
|
505
|
+
return;
|
|
506
|
+
// Try to store the content as-is for performance
|
|
507
|
+
// In case that some transactions are missing, a correction will be requested, but it's an edge case
|
|
508
|
+
storage.store(data, (correction) => {
|
|
509
|
+
if (!coValue.hasVerifiedContent())
|
|
510
|
+
return;
|
|
511
|
+
const newContentPieces = coValue.verified.newContentSince(correction);
|
|
512
|
+
if (!newContentPieces)
|
|
513
|
+
return;
|
|
514
|
+
storage.store(newContentPieces, (response) => {
|
|
515
|
+
logger.error("Correction requested by storage after sending a correction content", {
|
|
516
|
+
response,
|
|
517
|
+
knownState: coValue.knownState(),
|
|
518
|
+
});
|
|
519
|
+
});
|
|
520
|
+
});
|
|
521
|
+
}
|
|
508
522
|
syncCoValue(coValue) {
|
|
509
523
|
this.requestedSyncs.delete(coValue.id);
|
|
524
|
+
if (this.local.storage && coValue.hasVerifiedContent()) {
|
|
525
|
+
const knownState = this.local.storage.getKnownState(coValue.id);
|
|
526
|
+
const newContentPieces = coValue.verified.newContentSince(knownState);
|
|
527
|
+
this.storeCoValue(coValue, newContentPieces);
|
|
528
|
+
}
|
|
510
529
|
for (const peer of this.peersInPriorityOrder()) {
|
|
511
530
|
if (peer.closed)
|
|
512
531
|
continue;
|
|
@@ -554,15 +573,14 @@ export class SyncManager {
|
|
|
554
573
|
}, timeout);
|
|
555
574
|
});
|
|
556
575
|
}
|
|
557
|
-
waitForStorageSync(id
|
|
558
|
-
|
|
559
|
-
return Promise.all(peers
|
|
560
|
-
.filter((peer) => peer.role === "storage")
|
|
561
|
-
.map((peer) => this.waitForSyncWithPeer(peer.id, id, timeout)));
|
|
576
|
+
waitForStorageSync(id) {
|
|
577
|
+
return this.local.storage?.waitForSync(id, this.local.getCoValue(id));
|
|
562
578
|
}
|
|
563
579
|
waitForSync(id, timeout = 30000) {
|
|
564
580
|
const peers = this.getPeers();
|
|
565
|
-
return Promise.all(peers
|
|
581
|
+
return Promise.all(peers
|
|
582
|
+
.map((peer) => this.waitForSyncWithPeer(peer.id, id, timeout))
|
|
583
|
+
.concat(this.waitForStorageSync(id)));
|
|
566
584
|
}
|
|
567
585
|
waitForAllCoValuesSync(timeout = 60000) {
|
|
568
586
|
const coValues = this.local.allCoValues();
|