cojson 0.8.5 → 0.8.12
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/CHANGELOG.md +12 -0
- package/dist/native/PeerKnownStates.js +63 -0
- package/dist/native/PeerKnownStates.js.map +1 -0
- package/dist/native/PeerState.js +5 -1
- package/dist/native/PeerState.js.map +1 -1
- package/dist/native/coValueState.js +74 -0
- package/dist/native/coValueState.js.map +1 -0
- package/dist/native/exports.js +39 -0
- package/dist/native/exports.js.map +1 -0
- package/dist/native/index.native.js +2 -39
- package/dist/native/index.native.js.map +1 -1
- package/dist/native/localNode.js +29 -51
- package/dist/native/localNode.js.map +1 -1
- package/dist/native/storage/index.js +2 -2
- package/dist/native/storage/index.js.map +1 -1
- package/dist/native/sync.js +89 -109
- package/dist/native/sync.js.map +1 -1
- package/dist/web/PeerKnownStates.js +63 -0
- package/dist/web/PeerKnownStates.js.map +1 -0
- package/dist/web/PeerState.js +5 -1
- package/dist/web/PeerState.js.map +1 -1
- package/dist/web/coValueState.js +74 -0
- package/dist/web/coValueState.js.map +1 -0
- package/dist/web/exports.js +39 -0
- package/dist/web/exports.js.map +1 -0
- package/dist/web/index.web.js +2 -39
- package/dist/web/index.web.js.map +1 -1
- package/dist/web/localNode.js +29 -51
- package/dist/web/localNode.js.map +1 -1
- package/dist/web/storage/index.js +2 -2
- package/dist/web/storage/index.js.map +1 -1
- package/dist/web/sync.js +89 -109
- package/dist/web/sync.js.map +1 -1
- package/package.json +1 -1
- package/src/PeerKnownStates.ts +108 -0
- package/src/PeerState.ts +8 -2
- package/src/coValueState.ts +107 -0
- package/src/exports.ts +149 -0
- package/src/index.native.ts +2 -152
- package/src/index.web.ts +2 -152
- package/src/localNode.ts +43 -90
- package/src/storage/index.ts +2 -2
- package/src/sync.ts +95 -148
- package/src/tests/PeerKnownStates.test.ts +100 -0
- package/src/tests/PeerState.test.ts +0 -11
- package/src/tests/sync.test.ts +2 -2
- package/.turbo/turbo-build.log +0 -16
- package/.turbo/turbo-lint.log +0 -4
- package/.turbo/turbo-test.log +0 -1001
package/src/sync.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
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
|
|
4
|
+
import { LocalNode } from "./localNode.js";
|
|
5
|
+
import { CoValueState } from "./coValueState.js";
|
|
5
6
|
import { RawCoID, SessionID } from "./ids.js";
|
|
6
7
|
import { PeerState } from "./PeerState.js";
|
|
7
8
|
import { CoValuePriority } from "./priority.js";
|
|
@@ -74,7 +75,7 @@ export interface Peer {
|
|
|
74
75
|
id: PeerID;
|
|
75
76
|
incoming: IncomingSyncStream;
|
|
76
77
|
outgoing: OutgoingSyncQueue;
|
|
77
|
-
role: "peer" | "server" | "client";
|
|
78
|
+
role: "peer" | "server" | "client" | "storage";
|
|
78
79
|
priority?: number;
|
|
79
80
|
crashOnClose: boolean;
|
|
80
81
|
}
|
|
@@ -128,11 +129,12 @@ export class SyncManager {
|
|
|
128
129
|
|
|
129
130
|
async loadFromPeers(id: RawCoID, forPeer?: PeerID) {
|
|
130
131
|
const eligiblePeers = this.peersInPriorityOrder().filter(
|
|
131
|
-
(peer) => peer.id !== forPeer && peer.
|
|
132
|
+
(peer) => peer.id !== forPeer && peer.isServerOrStoragePeer(),
|
|
132
133
|
);
|
|
133
134
|
|
|
135
|
+
const coValueEntry = this.local.coValues[id];
|
|
136
|
+
|
|
134
137
|
for (const peer of eligiblePeers) {
|
|
135
|
-
// console.log("loading", id, "from", peer.id);
|
|
136
138
|
await peer.pushOutgoingMessage({
|
|
137
139
|
action: "load",
|
|
138
140
|
id: id,
|
|
@@ -140,44 +142,9 @@ export class SyncManager {
|
|
|
140
142
|
sessions: {},
|
|
141
143
|
});
|
|
142
144
|
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
continue;
|
|
145
|
+
if (coValueEntry?.state.type === "unknown") {
|
|
146
|
+
await coValueEntry.state.waitForPeer(peer.id);
|
|
146
147
|
}
|
|
147
|
-
const firstStateEntry = coValueEntry.firstPeerState[peer.id];
|
|
148
|
-
if (firstStateEntry?.type !== "waiting") {
|
|
149
|
-
throw new Error("Expected firstPeerState to be waiting " + id);
|
|
150
|
-
}
|
|
151
|
-
await new Promise<void>((resolve) => {
|
|
152
|
-
// const timeout = setTimeout(() => {
|
|
153
|
-
// if (this.local.coValues[id]?.state === "loading") {
|
|
154
|
-
// console.warn(
|
|
155
|
-
// "Timeout waiting for peer to load",
|
|
156
|
-
// id,
|
|
157
|
-
// "from",
|
|
158
|
-
// peer.id,
|
|
159
|
-
// "and it hasn't loaded from other peers yet"
|
|
160
|
-
// );
|
|
161
|
-
// }
|
|
162
|
-
// resolve();
|
|
163
|
-
// }, 1000);
|
|
164
|
-
firstStateEntry.done
|
|
165
|
-
.then(() => {
|
|
166
|
-
// clearTimeout(timeout);
|
|
167
|
-
resolve();
|
|
168
|
-
})
|
|
169
|
-
.catch((e) => {
|
|
170
|
-
// clearTimeout(timeout);
|
|
171
|
-
console.error(
|
|
172
|
-
"Error waiting for peer to load",
|
|
173
|
-
id,
|
|
174
|
-
"from",
|
|
175
|
-
peer.id,
|
|
176
|
-
e,
|
|
177
|
-
);
|
|
178
|
-
resolve();
|
|
179
|
-
});
|
|
180
|
-
});
|
|
181
148
|
}
|
|
182
149
|
}
|
|
183
150
|
|
|
@@ -213,7 +180,7 @@ export class SyncManager {
|
|
|
213
180
|
throw new Error("Expected coValue entry on subscribe");
|
|
214
181
|
}
|
|
215
182
|
|
|
216
|
-
if (entry.state === "
|
|
183
|
+
if (entry.state.type === "unknown") {
|
|
217
184
|
this.trySendToPeer(peer, {
|
|
218
185
|
action: "load",
|
|
219
186
|
id,
|
|
@@ -225,7 +192,7 @@ export class SyncManager {
|
|
|
225
192
|
return;
|
|
226
193
|
}
|
|
227
194
|
|
|
228
|
-
const coValue = entry.coValue;
|
|
195
|
+
const coValue = entry.state.coValue;
|
|
229
196
|
|
|
230
197
|
for (const id of coValue.getDependedOnCoValues()) {
|
|
231
198
|
await this.subscribeToIncludingDependencies(id, peer);
|
|
@@ -274,10 +241,7 @@ export class SyncManager {
|
|
|
274
241
|
}
|
|
275
242
|
}
|
|
276
243
|
|
|
277
|
-
async sendNewContentIncludingDependencies(
|
|
278
|
-
id: RawCoID,
|
|
279
|
-
peer: PeerState,
|
|
280
|
-
) {
|
|
244
|
+
async sendNewContentIncludingDependencies(id: RawCoID, peer: PeerState) {
|
|
281
245
|
const coValue = this.local.expectCoValueLoaded(id);
|
|
282
246
|
|
|
283
247
|
await Promise.all(
|
|
@@ -289,12 +253,12 @@ export class SyncManager {
|
|
|
289
253
|
);
|
|
290
254
|
|
|
291
255
|
const newContentPieces = coValue.newContentSince(
|
|
292
|
-
peer.optimisticKnownStates
|
|
256
|
+
peer.optimisticKnownStates.get(id),
|
|
293
257
|
);
|
|
294
258
|
|
|
295
259
|
if (newContentPieces) {
|
|
296
260
|
const optimisticKnownStateBefore =
|
|
297
|
-
peer.optimisticKnownStates
|
|
261
|
+
peer.optimisticKnownStates.get(id) || emptyKnownState(id);
|
|
298
262
|
|
|
299
263
|
const sendPieces = async () => {
|
|
300
264
|
let lastYield = performance.now();
|
|
@@ -321,14 +285,19 @@ export class SyncManager {
|
|
|
321
285
|
|
|
322
286
|
sendPieces().catch((e) => {
|
|
323
287
|
console.error("Error sending new content piece, retrying", e);
|
|
324
|
-
peer.optimisticKnownStates
|
|
288
|
+
peer.optimisticKnownStates.dispatch({
|
|
289
|
+
type: "SET",
|
|
290
|
+
id,
|
|
291
|
+
value: optimisticKnownStateBefore ?? emptyKnownState(id),
|
|
292
|
+
});
|
|
325
293
|
return this.sendNewContentIncludingDependencies(id, peer);
|
|
326
294
|
});
|
|
327
295
|
|
|
328
|
-
peer.optimisticKnownStates
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
296
|
+
peer.optimisticKnownStates.dispatch({
|
|
297
|
+
type: "COMBINE_WITH",
|
|
298
|
+
id,
|
|
299
|
+
value: coValue.knownState(),
|
|
300
|
+
});
|
|
332
301
|
}
|
|
333
302
|
}
|
|
334
303
|
|
|
@@ -336,7 +305,7 @@ export class SyncManager {
|
|
|
336
305
|
const peerState = new PeerState(peer);
|
|
337
306
|
this.peers[peer.id] = peerState;
|
|
338
307
|
|
|
339
|
-
if (
|
|
308
|
+
if (peerState.isServerOrStoragePeer()) {
|
|
340
309
|
const initialSync = async () => {
|
|
341
310
|
for (const id of Object.keys(
|
|
342
311
|
this.local.coValues,
|
|
@@ -344,11 +313,10 @@ export class SyncManager {
|
|
|
344
313
|
// console.log("subscribing to after peer added", id, peer.id)
|
|
345
314
|
await this.subscribeToIncludingDependencies(id, peerState);
|
|
346
315
|
|
|
347
|
-
peerState.optimisticKnownStates
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
};
|
|
316
|
+
peerState.optimisticKnownStates.dispatch({
|
|
317
|
+
type: "SET_AS_EMPTY",
|
|
318
|
+
id,
|
|
319
|
+
});
|
|
352
320
|
}
|
|
353
321
|
};
|
|
354
322
|
void initialSync();
|
|
@@ -412,7 +380,11 @@ export class SyncManager {
|
|
|
412
380
|
}
|
|
413
381
|
|
|
414
382
|
async handleLoad(msg: LoadMessage, peer: PeerState) {
|
|
415
|
-
peer.optimisticKnownStates
|
|
383
|
+
peer.optimisticKnownStates.dispatch({
|
|
384
|
+
type: "SET",
|
|
385
|
+
id: msg.id,
|
|
386
|
+
value: knownStateIn(msg),
|
|
387
|
+
});
|
|
416
388
|
let entry = this.local.coValues[msg.id];
|
|
417
389
|
|
|
418
390
|
if (!entry) {
|
|
@@ -421,11 +393,11 @@ export class SyncManager {
|
|
|
421
393
|
// special case: we should be able to solve this much more neatly
|
|
422
394
|
// with an explicit state machine in the future
|
|
423
395
|
const eligiblePeers = this.peersInPriorityOrder().filter(
|
|
424
|
-
(other) => other.id !== peer.id && other.
|
|
396
|
+
(other) => other.id !== peer.id && other.isServerOrStoragePeer(),
|
|
425
397
|
);
|
|
426
398
|
if (eligiblePeers.length === 0) {
|
|
427
399
|
if (msg.header || Object.keys(msg.sessions).length > 0) {
|
|
428
|
-
this.local.coValues[msg.id] =
|
|
400
|
+
this.local.coValues[msg.id] = CoValueState.Unknown(
|
|
429
401
|
new Set([peer.id]),
|
|
430
402
|
);
|
|
431
403
|
this.trySendToPeer(peer, {
|
|
@@ -452,17 +424,21 @@ export class SyncManager {
|
|
|
452
424
|
entry = this.local.coValues[msg.id]!;
|
|
453
425
|
}
|
|
454
426
|
|
|
455
|
-
if (entry.state === "
|
|
427
|
+
if (entry.state.type === "unknown") {
|
|
456
428
|
// console.debug(
|
|
457
429
|
// "Waiting for loaded",
|
|
458
430
|
// msg.id,
|
|
459
431
|
// "after message from",
|
|
460
432
|
// peer.id,
|
|
461
433
|
// );
|
|
462
|
-
const loaded = await entry.
|
|
463
|
-
|
|
434
|
+
const loaded = await entry.state.ready;
|
|
435
|
+
|
|
464
436
|
if (loaded === "unavailable") {
|
|
465
|
-
peer.optimisticKnownStates
|
|
437
|
+
peer.optimisticKnownStates.dispatch({
|
|
438
|
+
type: "SET",
|
|
439
|
+
id: msg.id,
|
|
440
|
+
value: knownStateIn(msg),
|
|
441
|
+
});
|
|
466
442
|
peer.toldKnownState.add(msg.id);
|
|
467
443
|
|
|
468
444
|
this.trySendToPeer(peer, {
|
|
@@ -485,10 +461,11 @@ export class SyncManager {
|
|
|
485
461
|
async handleKnownState(msg: KnownStateMessage, peer: PeerState) {
|
|
486
462
|
let entry = this.local.coValues[msg.id];
|
|
487
463
|
|
|
488
|
-
peer.optimisticKnownStates
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
464
|
+
peer.optimisticKnownStates.dispatch({
|
|
465
|
+
type: "COMBINE_WITH",
|
|
466
|
+
id: msg.id,
|
|
467
|
+
value: knownStateIn(msg),
|
|
468
|
+
});
|
|
492
469
|
|
|
493
470
|
if (!entry) {
|
|
494
471
|
if (msg.asDependencyOf) {
|
|
@@ -514,31 +491,17 @@ export class SyncManager {
|
|
|
514
491
|
}
|
|
515
492
|
}
|
|
516
493
|
|
|
517
|
-
if (entry.state === "
|
|
518
|
-
const availableOnPeer = peer.optimisticKnownStates
|
|
519
|
-
|
|
520
|
-
if (
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
: { type: "unavailable" };
|
|
526
|
-
// console.log(
|
|
527
|
-
// "Marking",
|
|
528
|
-
// msg.id,
|
|
529
|
-
// "as",
|
|
530
|
-
// entry.firstPeerState[peer.id]?.type,
|
|
531
|
-
// "from",
|
|
532
|
-
// peer.id
|
|
533
|
-
// );
|
|
534
|
-
if (
|
|
535
|
-
Object.values(entry.firstPeerState).every(
|
|
536
|
-
(s) => s.type === "unavailable",
|
|
537
|
-
)
|
|
538
|
-
) {
|
|
539
|
-
entry.resolve("unavailable");
|
|
494
|
+
if (entry.state.type === "unknown") {
|
|
495
|
+
const availableOnPeer = peer.optimisticKnownStates.get(msg.id)?.header;
|
|
496
|
+
|
|
497
|
+
if (!availableOnPeer) {
|
|
498
|
+
entry.dispatch({
|
|
499
|
+
type: "not-found",
|
|
500
|
+
peerId: peer.id,
|
|
501
|
+
});
|
|
540
502
|
}
|
|
541
|
-
|
|
503
|
+
|
|
504
|
+
return;
|
|
542
505
|
}
|
|
543
506
|
|
|
544
507
|
await this.tellUntoldKnownStateIncludingDependencies(msg.id, peer);
|
|
@@ -546,7 +509,7 @@ export class SyncManager {
|
|
|
546
509
|
}
|
|
547
510
|
|
|
548
511
|
async handleNewContent(msg: NewContentMessage, peer: PeerState) {
|
|
549
|
-
|
|
512
|
+
const entry = this.local.coValues[msg.id];
|
|
550
513
|
|
|
551
514
|
if (!entry) {
|
|
552
515
|
console.error(
|
|
@@ -555,46 +518,31 @@ export class SyncManager {
|
|
|
555
518
|
return;
|
|
556
519
|
}
|
|
557
520
|
|
|
558
|
-
let
|
|
559
|
-
|
|
560
|
-
const peerOptimisticKnownState = peer.optimisticKnownStates[msg.id];
|
|
561
|
-
|
|
562
|
-
if (!peerOptimisticKnownState) {
|
|
563
|
-
console.error(
|
|
564
|
-
"Expected optimisticKnownState to be set for coValue we receive new content for",
|
|
565
|
-
);
|
|
566
|
-
return;
|
|
567
|
-
}
|
|
521
|
+
let coValue: CoValueCore;
|
|
568
522
|
|
|
569
|
-
if (entry.state === "
|
|
523
|
+
if (entry.state.type === "unknown") {
|
|
570
524
|
if (!msg.header) {
|
|
571
525
|
console.error("Expected header to be sent in first message");
|
|
572
526
|
return;
|
|
573
527
|
}
|
|
574
528
|
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
}
|
|
580
|
-
|
|
581
|
-
peerOptimisticKnownState.header = true;
|
|
582
|
-
|
|
583
|
-
const coValue = new CoValueCore(msg.header, this.local);
|
|
529
|
+
peer.optimisticKnownStates.dispatch({
|
|
530
|
+
type: "UPDATE_HEADER",
|
|
531
|
+
id: msg.id,
|
|
532
|
+
header: true,
|
|
533
|
+
});
|
|
584
534
|
|
|
585
|
-
|
|
535
|
+
coValue = new CoValueCore(msg.header, this.local);
|
|
586
536
|
|
|
587
|
-
entry
|
|
588
|
-
|
|
589
|
-
coValue
|
|
590
|
-
|
|
591
|
-
};
|
|
592
|
-
|
|
593
|
-
|
|
537
|
+
entry.dispatch({
|
|
538
|
+
type: "found",
|
|
539
|
+
coValue,
|
|
540
|
+
peerId: peer.id,
|
|
541
|
+
});
|
|
542
|
+
} else {
|
|
543
|
+
coValue = entry.state.coValue;
|
|
594
544
|
}
|
|
595
545
|
|
|
596
|
-
const coValue = entry.coValue;
|
|
597
|
-
|
|
598
546
|
let invalidStateAssumed = false;
|
|
599
547
|
|
|
600
548
|
for (const [sessionID, newContentForSession] of Object.entries(
|
|
@@ -648,15 +596,13 @@ export class SyncManager {
|
|
|
648
596
|
);
|
|
649
597
|
}
|
|
650
598
|
|
|
651
|
-
const theirTotalnTxs = Object.values(
|
|
652
|
-
|
|
653
|
-
).reduce((sum, nTxs) => sum + nTxs, 0);
|
|
654
|
-
const ourTotalnTxs = [...coValue.sessionLogs.values()].reduce(
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
);
|
|
658
|
-
|
|
659
|
-
entry.onProgress?.(ourTotalnTxs / theirTotalnTxs);
|
|
599
|
+
// const theirTotalnTxs = Object.values(
|
|
600
|
+
// peer.optimisticKnownStates[msg.id]?.sessions || {},
|
|
601
|
+
// ).reduce((sum, nTxs) => sum + nTxs, 0);
|
|
602
|
+
// const ourTotalnTxs = [...coValue.sessionLogs.values()].reduce(
|
|
603
|
+
// (sum, session) => sum + session.transactions.length,
|
|
604
|
+
// 0,
|
|
605
|
+
// );
|
|
660
606
|
|
|
661
607
|
if (result.isErr()) {
|
|
662
608
|
console.error(
|
|
@@ -673,15 +619,14 @@ export class SyncManager {
|
|
|
673
619
|
continue;
|
|
674
620
|
}
|
|
675
621
|
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
622
|
+
peer.optimisticKnownStates.dispatch({
|
|
623
|
+
type: "UPDATE_SESSION_COUNTER",
|
|
624
|
+
id: msg.id,
|
|
625
|
+
sessionId: sessionID,
|
|
626
|
+
value:
|
|
627
|
+
newContentForSession.after +
|
|
679
628
|
newContentForSession.newTransactions.length,
|
|
680
|
-
);
|
|
681
|
-
}
|
|
682
|
-
|
|
683
|
-
if (resolveAfterDone) {
|
|
684
|
-
resolveAfterDone(coValue);
|
|
629
|
+
});
|
|
685
630
|
}
|
|
686
631
|
|
|
687
632
|
await this.syncCoValue(coValue);
|
|
@@ -698,7 +643,11 @@ export class SyncManager {
|
|
|
698
643
|
}
|
|
699
644
|
|
|
700
645
|
async handleCorrection(msg: KnownStateMessage, peer: PeerState) {
|
|
701
|
-
peer.optimisticKnownStates
|
|
646
|
+
peer.optimisticKnownStates.dispatch({
|
|
647
|
+
type: "SET",
|
|
648
|
+
id: msg.id,
|
|
649
|
+
value: knownStateIn(msg),
|
|
650
|
+
});
|
|
702
651
|
|
|
703
652
|
return this.sendNewContentIncludingDependencies(msg.id, peer);
|
|
704
653
|
}
|
|
@@ -740,9 +689,7 @@ export class SyncManager {
|
|
|
740
689
|
// });
|
|
741
690
|
// blockingSince = performance.now();
|
|
742
691
|
// }
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
if (optimisticKnownState) {
|
|
692
|
+
if (peer.optimisticKnownStates.has(coValue.id)) {
|
|
746
693
|
await this.tellUntoldKnownStateIncludingDependencies(
|
|
747
694
|
coValue.id,
|
|
748
695
|
peer,
|
|
@@ -751,7 +698,7 @@ export class SyncManager {
|
|
|
751
698
|
coValue.id,
|
|
752
699
|
peer,
|
|
753
700
|
);
|
|
754
|
-
} else if (peer.
|
|
701
|
+
} else if (peer.isServerOrStoragePeer()) {
|
|
755
702
|
await this.subscribeToIncludingDependencies(coValue.id, peer);
|
|
756
703
|
await this.sendNewContentIncludingDependencies(
|
|
757
704
|
coValue.id,
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { PeerKnownStates } from '../PeerKnownStates.js';
|
|
2
|
+
import { CoValueKnownState, emptyKnownState } from '../sync.js';
|
|
3
|
+
import { RawCoID, SessionID } from '../ids.js';
|
|
4
|
+
import { vi, describe, test, expect } from 'vitest';
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
describe('PeerKnownStates', () => {
|
|
8
|
+
test('should set and get a known state', () => {
|
|
9
|
+
const peerKnownStates = new PeerKnownStates();
|
|
10
|
+
const id = 'test-id' as RawCoID;
|
|
11
|
+
const knownState: CoValueKnownState = emptyKnownState(id);
|
|
12
|
+
|
|
13
|
+
peerKnownStates.dispatch({ type: 'SET', id, value: knownState });
|
|
14
|
+
|
|
15
|
+
expect(peerKnownStates.get(id)).toEqual(knownState);
|
|
16
|
+
expect(peerKnownStates.has(id)).toBe(true);
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
test('should update header', () => {
|
|
20
|
+
const peerKnownStates = new PeerKnownStates();
|
|
21
|
+
const id = 'test-id' as RawCoID;
|
|
22
|
+
|
|
23
|
+
peerKnownStates.dispatch({ type: 'UPDATE_HEADER', id, header: true });
|
|
24
|
+
|
|
25
|
+
const result = peerKnownStates.get(id);
|
|
26
|
+
expect(result?.header).toBe(true);
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
test('should update session counter', () => {
|
|
30
|
+
const peerKnownStates = new PeerKnownStates();
|
|
31
|
+
const id = 'test-id' as RawCoID;
|
|
32
|
+
const sessionId = 'session-1' as SessionID;
|
|
33
|
+
|
|
34
|
+
peerKnownStates.dispatch({ type: 'UPDATE_SESSION_COUNTER', id, sessionId, value: 5 });
|
|
35
|
+
|
|
36
|
+
const result = peerKnownStates.get(id);
|
|
37
|
+
expect(result?.sessions[sessionId]).toBe(5);
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
test('should combine with existing state', () => {
|
|
41
|
+
const peerKnownStates = new PeerKnownStates();
|
|
42
|
+
const id = 'test-id' as RawCoID;
|
|
43
|
+
const session1 = 'session-1' as SessionID;
|
|
44
|
+
const session2 = 'session-2' as SessionID;
|
|
45
|
+
const initialState: CoValueKnownState = {
|
|
46
|
+
...emptyKnownState(id),
|
|
47
|
+
sessions: { [session1]: 5 },
|
|
48
|
+
};
|
|
49
|
+
const combineState: CoValueKnownState = {
|
|
50
|
+
...emptyKnownState(id),
|
|
51
|
+
sessions: { [session2]: 10 },
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
peerKnownStates.dispatch({ type: 'SET', id, value: initialState });
|
|
55
|
+
peerKnownStates.dispatch({ type: 'COMBINE_WITH', id, value: combineState });
|
|
56
|
+
|
|
57
|
+
const result = peerKnownStates.get(id);
|
|
58
|
+
expect(result?.sessions).toEqual({ [session1]: 5, [session2]: 10 });
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
test('should set as empty', () => {
|
|
62
|
+
const peerKnownStates = new PeerKnownStates();
|
|
63
|
+
const id = 'test-id' as RawCoID;
|
|
64
|
+
const sessionId = 'session-1' as SessionID;
|
|
65
|
+
const initialState: CoValueKnownState = {
|
|
66
|
+
...emptyKnownState(id),
|
|
67
|
+
sessions: { [sessionId]: 5 },
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
peerKnownStates.dispatch({ type: 'SET', id, value: initialState });
|
|
71
|
+
peerKnownStates.dispatch({ type: 'SET_AS_EMPTY', id });
|
|
72
|
+
|
|
73
|
+
const result = peerKnownStates.get(id);
|
|
74
|
+
expect(result).toEqual(emptyKnownState(id));
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
test('should trigger listeners on dispatch', () => {
|
|
78
|
+
const peerKnownStates = new PeerKnownStates();
|
|
79
|
+
const id = 'test-id' as RawCoID;
|
|
80
|
+
const listener = vi.fn();
|
|
81
|
+
|
|
82
|
+
peerKnownStates.subscribe(listener);
|
|
83
|
+
peerKnownStates.dispatch({ type: 'SET_AS_EMPTY', id });
|
|
84
|
+
|
|
85
|
+
expect(listener).toHaveBeenCalledWith(id, emptyKnownState(id));
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
test('should unsubscribe listener', () => {
|
|
89
|
+
const peerKnownStates = new PeerKnownStates();
|
|
90
|
+
const id = 'test-id' as RawCoID;
|
|
91
|
+
const listener = vi.fn();
|
|
92
|
+
|
|
93
|
+
const unsubscribe = peerKnownStates.subscribe(listener);
|
|
94
|
+
unsubscribe();
|
|
95
|
+
|
|
96
|
+
peerKnownStates.dispatch({ type: 'SET_AS_EMPTY', id });
|
|
97
|
+
|
|
98
|
+
expect(listener).not.toHaveBeenCalled();
|
|
99
|
+
});
|
|
100
|
+
});
|
|
@@ -20,17 +20,6 @@ function setup() {
|
|
|
20
20
|
}
|
|
21
21
|
|
|
22
22
|
describe("PeerState", () => {
|
|
23
|
-
test("should initialize with correct properties", () => {
|
|
24
|
-
const { peerState } = setup();
|
|
25
|
-
expect(peerState.id).toBe("test-peer");
|
|
26
|
-
expect(peerState.role).toBe("peer");
|
|
27
|
-
expect(peerState.priority).toBe(1);
|
|
28
|
-
expect(peerState.crashOnClose).toBe(false);
|
|
29
|
-
expect(peerState.closed).toBe(false);
|
|
30
|
-
expect(peerState.optimisticKnownStates).toEqual({});
|
|
31
|
-
expect(peerState.toldKnownState).toEqual(new Set());
|
|
32
|
-
});
|
|
33
|
-
|
|
34
23
|
test("should push outgoing message to peer", async () => {
|
|
35
24
|
const { mockPeer, peerState } = setup();
|
|
36
25
|
const message: SyncMessage = { action: "load", id: "co_ztest-id", header: false, sessions: {} };
|
package/src/tests/sync.test.ts
CHANGED
|
@@ -761,7 +761,7 @@ test.skip("When replaying creation and transactions of a coValue as new content,
|
|
|
761
761
|
expect(groupTellKnownStateMsg).toMatchObject(groupStateEx(group));
|
|
762
762
|
|
|
763
763
|
expect(
|
|
764
|
-
node2.syncManager.peers["test1"]!.optimisticKnownStates
|
|
764
|
+
node2.syncManager.peers["test1"]!.optimisticKnownStates.has(group.core.id),
|
|
765
765
|
).toBeDefined();
|
|
766
766
|
|
|
767
767
|
// await inTx1.push(adminTellKnownStateMsg);
|
|
@@ -1086,7 +1086,7 @@ test("If we start loading a coValue before connecting to a peer that has it, it
|
|
|
1086
1086
|
|
|
1087
1087
|
const mapOnNode2Promise = node2.loadCoValueCore(map.core.id);
|
|
1088
1088
|
|
|
1089
|
-
expect(node2.coValues[map.core.id]?.state).toEqual("
|
|
1089
|
+
expect(node2.coValues[map.core.id]?.state.type).toEqual("unknown");
|
|
1090
1090
|
|
|
1091
1091
|
node2.syncManager.addPeer(node1asPeer);
|
|
1092
1092
|
|
package/.turbo/turbo-build.log
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
> cojson@0.8.3 build /Users/anselm/jazz/jazz/packages/cojson
|
|
3
|
-
> npm run lint && rm -rf ./dist && pnpm run build:native && pnpm run build:web
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
> cojson@0.8.3 lint
|
|
7
|
-
> eslint . --ext ts,tsx
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
> cojson@0.8.3 build:native /Users/anselm/jazz/jazz/packages/cojson
|
|
11
|
-
> tsc --sourceMap --outDir dist/native -p tsconfig.native.json
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
> cojson@0.8.3 build:web /Users/anselm/jazz/jazz/packages/cojson
|
|
15
|
-
> tsc --sourceMap --outDir dist/web -p tsconfig.web.json
|
|
16
|
-
|
package/.turbo/turbo-lint.log
DELETED