cojson 0.7.11 → 0.7.14
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 +2 -2
- package/.turbo/turbo-test.log +401 -421
- package/CHANGELOG.md +6 -0
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/storage/index.js +22 -30
- package/dist/storage/index.js.map +1 -1
- package/dist/streamUtils.js +27 -105
- package/dist/streamUtils.js.map +1 -1
- package/dist/sync.js +69 -85
- package/dist/sync.js.map +1 -1
- package/dist/tests/account.test.js +4 -2
- package/dist/tests/account.test.js.map +1 -1
- package/dist/tests/sync.test.js +286 -239
- package/dist/tests/sync.test.js.map +1 -1
- package/package.json +2 -3
- package/src/index.ts +18 -2
- package/src/storage/index.ts +37 -67
- package/src/streamUtils.ts +46 -156
- package/src/sync.ts +125 -118
- package/src/tests/account.test.ts +5 -2
- package/src/tests/sync.test.ts +798 -732
package/CHANGELOG.md
CHANGED
package/dist/index.js
CHANGED
|
@@ -16,6 +16,7 @@ import { parseJSON } from "./jsonStringify.js";
|
|
|
16
16
|
import { RawAccount, RawProfile, accountHeaderForInitialAgentSecret, } from "./coValues/account.js";
|
|
17
17
|
import { expectGroup } from "./typeUtils/expectGroup.js";
|
|
18
18
|
import { isAccountID } from "./typeUtils/isAccountID.js";
|
|
19
|
+
import { DisconnectedError, PingTimeoutError } from "./sync.js";
|
|
19
20
|
import { LSMStorage, } from "./storage/index.js";
|
|
20
21
|
/** @hidden */
|
|
21
22
|
export const cojsonInternals = {
|
|
@@ -35,5 +36,5 @@ export const cojsonInternals = {
|
|
|
35
36
|
idforHeader,
|
|
36
37
|
StreamingHash,
|
|
37
38
|
};
|
|
38
|
-
export { LocalNode, RawGroup, EVERYONE, RawCoMap, RawCoList, RawCoStream, RawBinaryCoStream, RawAccount, RawProfile as Profile, CoValueCore, ControlledAgent, RawControlledAccount, MAX_RECOMMENDED_TX_SIZE, CryptoProvider, WasmCrypto, PureJSCrypto, isRawCoID, LSMStorage, };
|
|
39
|
+
export { LocalNode, RawGroup, EVERYONE, RawCoMap, RawCoList, RawCoStream, RawBinaryCoStream, RawAccount, RawProfile as Profile, CoValueCore, ControlledAgent, RawControlledAccount, MAX_RECOMMENDED_TX_SIZE, CryptoProvider, WasmCrypto, PureJSCrypto, isRawCoID, LSMStorage, DisconnectedError, PingTimeoutError, };
|
|
39
40
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACH,WAAW,EACX,kBAAkB,EAClB,uBAAuB,EACvB,WAAW,GACd,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,6BAA6B,EAAE,MAAM,8CAA8C,CAAC;AAC7F,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAE3C,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAC/C,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACjD,OAAO,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AACxE,OAAO,EACH,gBAAgB,EAChB,eAAe,EACf,aAAa,EACb,cAAc,GACjB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AACpD,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AACxD,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,eAAe,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAE9E,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AACvE,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAEzD,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AACpE,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC/C,OAAO,EACH,UAAU,EACV,UAAU,EACV,kCAAkC,GACrC,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AACzD,OAAO,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACH,WAAW,EACX,kBAAkB,EAClB,uBAAuB,EACvB,WAAW,GACd,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,6BAA6B,EAAE,MAAM,8CAA8C,CAAC;AAC7F,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAE3C,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAC/C,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACjD,OAAO,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AACxE,OAAO,EACH,gBAAgB,EAChB,eAAe,EACf,aAAa,EACb,cAAc,GACjB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AACpD,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AACxD,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,eAAe,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAE9E,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AACvE,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAEzD,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AACpE,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC/C,OAAO,EACH,UAAU,EACV,UAAU,EACV,kCAAkC,GACrC,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AACzD,OAAO,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AAezD,OAAO,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAYhE,OAAO,EACH,UAAU,GAIb,MAAM,oBAAoB,CAAC;AAG5B,cAAc;AACd,MAAM,CAAC,MAAM,eAAe,GAAG;IAC3B,kBAAkB;IAClB,cAAc;IACd,cAAc;IACd,gBAAgB;IAChB,gBAAgB;IAChB,eAAe;IACf,WAAW;IACX,gBAAgB;IAChB,gBAAgB;IAChB,SAAS;IACT,6BAA6B;IAC7B,WAAW;IACX,kCAAkC;IAClC,WAAW;IACX,aAAa;CAChB,CAAC;AAEF,OAAO,EACH,SAAS,EACT,QAAQ,EAER,QAAQ,EAER,QAAQ,EACR,SAAS,EACT,WAAW,EACX,iBAAiB,EAIjB,UAAU,EAIV,UAAU,IAAI,OAAO,EAGrB,WAAW,EACX,eAAe,EACf,oBAAoB,EACpB,uBAAuB,EAQvB,cAAc,EACd,UAAU,EACV,YAAY,EAEZ,SAAS,EACT,UAAU,EACV,iBAAiB,EACjB,gBAAgB,GACnB,CAAC"}
|
package/dist/storage/index.js
CHANGED
|
@@ -1,34 +1,26 @@
|
|
|
1
|
-
import { Effect, Either, SynchronizedRef } from "effect";
|
|
1
|
+
import { Effect, Either, Queue, Stream, SynchronizedRef } from "effect";
|
|
2
2
|
import { connectedPeers } from "../streamUtils.js";
|
|
3
3
|
import { chunkToKnownState, contentSinceChunk, mergeChunks, } from "./chunksAndKnownStates.js";
|
|
4
4
|
import { readChunk, readHeader, textDecoder, writeBlock, writeToWal, } from "./FileSystem.js";
|
|
5
5
|
export class LSMStorage {
|
|
6
6
|
constructor(fs, fromLocalNode, toLocalNode) {
|
|
7
|
-
this.headerCache = new Map();
|
|
8
7
|
this.fs = fs;
|
|
9
|
-
this.fromLocalNode = fromLocalNode
|
|
10
|
-
this.toLocalNode = toLocalNode
|
|
8
|
+
this.fromLocalNode = fromLocalNode;
|
|
9
|
+
this.toLocalNode = toLocalNode;
|
|
10
|
+
this.headerCache = new Map();
|
|
11
11
|
this.coValues = SynchronizedRef.unsafeMake({});
|
|
12
12
|
this.currentWal = SynchronizedRef.unsafeMake(undefined);
|
|
13
|
-
void
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
const result = yield* Effect.promise(() => this.fromLocalNode.read());
|
|
17
|
-
done = result.done;
|
|
18
|
-
if (result.value) {
|
|
19
|
-
if (result.value.action === "done") {
|
|
20
|
-
continue;
|
|
21
|
-
}
|
|
22
|
-
if (result.value.action === "content") {
|
|
23
|
-
yield* this.handleNewContent(result.value);
|
|
24
|
-
}
|
|
25
|
-
else {
|
|
26
|
-
yield* this.sendNewContent(result.value.id, result.value, undefined);
|
|
27
|
-
}
|
|
28
|
-
}
|
|
13
|
+
void this.fromLocalNode.pipe(Stream.runForEach((msg) => Effect.gen(this, function* () {
|
|
14
|
+
if (msg.action === "done") {
|
|
15
|
+
return;
|
|
29
16
|
}
|
|
30
|
-
|
|
31
|
-
|
|
17
|
+
if (msg.action === "content") {
|
|
18
|
+
yield* this.handleNewContent(msg);
|
|
19
|
+
}
|
|
20
|
+
else {
|
|
21
|
+
yield* this.sendNewContent(msg.id, msg, undefined);
|
|
22
|
+
}
|
|
23
|
+
})), Effect.runPromise);
|
|
32
24
|
setTimeout(() => this.compact(), 20000);
|
|
33
25
|
}
|
|
34
26
|
sendNewContent(id, known, asDependencyOf) {
|
|
@@ -41,13 +33,13 @@ export class LSMStorage {
|
|
|
41
33
|
coValue = yield* this.loadCoValue(id, this.fs);
|
|
42
34
|
}
|
|
43
35
|
if (!coValue) {
|
|
44
|
-
yield*
|
|
36
|
+
yield* Queue.offer(this.toLocalNode, {
|
|
45
37
|
id: id,
|
|
46
38
|
action: "known",
|
|
47
39
|
header: false,
|
|
48
40
|
sessions: {},
|
|
49
41
|
asDependencyOf,
|
|
50
|
-
})
|
|
42
|
+
});
|
|
51
43
|
return coValues;
|
|
52
44
|
}
|
|
53
45
|
if (!known?.header &&
|
|
@@ -78,15 +70,15 @@ export class LSMStorage {
|
|
|
78
70
|
}
|
|
79
71
|
const newContentMessages = contentSinceChunk(id, coValue, known).map((message) => ({ ...message, asDependencyOf }));
|
|
80
72
|
const ourKnown = chunkToKnownState(id, coValue);
|
|
81
|
-
yield*
|
|
73
|
+
yield* Queue.offer(this.toLocalNode, {
|
|
82
74
|
action: "known",
|
|
83
75
|
...ourKnown,
|
|
84
76
|
asDependencyOf,
|
|
85
|
-
})
|
|
77
|
+
});
|
|
86
78
|
for (const message of newContentMessages) {
|
|
87
79
|
if (Object.keys(message.new).length === 0)
|
|
88
80
|
continue;
|
|
89
|
-
yield*
|
|
81
|
+
yield* Queue.offer(this.toLocalNode, message);
|
|
90
82
|
}
|
|
91
83
|
return { ...coValues, [id]: coValue };
|
|
92
84
|
});
|
|
@@ -251,12 +243,12 @@ export class LSMStorage {
|
|
|
251
243
|
}));
|
|
252
244
|
setTimeout(() => this.compact(), 5000);
|
|
253
245
|
}
|
|
254
|
-
static asPeer({ fs, trace, localNodeName = "local", }) {
|
|
255
|
-
const [localNodeAsPeer, storageAsPeer] = connectedPeers(localNodeName, "storage", {
|
|
246
|
+
static async asPeer({ fs, trace, localNodeName = "local", }) {
|
|
247
|
+
const [localNodeAsPeer, storageAsPeer] = await Effect.runPromise(connectedPeers(localNodeName, "storage", {
|
|
256
248
|
peer1role: "client",
|
|
257
249
|
peer2role: "server",
|
|
258
250
|
trace,
|
|
259
|
-
});
|
|
251
|
+
}));
|
|
260
252
|
new LSMStorage(fs, localNodeAsPeer.incoming, localNodeAsPeer.outgoing);
|
|
261
253
|
// return { ...storageAsPeer, priority: 200 };
|
|
262
254
|
return storageAsPeer;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/storage/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/storage/index.ts"],"names":[],"mappings":"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"}
|
package/dist/streamUtils.js
CHANGED
|
@@ -1,113 +1,35 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Console, Effect, Queue, Stream } from "effect";
|
|
2
2
|
export function connectedPeers(peer1id, peer2id, { trace = false, peer1role = "peer", peer2role = "peer", } = {}) {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
.pipeThrough(new TransformStream({
|
|
20
|
-
transform(chunk, controller) {
|
|
21
|
-
trace &&
|
|
22
|
-
console.debug(`${peer1id} -> ${peer2id}`, JSON.stringify(chunk, (k, v) => k === "changes" || k === "encryptedChanges"
|
|
23
|
-
? v.slice(0, 20) + "..."
|
|
24
|
-
: v, 2));
|
|
25
|
-
controller.enqueue(chunk);
|
|
26
|
-
},
|
|
27
|
-
}))
|
|
28
|
-
.pipeTo(inTx2);
|
|
29
|
-
const peer2AsPeer = {
|
|
30
|
-
id: peer2id,
|
|
31
|
-
incoming: inRx1,
|
|
32
|
-
outgoing: outTx1,
|
|
33
|
-
role: peer2role,
|
|
34
|
-
};
|
|
35
|
-
const peer1AsPeer = {
|
|
36
|
-
id: peer1id,
|
|
37
|
-
incoming: inRx2,
|
|
38
|
-
outgoing: outTx2,
|
|
39
|
-
role: peer1role,
|
|
40
|
-
};
|
|
41
|
-
return [peer1AsPeer, peer2AsPeer];
|
|
42
|
-
}
|
|
43
|
-
export function newStreamPair(pairName) {
|
|
44
|
-
let queueLength = 0;
|
|
45
|
-
let readerClosed = false;
|
|
46
|
-
let resolveEnqueue;
|
|
47
|
-
const enqueuePromise = new Promise((resolve) => {
|
|
48
|
-
resolveEnqueue = resolve;
|
|
3
|
+
return Effect.gen(function* () {
|
|
4
|
+
const [from1to2Rx, from1to2Tx] = yield* newQueuePair(trace ? { traceAs: `${peer1id} -> ${peer2id}` } : undefined);
|
|
5
|
+
const [from2to1Rx, from2to1Tx] = yield* newQueuePair(trace ? { traceAs: `${peer2id} -> ${peer1id}` } : undefined);
|
|
6
|
+
const peer2AsPeer = {
|
|
7
|
+
id: peer2id,
|
|
8
|
+
incoming: from2to1Rx,
|
|
9
|
+
outgoing: from1to2Tx,
|
|
10
|
+
role: peer2role,
|
|
11
|
+
};
|
|
12
|
+
const peer1AsPeer = {
|
|
13
|
+
id: peer1id,
|
|
14
|
+
incoming: from1to2Rx,
|
|
15
|
+
outgoing: from2to1Tx,
|
|
16
|
+
role: peer1role,
|
|
17
|
+
};
|
|
18
|
+
return [peer1AsPeer, peer2AsPeer];
|
|
49
19
|
});
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
console.warn(pairName, "overflowing queue length", queueLength);
|
|
60
|
-
}
|
|
20
|
+
}
|
|
21
|
+
export function newQueuePair(options = {}) {
|
|
22
|
+
return Effect.gen(function* () {
|
|
23
|
+
const queue = yield* Queue.unbounded();
|
|
24
|
+
if (options.traceAs) {
|
|
25
|
+
return [Stream.fromQueue(queue).pipe(Stream.tap((msg) => Console.debug(options.traceAs, JSON.stringify(msg, (k, v) => k === "changes" ||
|
|
26
|
+
k === "encryptedChanges"
|
|
27
|
+
? v.slice(0, 20) + "..."
|
|
28
|
+
: v, 2)))), queue];
|
|
61
29
|
}
|
|
62
30
|
else {
|
|
63
|
-
|
|
64
|
-
console.debug(pairName, "ok queue length", queueLength);
|
|
65
|
-
queueWasOverflowing = false;
|
|
66
|
-
}
|
|
31
|
+
return [Stream.fromQueue(queue), queue];
|
|
67
32
|
}
|
|
68
|
-
}
|
|
69
|
-
const readable = new ReadableStream({
|
|
70
|
-
async start(controller) {
|
|
71
|
-
resolveEnqueue(controller.enqueue.bind(controller));
|
|
72
|
-
resolveClose(controller.close.bind(controller));
|
|
73
|
-
},
|
|
74
|
-
cancel(_reason) {
|
|
75
|
-
console.log("Manually closing reader");
|
|
76
|
-
readerClosed = true;
|
|
77
|
-
},
|
|
78
|
-
}).pipeThrough(
|
|
79
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
80
|
-
new TransformStream({
|
|
81
|
-
transform(chunk, controller) {
|
|
82
|
-
queueLength -= 1;
|
|
83
|
-
maybeReportQueueLength();
|
|
84
|
-
controller.enqueue(chunk);
|
|
85
|
-
},
|
|
86
|
-
}));
|
|
87
|
-
let lastWritePromise = Promise.resolve();
|
|
88
|
-
const writable = new WritableStream({
|
|
89
|
-
async write(chunk) {
|
|
90
|
-
queueLength += 1;
|
|
91
|
-
maybeReportQueueLength();
|
|
92
|
-
const enqueue = await enqueuePromise;
|
|
93
|
-
if (readerClosed) {
|
|
94
|
-
throw new Error("Reader closed");
|
|
95
|
-
}
|
|
96
|
-
else {
|
|
97
|
-
// make sure write resolves before corresponding read, but make sure writes are still in order
|
|
98
|
-
await lastWritePromise;
|
|
99
|
-
lastWritePromise = new Promise((resolve) => {
|
|
100
|
-
enqueue(chunk);
|
|
101
|
-
resolve();
|
|
102
|
-
});
|
|
103
|
-
}
|
|
104
|
-
},
|
|
105
|
-
async abort(reason) {
|
|
106
|
-
console.debug("Manually closing writer", reason);
|
|
107
|
-
const close = await closePromise;
|
|
108
|
-
close();
|
|
109
|
-
},
|
|
110
33
|
});
|
|
111
|
-
return [readable, writable];
|
|
112
34
|
}
|
|
113
35
|
//# 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":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"streamUtils.js","sourceRoot":"","sources":["../src/streamUtils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAGxD,MAAM,UAAU,cAAc,CAC1B,OAAe,EACf,OAAe,EACf,EACI,KAAK,GAAG,KAAK,EACb,SAAS,GAAG,MAAM,EAClB,SAAS,GAAG,MAAM,MAKlB,EAAE;IAEN,OAAO,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;QACvB,MAAM,CAAC,UAAU,EAAE,UAAU,CAAC,GAAG,KAAK,CAAC,CAAC,YAAY,CAChD,KAAK,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,GAAG,OAAO,OAAO,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,CAC9D,CAAC;QACF,MAAM,CAAC,UAAU,EAAE,UAAU,CAAC,GAAG,KAAK,CAAC,CAAC,YAAY,CAChD,KAAK,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,GAAG,OAAO,OAAO,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,CAC9D,CAAC;QAEF,MAAM,WAAW,GAAS;YACtB,EAAE,EAAE,OAAO;YACX,QAAQ,EAAE,UAAU;YACpB,QAAQ,EAAE,UAAU;YACpB,IAAI,EAAE,SAAS;SAClB,CAAC;QAEF,MAAM,WAAW,GAAS;YACtB,EAAE,EAAE,OAAO;YACX,QAAQ,EAAE,UAAU;YACpB,QAAQ,EAAE,UAAU;YACpB,IAAI,EAAE,SAAS;SAClB,CAAC;QAEF,OAAO,CAAC,WAAW,EAAE,WAAW,CAAC,CAAC;IACtC,CAAC,CAAC,CAAC;AACP,CAAC;AAED,MAAM,UAAU,YAAY,CACxB,UAAgC,EAAE;IAElC,OAAO,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;QACvB,MAAM,KAAK,GAAG,KAAK,CAAC,CAAC,KAAK,CAAC,SAAS,EAAe,CAAC;QAEpD,IAAI,OAAO,CAAC,OAAO,EAAE;YACjB,OAAO,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,CAClE,OAAO,CAAC,OAAO,EACf,IAAI,CAAC,SAAS,CACV,GAAG,EACH,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CACL,CAAC,KAAK,SAAS;oBACf,CAAC,KAAK,kBAAkB;oBACpB,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,KAAK;oBACxB,CAAC,CAAC,CAAC,EACX,CAAC,CACJ,CACJ,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;SACf;aAAM;YACH,OAAO,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,KAAK,CAAC,CAAC;SAC3C;IACL,CAAC,CAAC,CAAC;AACP,CAAC"}
|
package/dist/sync.js
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { CoValueCore } from "./coValueCore.js";
|
|
2
|
+
import { newLoadingState } from "./localNode.js";
|
|
3
|
+
import { Effect, Queue, Stream } from "effect";
|
|
2
4
|
export function emptyKnownState(id) {
|
|
3
5
|
return {
|
|
4
6
|
id,
|
|
@@ -6,6 +8,19 @@ export function emptyKnownState(id) {
|
|
|
6
8
|
sessions: {},
|
|
7
9
|
};
|
|
8
10
|
}
|
|
11
|
+
export class DisconnectedError extends Error {
|
|
12
|
+
constructor(message) {
|
|
13
|
+
super(message);
|
|
14
|
+
this.message = message;
|
|
15
|
+
this._tag = "DisconnectedError";
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
export class PingTimeoutError extends Error {
|
|
19
|
+
constructor() {
|
|
20
|
+
super(...arguments);
|
|
21
|
+
this._tag = "PingTimeoutError";
|
|
22
|
+
}
|
|
23
|
+
}
|
|
9
24
|
export function combinedKnownStates(stateA, stateB) {
|
|
10
25
|
const sessionStates = {};
|
|
11
26
|
const allSessions = new Set([
|
|
@@ -36,23 +51,16 @@ export class SyncManager {
|
|
|
36
51
|
return bPriority - aPriority;
|
|
37
52
|
});
|
|
38
53
|
}
|
|
39
|
-
async loadFromPeers(id,
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
continue;
|
|
43
|
-
}
|
|
44
|
-
if (peer.role !== "server") {
|
|
45
|
-
continue;
|
|
46
|
-
}
|
|
54
|
+
async loadFromPeers(id, forPeer) {
|
|
55
|
+
const eligiblePeers = this.peersInPriorityOrder().filter((peer) => peer.id !== forPeer && peer.role === "server");
|
|
56
|
+
for (const peer of eligiblePeers) {
|
|
47
57
|
// console.log("loading", id, "from", peer.id);
|
|
48
|
-
peer.outgoing
|
|
49
|
-
.write({
|
|
58
|
+
Effect.runPromise(Queue.offer(peer.outgoing, {
|
|
50
59
|
action: "load",
|
|
51
60
|
id: id,
|
|
52
61
|
header: false,
|
|
53
62
|
sessions: {},
|
|
54
|
-
})
|
|
55
|
-
.catch((e) => {
|
|
63
|
+
})).catch((e) => {
|
|
56
64
|
console.error("Error writing to peer", e);
|
|
57
65
|
});
|
|
58
66
|
const coValueEntry = this.local.coValues[id];
|
|
@@ -162,7 +170,9 @@ export class SyncManager {
|
|
|
162
170
|
let lastYield = performance.now();
|
|
163
171
|
for (const [_i, piece] of newContentPieces.entries()) {
|
|
164
172
|
// console.log(
|
|
165
|
-
// `${id} -> ${peer.id}: Sending content piece ${i + 1}/${
|
|
173
|
+
// `${id} -> ${peer.id}: Sending content piece ${i + 1}/${
|
|
174
|
+
// newContentPieces.length
|
|
175
|
+
// } header: ${!!piece.header}`,
|
|
166
176
|
// // Object.values(piece.new).map((s) => s.newTransactions)
|
|
167
177
|
// );
|
|
168
178
|
await this.trySendToPeer(peer, piece);
|
|
@@ -187,7 +197,7 @@ export class SyncManager {
|
|
|
187
197
|
id: peer.id,
|
|
188
198
|
optimisticKnownStates: {},
|
|
189
199
|
incoming: peer.incoming,
|
|
190
|
-
outgoing: peer.outgoing
|
|
200
|
+
outgoing: peer.outgoing,
|
|
191
201
|
toldKnownState: new Set(),
|
|
192
202
|
role: peer.role,
|
|
193
203
|
delayOnError: peer.delayOnError,
|
|
@@ -208,89 +218,63 @@ export class SyncManager {
|
|
|
208
218
|
};
|
|
209
219
|
void initialSync();
|
|
210
220
|
}
|
|
211
|
-
|
|
212
|
-
try {
|
|
213
|
-
for await (const msg of peerState.incoming) {
|
|
214
|
-
try {
|
|
215
|
-
// await this.handleSyncMessage(msg, peerState);
|
|
216
|
-
this.handleSyncMessage(msg, peerState).catch((e) => {
|
|
217
|
-
console.error(new Date(), `Error reading from peer ${peer.id}, handling msg`, JSON.stringify(msg, (k, v) => k === "changes" || k === "encryptedChanges"
|
|
218
|
-
? v.slice(0, 20) + "..."
|
|
219
|
-
: v), e);
|
|
220
|
-
});
|
|
221
|
-
// await new Promise<void>((resolve) => {
|
|
222
|
-
// setTimeout(resolve, 0);
|
|
223
|
-
// });
|
|
224
|
-
}
|
|
225
|
-
catch (e) {
|
|
226
|
-
console.error(new Date(), `Error reading from peer ${peer.id}, handling msg`, JSON.stringify(msg, (k, v) => k === "changes" || k === "encryptedChanges"
|
|
227
|
-
? v.slice(0, 20) + "..."
|
|
228
|
-
: v), e);
|
|
229
|
-
if (peerState.delayOnError) {
|
|
230
|
-
await new Promise((resolve) => {
|
|
231
|
-
setTimeout(resolve, peerState.delayOnError);
|
|
232
|
-
});
|
|
233
|
-
}
|
|
234
|
-
}
|
|
235
|
-
}
|
|
236
|
-
}
|
|
237
|
-
catch (e) {
|
|
238
|
-
console.error(`Error reading from peer ${peer.id}`, e);
|
|
239
|
-
}
|
|
221
|
+
void Effect.runPromise(peerState.incoming.pipe(Stream.ensuring(Effect.sync(() => {
|
|
240
222
|
console.log("Peer disconnected:", peer.id);
|
|
241
223
|
delete this.peers[peer.id];
|
|
242
|
-
}
|
|
243
|
-
|
|
224
|
+
})), Stream.runForEach((msg) => Effect.tryPromise({
|
|
225
|
+
try: () => this.handleSyncMessage(msg, peerState),
|
|
226
|
+
catch: (e) => new Error(`Error reading from peer ${peer.id}, handling msg\n\n${JSON.stringify(msg, (k, v) => k === "changes" ||
|
|
227
|
+
k === "encryptedChanges"
|
|
228
|
+
? v.slice(0, 20) + "..."
|
|
229
|
+
: v)}`, { cause: e }),
|
|
230
|
+
}).pipe(Effect.timeoutFail({
|
|
231
|
+
duration: 10000,
|
|
232
|
+
onTimeout: () => new Error("Took >10s to process message"),
|
|
233
|
+
}))), Effect.catchAll((e) => Effect.logError("Error in peer", peer.id, e.message, typeof e.cause === "object" &&
|
|
234
|
+
e.cause instanceof Error &&
|
|
235
|
+
e.cause.message))));
|
|
244
236
|
}
|
|
245
237
|
trySendToPeer(peer, msg) {
|
|
246
|
-
|
|
247
|
-
// already disconnected, return to drain potential queue
|
|
248
|
-
return Promise.resolve();
|
|
249
|
-
}
|
|
250
|
-
return new Promise((resolve) => {
|
|
251
|
-
const start = Date.now();
|
|
252
|
-
peer.outgoing
|
|
253
|
-
.write(msg)
|
|
254
|
-
.then(() => {
|
|
255
|
-
const end = Date.now();
|
|
256
|
-
if (end - start > 1000) {
|
|
257
|
-
// console.error(
|
|
258
|
-
// new Error(
|
|
259
|
-
// `Writing to peer "${peer.id}" took ${
|
|
260
|
-
// Math.round((Date.now() - start) / 100) / 10
|
|
261
|
-
// }s - this should never happen as write should resolve quickly or error`
|
|
262
|
-
// )
|
|
263
|
-
// );
|
|
264
|
-
}
|
|
265
|
-
else {
|
|
266
|
-
resolve();
|
|
267
|
-
}
|
|
268
|
-
})
|
|
269
|
-
.catch((e) => {
|
|
270
|
-
console.error(new Error(`Error writing to peer ${peer.id}, disconnecting`, {
|
|
271
|
-
cause: e,
|
|
272
|
-
}));
|
|
273
|
-
delete this.peers[peer.id];
|
|
274
|
-
});
|
|
275
|
-
});
|
|
238
|
+
return Effect.runPromise(Queue.offer(peer.outgoing, msg));
|
|
276
239
|
}
|
|
277
240
|
async handleLoad(msg, peer) {
|
|
278
241
|
peer.optimisticKnownStates[msg.id] = knownStateIn(msg);
|
|
279
242
|
let entry = this.local.coValues[msg.id];
|
|
280
243
|
if (!entry) {
|
|
281
244
|
// console.log(`Loading ${msg.id} from all peers except ${peer.id}`);
|
|
282
|
-
this
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
245
|
+
// special case: we should be able to solve this much more neatly
|
|
246
|
+
// with an explicit state machine in the future
|
|
247
|
+
const eligiblePeers = this.peersInPriorityOrder().filter((other) => other.id !== peer.id && peer.role === "server");
|
|
248
|
+
if (eligiblePeers.length === 0) {
|
|
249
|
+
if (msg.header || Object.keys(msg.sessions).length > 0) {
|
|
250
|
+
this.local.coValues[msg.id] = newLoadingState(new Set([peer.id]));
|
|
251
|
+
this.trySendToPeer(peer, {
|
|
252
|
+
action: "known",
|
|
253
|
+
id: msg.id,
|
|
254
|
+
header: false,
|
|
255
|
+
sessions: {},
|
|
256
|
+
}).catch((e) => {
|
|
257
|
+
console.error("Error sending known state back", e);
|
|
258
|
+
});
|
|
259
|
+
}
|
|
260
|
+
return;
|
|
261
|
+
}
|
|
262
|
+
else {
|
|
263
|
+
this.local
|
|
264
|
+
.loadCoValueCore(msg.id, {
|
|
265
|
+
dontLoadFrom: peer.id,
|
|
266
|
+
dontWaitFor: peer.id,
|
|
267
|
+
})
|
|
268
|
+
.catch((e) => {
|
|
269
|
+
console.error("Error loading coValue in handleLoad", e);
|
|
270
|
+
});
|
|
271
|
+
}
|
|
290
272
|
entry = this.local.coValues[msg.id];
|
|
291
273
|
}
|
|
292
274
|
if (entry.state === "loading") {
|
|
275
|
+
console.log("Waiting for loaded", msg.id, "after message from", peer.id);
|
|
293
276
|
const loaded = await entry.done;
|
|
277
|
+
console.log("Loaded", msg.id, loaded);
|
|
294
278
|
if (loaded === "unavailable") {
|
|
295
279
|
peer.optimisticKnownStates[msg.id] = knownStateIn(msg);
|
|
296
280
|
peer.toldKnownState.add(msg.id);
|
|
@@ -324,7 +308,7 @@ export class SyncManager {
|
|
|
324
308
|
}
|
|
325
309
|
}
|
|
326
310
|
else {
|
|
327
|
-
throw new Error(
|
|
311
|
+
throw new Error(`Expected coValue entry for ${msg.id} to be created on known state, missing subscribe?`);
|
|
328
312
|
}
|
|
329
313
|
}
|
|
330
314
|
if (entry.state === "loading") {
|
|
@@ -355,7 +339,7 @@ export class SyncManager {
|
|
|
355
339
|
async handleNewContent(msg, peer) {
|
|
356
340
|
let entry = this.local.coValues[msg.id];
|
|
357
341
|
if (!entry) {
|
|
358
|
-
throw new Error(
|
|
342
|
+
throw new Error(`Expected coValue entry for ${msg.id} to be created on new content, missing subscribe?`);
|
|
359
343
|
}
|
|
360
344
|
let resolveAfterDone;
|
|
361
345
|
const peerOptimisticKnownState = peer.optimisticKnownStates[msg.id];
|