cojson 0.7.11 → 0.7.17
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 +12 -0
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/storage/FileSystem.js +9 -3
- package/dist/storage/FileSystem.js.map +1 -1
- package/dist/storage/chunksAndKnownStates.js +2 -0
- package/dist/storage/chunksAndKnownStates.js.map +1 -1
- package/dist/storage/index.js +38 -36
- 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/FileSystem.ts +9 -8
- package/src/storage/chunksAndKnownStates.ts +2 -0
- package/src/storage/index.ts +64 -73
- 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/src/streamUtils.ts
CHANGED
|
@@ -1,8 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
ReadableStream,
|
|
3
|
-
TransformStream,
|
|
4
|
-
WritableStream,
|
|
5
|
-
} from "isomorphic-streams";
|
|
1
|
+
import { Console, Effect, Queue, Stream } from "effect";
|
|
6
2
|
import { Peer, PeerID, SyncMessage } from "./sync.js";
|
|
7
3
|
|
|
8
4
|
export function connectedPeers(
|
|
@@ -17,160 +13,54 @@ export function connectedPeers(
|
|
|
17
13
|
peer1role?: Peer["role"];
|
|
18
14
|
peer2role?: Peer["role"];
|
|
19
15
|
} = {},
|
|
20
|
-
): [Peer, Peer] {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
),
|
|
45
|
-
);
|
|
46
|
-
controller.enqueue(chunk);
|
|
47
|
-
},
|
|
48
|
-
}),
|
|
49
|
-
)
|
|
50
|
-
.pipeTo(inTx1);
|
|
51
|
-
|
|
52
|
-
void outRx1
|
|
53
|
-
.pipeThrough(
|
|
54
|
-
new TransformStream({
|
|
55
|
-
transform(
|
|
56
|
-
chunk: SyncMessage,
|
|
57
|
-
controller: { enqueue: (msg: SyncMessage) => void },
|
|
58
|
-
) {
|
|
59
|
-
trace &&
|
|
60
|
-
console.debug(
|
|
61
|
-
`${peer1id} -> ${peer2id}`,
|
|
62
|
-
JSON.stringify(
|
|
63
|
-
chunk,
|
|
64
|
-
(k, v) =>
|
|
65
|
-
k === "changes" || k === "encryptedChanges"
|
|
66
|
-
? v.slice(0, 20) + "..."
|
|
67
|
-
: v,
|
|
68
|
-
2,
|
|
69
|
-
),
|
|
70
|
-
);
|
|
71
|
-
controller.enqueue(chunk);
|
|
72
|
-
},
|
|
73
|
-
}),
|
|
74
|
-
)
|
|
75
|
-
.pipeTo(inTx2);
|
|
76
|
-
|
|
77
|
-
const peer2AsPeer: Peer = {
|
|
78
|
-
id: peer2id,
|
|
79
|
-
incoming: inRx1,
|
|
80
|
-
outgoing: outTx1,
|
|
81
|
-
role: peer2role,
|
|
82
|
-
};
|
|
83
|
-
|
|
84
|
-
const peer1AsPeer: Peer = {
|
|
85
|
-
id: peer1id,
|
|
86
|
-
incoming: inRx2,
|
|
87
|
-
outgoing: outTx2,
|
|
88
|
-
role: peer1role,
|
|
89
|
-
};
|
|
90
|
-
|
|
91
|
-
return [peer1AsPeer, peer2AsPeer];
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
export function newStreamPair<T>(
|
|
95
|
-
pairName?: string,
|
|
96
|
-
): [ReadableStream<T>, WritableStream<T>] {
|
|
97
|
-
let queueLength = 0;
|
|
98
|
-
let readerClosed = false;
|
|
99
|
-
|
|
100
|
-
let resolveEnqueue: (enqueue: (item: T) => void) => void;
|
|
101
|
-
const enqueuePromise = new Promise<(item: T) => void>((resolve) => {
|
|
102
|
-
resolveEnqueue = resolve;
|
|
16
|
+
): Effect.Effect<[Peer, Peer]> {
|
|
17
|
+
return Effect.gen(function* () {
|
|
18
|
+
const [from1to2Rx, from1to2Tx] = yield* newQueuePair(
|
|
19
|
+
trace ? { traceAs: `${peer1id} -> ${peer2id}` } : undefined,
|
|
20
|
+
);
|
|
21
|
+
const [from2to1Rx, from2to1Tx] = yield* newQueuePair(
|
|
22
|
+
trace ? { traceAs: `${peer2id} -> ${peer1id}` } : undefined,
|
|
23
|
+
);
|
|
24
|
+
|
|
25
|
+
const peer2AsPeer: Peer = {
|
|
26
|
+
id: peer2id,
|
|
27
|
+
incoming: from2to1Rx,
|
|
28
|
+
outgoing: from1to2Tx,
|
|
29
|
+
role: peer2role,
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
const peer1AsPeer: Peer = {
|
|
33
|
+
id: peer1id,
|
|
34
|
+
incoming: from1to2Rx,
|
|
35
|
+
outgoing: from2to1Tx,
|
|
36
|
+
role: peer1role,
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
return [peer1AsPeer, peer2AsPeer];
|
|
103
40
|
});
|
|
41
|
+
}
|
|
104
42
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
43
|
+
export function newQueuePair(
|
|
44
|
+
options: { traceAs?: string } = {},
|
|
45
|
+
): Effect.Effect<[Stream.Stream<SyncMessage>, Queue.Enqueue<SyncMessage>]> {
|
|
46
|
+
return Effect.gen(function* () {
|
|
47
|
+
const queue = yield* Queue.unbounded<SyncMessage>();
|
|
48
|
+
|
|
49
|
+
if (options.traceAs) {
|
|
50
|
+
return [Stream.fromQueue(queue).pipe(Stream.tap((msg) => Console.debug(
|
|
51
|
+
options.traceAs,
|
|
52
|
+
JSON.stringify(
|
|
53
|
+
msg,
|
|
54
|
+
(k, v) =>
|
|
55
|
+
k === "changes" ||
|
|
56
|
+
k === "encryptedChanges"
|
|
57
|
+
? v.slice(0, 20) + "..."
|
|
58
|
+
: v,
|
|
59
|
+
2,
|
|
60
|
+
),
|
|
61
|
+
))), queue];
|
|
118
62
|
} else {
|
|
119
|
-
|
|
120
|
-
console.debug(pairName, "ok queue length", queueLength);
|
|
121
|
-
queueWasOverflowing = false;
|
|
122
|
-
}
|
|
63
|
+
return [Stream.fromQueue(queue), queue];
|
|
123
64
|
}
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
const readable = new ReadableStream<T>({
|
|
127
|
-
async start(controller) {
|
|
128
|
-
resolveEnqueue(controller.enqueue.bind(controller));
|
|
129
|
-
resolveClose(controller.close.bind(controller));
|
|
130
|
-
},
|
|
131
|
-
|
|
132
|
-
cancel(_reason) {
|
|
133
|
-
console.log("Manually closing reader");
|
|
134
|
-
readerClosed = true;
|
|
135
|
-
},
|
|
136
|
-
}).pipeThrough(
|
|
137
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
138
|
-
new TransformStream<any, any>({
|
|
139
|
-
transform(
|
|
140
|
-
chunk: SyncMessage,
|
|
141
|
-
controller: { enqueue: (msg: SyncMessage) => void },
|
|
142
|
-
) {
|
|
143
|
-
queueLength -= 1;
|
|
144
|
-
maybeReportQueueLength();
|
|
145
|
-
controller.enqueue(chunk);
|
|
146
|
-
},
|
|
147
|
-
}),
|
|
148
|
-
) as ReadableStream<T>;
|
|
149
|
-
|
|
150
|
-
let lastWritePromise = Promise.resolve();
|
|
151
|
-
|
|
152
|
-
const writable = new WritableStream<T>({
|
|
153
|
-
async write(chunk) {
|
|
154
|
-
queueLength += 1;
|
|
155
|
-
maybeReportQueueLength();
|
|
156
|
-
const enqueue = await enqueuePromise;
|
|
157
|
-
if (readerClosed) {
|
|
158
|
-
throw new Error("Reader closed");
|
|
159
|
-
} else {
|
|
160
|
-
// make sure write resolves before corresponding read, but make sure writes are still in order
|
|
161
|
-
await lastWritePromise;
|
|
162
|
-
lastWritePromise = new Promise((resolve) => {
|
|
163
|
-
enqueue(chunk);
|
|
164
|
-
resolve();
|
|
165
|
-
});
|
|
166
|
-
}
|
|
167
|
-
},
|
|
168
|
-
async abort(reason) {
|
|
169
|
-
console.debug("Manually closing writer", reason);
|
|
170
|
-
const close = await closePromise;
|
|
171
|
-
close();
|
|
172
|
-
},
|
|
173
65
|
});
|
|
174
|
-
|
|
175
|
-
return [readable, writable];
|
|
176
66
|
}
|
package/src/sync.ts
CHANGED
|
@@ -1,13 +1,9 @@
|
|
|
1
1
|
import { Signature } from "./crypto/crypto.js";
|
|
2
2
|
import { CoValueHeader, Transaction } from "./coValueCore.js";
|
|
3
3
|
import { CoValueCore } from "./coValueCore.js";
|
|
4
|
-
import { LocalNode } from "./localNode.js";
|
|
5
|
-
import {
|
|
6
|
-
ReadableStream,
|
|
7
|
-
WritableStream,
|
|
8
|
-
WritableStreamDefaultWriter,
|
|
9
|
-
} from "isomorphic-streams";
|
|
4
|
+
import { LocalNode, newLoadingState } from "./localNode.js";
|
|
10
5
|
import { RawCoID, SessionID } from "./ids.js";
|
|
6
|
+
import { Effect, Queue, Stream } from "effect";
|
|
11
7
|
|
|
12
8
|
export type CoValueKnownState = {
|
|
13
9
|
id: RawCoID;
|
|
@@ -60,10 +56,27 @@ export type DoneMessage = {
|
|
|
60
56
|
|
|
61
57
|
export type PeerID = string;
|
|
62
58
|
|
|
59
|
+
export class DisconnectedError extends Error {
|
|
60
|
+
readonly _tag = "DisconnectedError";
|
|
61
|
+
constructor(public message: string) {
|
|
62
|
+
super(message);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export class PingTimeoutError extends Error {
|
|
67
|
+
readonly _tag = "PingTimeoutError";
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export type IncomingSyncStream = Stream.Stream<
|
|
71
|
+
SyncMessage,
|
|
72
|
+
DisconnectedError | PingTimeoutError
|
|
73
|
+
>;
|
|
74
|
+
export type OutgoingSyncQueue = Queue.Enqueue<SyncMessage>;
|
|
75
|
+
|
|
63
76
|
export interface Peer {
|
|
64
77
|
id: PeerID;
|
|
65
|
-
incoming:
|
|
66
|
-
outgoing:
|
|
78
|
+
incoming: IncomingSyncStream;
|
|
79
|
+
outgoing: OutgoingSyncQueue;
|
|
67
80
|
role: "peer" | "server" | "client";
|
|
68
81
|
delayOnError?: number;
|
|
69
82
|
priority?: number;
|
|
@@ -73,8 +86,8 @@ export interface PeerState {
|
|
|
73
86
|
id: PeerID;
|
|
74
87
|
optimisticKnownStates: { [id: RawCoID]: CoValueKnownState };
|
|
75
88
|
toldKnownState: Set<RawCoID>;
|
|
76
|
-
incoming:
|
|
77
|
-
outgoing:
|
|
89
|
+
incoming: IncomingSyncStream;
|
|
90
|
+
outgoing: OutgoingSyncQueue;
|
|
78
91
|
role: "peer" | "server" | "client";
|
|
79
92
|
delayOnError?: number;
|
|
80
93
|
priority?: number;
|
|
@@ -127,25 +140,24 @@ export class SyncManager {
|
|
|
127
140
|
});
|
|
128
141
|
}
|
|
129
142
|
|
|
130
|
-
async loadFromPeers(id: RawCoID,
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
continue;
|
|
137
|
-
}
|
|
143
|
+
async loadFromPeers(id: RawCoID, forPeer?: PeerID) {
|
|
144
|
+
const eligiblePeers = this.peersInPriorityOrder().filter(
|
|
145
|
+
(peer) => peer.id !== forPeer && peer.role === "server",
|
|
146
|
+
);
|
|
147
|
+
|
|
148
|
+
for (const peer of eligiblePeers) {
|
|
138
149
|
// console.log("loading", id, "from", peer.id);
|
|
139
|
-
|
|
140
|
-
.
|
|
150
|
+
Effect.runPromise(
|
|
151
|
+
Queue.offer(peer.outgoing, {
|
|
141
152
|
action: "load",
|
|
142
153
|
id: id,
|
|
143
154
|
header: false,
|
|
144
155
|
sessions: {},
|
|
145
|
-
})
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
156
|
+
}),
|
|
157
|
+
).catch((e) => {
|
|
158
|
+
console.error("Error writing to peer", e);
|
|
159
|
+
});
|
|
160
|
+
|
|
149
161
|
const coValueEntry = this.local.coValues[id];
|
|
150
162
|
if (coValueEntry?.state !== "loading") {
|
|
151
163
|
continue;
|
|
@@ -297,7 +309,9 @@ export class SyncManager {
|
|
|
297
309
|
let lastYield = performance.now();
|
|
298
310
|
for (const [_i, piece] of newContentPieces.entries()) {
|
|
299
311
|
// console.log(
|
|
300
|
-
// `${id} -> ${peer.id}: Sending content piece ${i + 1}/${
|
|
312
|
+
// `${id} -> ${peer.id}: Sending content piece ${i + 1}/${
|
|
313
|
+
// newContentPieces.length
|
|
314
|
+
// } header: ${!!piece.header}`,
|
|
301
315
|
// // Object.values(piece.new).map((s) => s.newTransactions)
|
|
302
316
|
// );
|
|
303
317
|
await this.trySendToPeer(peer, piece);
|
|
@@ -328,7 +342,7 @@ export class SyncManager {
|
|
|
328
342
|
id: peer.id,
|
|
329
343
|
optimisticKnownStates: {},
|
|
330
344
|
incoming: peer.incoming,
|
|
331
|
-
outgoing: peer.outgoing
|
|
345
|
+
outgoing: peer.outgoing,
|
|
332
346
|
toldKnownState: new Set(),
|
|
333
347
|
role: peer.role,
|
|
334
348
|
delayOnError: peer.delayOnError,
|
|
@@ -354,91 +368,55 @@ export class SyncManager {
|
|
|
354
368
|
void initialSync();
|
|
355
369
|
}
|
|
356
370
|
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
this.
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
JSON.stringify(msg, (k, v) =>
|
|
382
|
-
k === "changes" || k === "encryptedChanges"
|
|
383
|
-
? v.slice(0, 20) + "..."
|
|
384
|
-
: v,
|
|
371
|
+
void Effect.runPromise(
|
|
372
|
+
peerState.incoming.pipe(
|
|
373
|
+
Stream.ensuring(
|
|
374
|
+
Effect.sync(() => {
|
|
375
|
+
console.log("Peer disconnected:", peer.id);
|
|
376
|
+
delete this.peers[peer.id];
|
|
377
|
+
}),
|
|
378
|
+
),
|
|
379
|
+
Stream.runForEach((msg) =>
|
|
380
|
+
Effect.tryPromise({
|
|
381
|
+
try: () => this.handleSyncMessage(msg, peerState),
|
|
382
|
+
catch: (e) =>
|
|
383
|
+
new Error(
|
|
384
|
+
`Error reading from peer ${
|
|
385
|
+
peer.id
|
|
386
|
+
}, handling msg\n\n${JSON.stringify(
|
|
387
|
+
msg,
|
|
388
|
+
(k, v) =>
|
|
389
|
+
k === "changes" ||
|
|
390
|
+
k === "encryptedChanges"
|
|
391
|
+
? v.slice(0, 20) + "..."
|
|
392
|
+
: v,
|
|
393
|
+
)}`,
|
|
394
|
+
{ cause: e },
|
|
385
395
|
),
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
396
|
+
}).pipe(
|
|
397
|
+
Effect.timeoutFail({
|
|
398
|
+
duration: 10000,
|
|
399
|
+
onTimeout: () =>
|
|
400
|
+
new Error("Took >10s to process message"),
|
|
401
|
+
}),
|
|
402
|
+
),
|
|
403
|
+
),
|
|
404
|
+
Effect.catchAll((e) =>
|
|
405
|
+
Effect.logError(
|
|
406
|
+
"Error in peer",
|
|
407
|
+
peer.id,
|
|
408
|
+
e.message,
|
|
409
|
+
typeof e.cause === "object" &&
|
|
410
|
+
e.cause instanceof Error &&
|
|
411
|
+
e.cause.message,
|
|
412
|
+
),
|
|
413
|
+
),
|
|
414
|
+
),
|
|
415
|
+
);
|
|
404
416
|
}
|
|
405
417
|
|
|
406
418
|
trySendToPeer(peer: PeerState, msg: SyncMessage) {
|
|
407
|
-
|
|
408
|
-
// already disconnected, return to drain potential queue
|
|
409
|
-
return Promise.resolve();
|
|
410
|
-
}
|
|
411
|
-
|
|
412
|
-
return new Promise<void>((resolve) => {
|
|
413
|
-
const start = Date.now();
|
|
414
|
-
peer.outgoing
|
|
415
|
-
.write(msg)
|
|
416
|
-
.then(() => {
|
|
417
|
-
const end = Date.now();
|
|
418
|
-
if (end - start > 1000) {
|
|
419
|
-
// console.error(
|
|
420
|
-
// new Error(
|
|
421
|
-
// `Writing to peer "${peer.id}" took ${
|
|
422
|
-
// Math.round((Date.now() - start) / 100) / 10
|
|
423
|
-
// }s - this should never happen as write should resolve quickly or error`
|
|
424
|
-
// )
|
|
425
|
-
// );
|
|
426
|
-
} else {
|
|
427
|
-
resolve();
|
|
428
|
-
}
|
|
429
|
-
})
|
|
430
|
-
.catch((e) => {
|
|
431
|
-
console.error(
|
|
432
|
-
new Error(
|
|
433
|
-
`Error writing to peer ${peer.id}, disconnecting`,
|
|
434
|
-
{
|
|
435
|
-
cause: e,
|
|
436
|
-
},
|
|
437
|
-
),
|
|
438
|
-
);
|
|
439
|
-
delete this.peers[peer.id];
|
|
440
|
-
});
|
|
441
|
-
});
|
|
419
|
+
return Effect.runPromise(Queue.offer(peer.outgoing, msg));
|
|
442
420
|
}
|
|
443
421
|
|
|
444
422
|
async handleLoad(msg: LoadMessage, peer: PeerState) {
|
|
@@ -447,21 +425,50 @@ export class SyncManager {
|
|
|
447
425
|
|
|
448
426
|
if (!entry) {
|
|
449
427
|
// console.log(`Loading ${msg.id} from all peers except ${peer.id}`);
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
428
|
+
|
|
429
|
+
// special case: we should be able to solve this much more neatly
|
|
430
|
+
// with an explicit state machine in the future
|
|
431
|
+
const eligiblePeers = this.peersInPriorityOrder().filter(
|
|
432
|
+
(other) => other.id !== peer.id && peer.role === "server",
|
|
433
|
+
);
|
|
434
|
+
if (eligiblePeers.length === 0) {
|
|
435
|
+
if (msg.header || Object.keys(msg.sessions).length > 0) {
|
|
436
|
+
this.local.coValues[msg.id] = newLoadingState(
|
|
437
|
+
new Set([peer.id]),
|
|
438
|
+
);
|
|
439
|
+
this.trySendToPeer(peer, {
|
|
440
|
+
action: "known",
|
|
441
|
+
id: msg.id,
|
|
442
|
+
header: false,
|
|
443
|
+
sessions: {},
|
|
444
|
+
}).catch((e) => {
|
|
445
|
+
console.error("Error sending known state back", e);
|
|
446
|
+
});
|
|
447
|
+
}
|
|
448
|
+
return;
|
|
449
|
+
} else {
|
|
450
|
+
this.local
|
|
451
|
+
.loadCoValueCore(msg.id, {
|
|
452
|
+
dontLoadFrom: peer.id,
|
|
453
|
+
dontWaitFor: peer.id,
|
|
454
|
+
})
|
|
455
|
+
.catch((e) => {
|
|
456
|
+
console.error("Error loading coValue in handleLoad", e);
|
|
457
|
+
});
|
|
458
|
+
}
|
|
458
459
|
|
|
459
460
|
entry = this.local.coValues[msg.id]!;
|
|
460
461
|
}
|
|
461
462
|
|
|
462
463
|
if (entry.state === "loading") {
|
|
464
|
+
console.log(
|
|
465
|
+
"Waiting for loaded",
|
|
466
|
+
msg.id,
|
|
467
|
+
"after message from",
|
|
468
|
+
peer.id,
|
|
469
|
+
);
|
|
463
470
|
const loaded = await entry.done;
|
|
464
|
-
|
|
471
|
+
console.log("Loaded", msg.id, loaded);
|
|
465
472
|
if (loaded === "unavailable") {
|
|
466
473
|
peer.optimisticKnownStates[msg.id] = knownStateIn(msg);
|
|
467
474
|
peer.toldKnownState.add(msg.id);
|
|
@@ -508,7 +515,7 @@ export class SyncManager {
|
|
|
508
515
|
}
|
|
509
516
|
} else {
|
|
510
517
|
throw new Error(
|
|
511
|
-
|
|
518
|
+
`Expected coValue entry for ${msg.id} to be created on known state, missing subscribe?`,
|
|
512
519
|
);
|
|
513
520
|
}
|
|
514
521
|
}
|
|
@@ -549,7 +556,7 @@ export class SyncManager {
|
|
|
549
556
|
|
|
550
557
|
if (!entry) {
|
|
551
558
|
throw new Error(
|
|
552
|
-
|
|
559
|
+
`Expected coValue entry for ${msg.id} to be created on new content, missing subscribe?`,
|
|
553
560
|
);
|
|
554
561
|
}
|
|
555
562
|
|
|
@@ -3,6 +3,7 @@ import { newRandomSessionID } from "../coValueCore.js";
|
|
|
3
3
|
import { LocalNode } from "../localNode.js";
|
|
4
4
|
import { connectedPeers } from "../streamUtils.js";
|
|
5
5
|
import { WasmCrypto } from "../crypto/WasmCrypto.js";
|
|
6
|
+
import { Effect } from "effect";
|
|
6
7
|
|
|
7
8
|
const Crypto = await WasmCrypto.create();
|
|
8
9
|
|
|
@@ -52,11 +53,13 @@ test("Can create account with one node, and then load it on another", async () =
|
|
|
52
53
|
map.set("foo", "bar", "private");
|
|
53
54
|
expect(map.get("foo")).toEqual("bar");
|
|
54
55
|
|
|
55
|
-
const [node1asPeer, node2asPeer] = connectedPeers("node1", "node2", {
|
|
56
|
+
const [node1asPeer, node2asPeer] = await Effect.runPromise(connectedPeers("node1", "node2", {
|
|
56
57
|
trace: true,
|
|
57
58
|
peer1role: "server",
|
|
58
59
|
peer2role: "client",
|
|
59
|
-
});
|
|
60
|
+
}));
|
|
61
|
+
|
|
62
|
+
console.log("After connected peers")
|
|
60
63
|
|
|
61
64
|
node.syncManager.addPeer(node2asPeer);
|
|
62
65
|
|