cojson 0.18.32 → 0.18.34
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +1 -1
- package/CHANGELOG.md +18 -0
- package/dist/SyncStateManager.d.ts.map +1 -1
- package/dist/SyncStateManager.js +2 -2
- package/dist/SyncStateManager.js.map +1 -1
- package/dist/coValueCore/SessionMap.d.ts +1 -0
- package/dist/coValueCore/SessionMap.d.ts.map +1 -1
- package/dist/coValueCore/SessionMap.js +22 -12
- package/dist/coValueCore/SessionMap.js.map +1 -1
- package/dist/coValueCore/coValueCore.d.ts +14 -9
- package/dist/coValueCore/coValueCore.d.ts.map +1 -1
- package/dist/coValueCore/coValueCore.js +65 -51
- package/dist/coValueCore/coValueCore.js.map +1 -1
- package/dist/coValueCore/verifiedState.d.ts +5 -3
- package/dist/coValueCore/verifiedState.d.ts.map +1 -1
- package/dist/coValueCore/verifiedState.js +93 -76
- package/dist/coValueCore/verifiedState.js.map +1 -1
- package/dist/coValues/group.d.ts +1 -0
- package/dist/coValues/group.d.ts.map +1 -1
- package/dist/coValues/group.js +24 -4
- package/dist/coValues/group.js.map +1 -1
- package/dist/knownState.d.ts +9 -1
- package/dist/knownState.d.ts.map +1 -1
- package/dist/knownState.js +29 -3
- package/dist/knownState.js.map +1 -1
- package/dist/localNode.d.ts.map +1 -1
- package/dist/localNode.js +3 -3
- package/dist/localNode.js.map +1 -1
- package/dist/queue/LocalTransactionsSyncQueue.d.ts +10 -9
- package/dist/queue/LocalTransactionsSyncQueue.d.ts.map +1 -1
- package/dist/queue/LocalTransactionsSyncQueue.js +53 -32
- package/dist/queue/LocalTransactionsSyncQueue.js.map +1 -1
- package/dist/storage/knownState.js +2 -2
- package/dist/storage/knownState.js.map +1 -1
- package/dist/sync.d.ts +1 -2
- package/dist/sync.d.ts.map +1 -1
- package/dist/sync.js +8 -3
- package/dist/sync.js.map +1 -1
- package/dist/tests/PureJSCrypto.test.js +1 -1
- package/dist/tests/PureJSCrypto.test.js.map +1 -1
- package/dist/tests/StorageApiAsync.test.js +11 -11
- package/dist/tests/StorageApiAsync.test.js.map +1 -1
- package/dist/tests/StorageApiSync.test.js +3 -3
- package/dist/tests/StorageApiSync.test.js.map +1 -1
- package/dist/tests/WasmCrypto.test.js +1 -1
- package/dist/tests/WasmCrypto.test.js.map +1 -1
- package/dist/tests/coPlainText.test.js +13 -14
- package/dist/tests/coPlainText.test.js.map +1 -1
- package/dist/tests/coStream.test.js +12 -12
- package/dist/tests/coStream.test.js.map +1 -1
- package/dist/tests/coValueCore.isCompletelyDownloaded.test.d.ts +2 -0
- package/dist/tests/coValueCore.isCompletelyDownloaded.test.d.ts.map +1 -0
- package/dist/tests/coValueCore.isCompletelyDownloaded.test.js +422 -0
- package/dist/tests/coValueCore.isCompletelyDownloaded.test.js.map +1 -0
- package/dist/tests/coValueCore.isStreaming.test.d.ts +2 -0
- package/dist/tests/coValueCore.isStreaming.test.d.ts.map +1 -0
- package/dist/tests/coValueCore.isStreaming.test.js +232 -0
- package/dist/tests/coValueCore.isStreaming.test.js.map +1 -0
- package/dist/tests/coValueCore.newContentSince.test.d.ts +2 -0
- package/dist/tests/coValueCore.newContentSince.test.d.ts.map +1 -0
- package/dist/tests/coValueCore.newContentSince.test.js +808 -0
- package/dist/tests/coValueCore.newContentSince.test.js.map +1 -0
- package/dist/tests/coreWasm.test.js +2 -2
- package/dist/tests/coreWasm.test.js.map +1 -1
- package/dist/tests/group.childKeyRotation.test.d.ts +2 -0
- package/dist/tests/group.childKeyRotation.test.d.ts.map +1 -0
- package/dist/tests/group.childKeyRotation.test.js +261 -0
- package/dist/tests/group.childKeyRotation.test.js.map +1 -0
- package/dist/tests/group.removeMember.test.js +1 -114
- package/dist/tests/group.removeMember.test.js.map +1 -1
- package/dist/tests/knownState.test.js +83 -11
- package/dist/tests/knownState.test.js.map +1 -1
- package/dist/tests/sync.auth.test.js +6 -6
- package/dist/tests/sync.load.test.js +67 -4
- package/dist/tests/sync.load.test.js.map +1 -1
- package/dist/tests/sync.mesh.test.js +41 -40
- package/dist/tests/sync.mesh.test.js.map +1 -1
- package/dist/tests/sync.peerReconciliation.test.js +1 -1
- package/dist/tests/sync.storage.test.js +29 -28
- package/dist/tests/sync.storage.test.js.map +1 -1
- package/dist/tests/sync.storageAsync.test.js +26 -25
- package/dist/tests/sync.storageAsync.test.js.map +1 -1
- package/dist/tests/sync.upload.test.js +96 -40
- package/dist/tests/sync.upload.test.js.map +1 -1
- package/dist/tests/testUtils.d.ts +12 -8
- package/dist/tests/testUtils.d.ts.map +1 -1
- package/dist/tests/testUtils.js +39 -8
- package/dist/tests/testUtils.js.map +1 -1
- package/package.json +3 -3
- package/src/SyncStateManager.ts +5 -2
- package/src/coValueCore/SessionMap.ts +39 -12
- package/src/coValueCore/coValueCore.ts +81 -66
- package/src/coValueCore/verifiedState.ts +139 -109
- package/src/coValues/group.ts +27 -4
- package/src/knownState.ts +49 -5
- package/src/localNode.ts +7 -5
- package/src/queue/LocalTransactionsSyncQueue.ts +77 -68
- package/src/storage/knownState.ts +2 -2
- package/src/sync.ts +7 -3
- package/src/tests/PureJSCrypto.test.ts +1 -2
- package/src/tests/StorageApiAsync.test.ts +11 -11
- package/src/tests/StorageApiSync.test.ts +3 -3
- package/src/tests/WasmCrypto.test.ts +1 -2
- package/src/tests/coPlainText.test.ts +13 -14
- package/src/tests/coStream.test.ts +12 -12
- package/src/tests/coValueCore.isCompletelyDownloaded.test.ts +590 -0
- package/src/tests/coValueCore.isStreaming.test.ts +353 -0
- package/src/tests/coValueCore.newContentSince.test.ts +966 -0
- package/src/tests/coreWasm.test.ts +2 -2
- package/src/tests/group.childKeyRotation.test.ts +431 -0
- package/src/tests/group.removeMember.test.ts +1 -184
- package/src/tests/knownState.test.ts +108 -11
- package/src/tests/sync.auth.test.ts +6 -6
- package/src/tests/sync.load.test.ts +79 -4
- package/src/tests/sync.mesh.test.ts +41 -40
- package/src/tests/sync.peerReconciliation.test.ts +1 -1
- package/src/tests/sync.storage.test.ts +29 -28
- package/src/tests/sync.storageAsync.test.ts +26 -25
- package/src/tests/sync.upload.test.ts +106 -40
- package/src/tests/testUtils.ts +43 -9
package/src/knownState.ts
CHANGED
|
@@ -109,15 +109,59 @@ export function cloneKnownState(knownState: CoValueKnownState) {
|
|
|
109
109
|
/**
|
|
110
110
|
* Checks if all the local sessions have the same counters as in remote.
|
|
111
111
|
*/
|
|
112
|
-
export function
|
|
113
|
-
|
|
114
|
-
|
|
112
|
+
export function areCurrentSessionsInSyncWith(
|
|
113
|
+
current: Record<string, number>,
|
|
114
|
+
target: Record<string, number>,
|
|
115
115
|
) {
|
|
116
|
-
for (const sessionId of Object.
|
|
117
|
-
|
|
116
|
+
for (const [sessionId, currentCount] of Object.entries(current) as [
|
|
117
|
+
SessionID,
|
|
118
|
+
number,
|
|
119
|
+
][]) {
|
|
120
|
+
const targetCount = target[sessionId] ?? 0;
|
|
121
|
+
if (currentCount !== targetCount) {
|
|
118
122
|
return false;
|
|
119
123
|
}
|
|
120
124
|
}
|
|
121
125
|
|
|
122
126
|
return true;
|
|
123
127
|
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Checks if all the local sessions have the same counters as in remote.
|
|
131
|
+
*/
|
|
132
|
+
export function isKnownStateSubsetOf(
|
|
133
|
+
current: Record<string, number>,
|
|
134
|
+
target: Record<string, number>,
|
|
135
|
+
) {
|
|
136
|
+
for (const [sessionId, currentCount] of Object.entries(current) as [
|
|
137
|
+
SessionID,
|
|
138
|
+
number,
|
|
139
|
+
][]) {
|
|
140
|
+
const targetCount = target[sessionId] ?? 0;
|
|
141
|
+
if (currentCount > targetCount) {
|
|
142
|
+
return false;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
return true;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Returns the record with the sessions that need to be sent to the target
|
|
151
|
+
*/
|
|
152
|
+
export function getKnownStateToSend(
|
|
153
|
+
current: Record<string, number>,
|
|
154
|
+
target: Record<string, number>,
|
|
155
|
+
) {
|
|
156
|
+
const toSend: Record<string, number> = {};
|
|
157
|
+
for (const [sessionId, currentCount] of Object.entries(current) as [
|
|
158
|
+
SessionID,
|
|
159
|
+
number,
|
|
160
|
+
][]) {
|
|
161
|
+
const targetCount = target[sessionId] ?? 0;
|
|
162
|
+
if (currentCount > targetCount) {
|
|
163
|
+
toSend[sessionId] = currentCount;
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
return toSend;
|
|
167
|
+
}
|
package/src/localNode.ts
CHANGED
|
@@ -10,7 +10,6 @@ import {
|
|
|
10
10
|
import {
|
|
11
11
|
type CoValueHeader,
|
|
12
12
|
type CoValueUniqueness,
|
|
13
|
-
VerifiedState,
|
|
14
13
|
} from "./coValueCore/verifiedState.js";
|
|
15
14
|
import {
|
|
16
15
|
AccountMeta,
|
|
@@ -31,7 +30,7 @@ import {
|
|
|
31
30
|
type RawGroup,
|
|
32
31
|
secretSeedFromInviteSecret,
|
|
33
32
|
} from "./coValues/group.js";
|
|
34
|
-
import { CO_VALUE_LOADING_CONFIG
|
|
33
|
+
import { CO_VALUE_LOADING_CONFIG } from "./config.js";
|
|
35
34
|
import { AgentSecret, CryptoProvider } from "./crypto/crypto.js";
|
|
36
35
|
import { AgentID, RawCoID, SessionID, isAgentID } from "./ids.js";
|
|
37
36
|
import { logger } from "./logger.js";
|
|
@@ -41,6 +40,7 @@ import { accountOrAgentIDfromSessionID } from "./typeUtils/accountOrAgentIDfromS
|
|
|
41
40
|
import { expectGroup } from "./typeUtils/expectGroup.js";
|
|
42
41
|
import { canBeBranched } from "./coValueCore/branching.js";
|
|
43
42
|
import { connectedPeers } from "./streamUtils.js";
|
|
43
|
+
import { emptyKnownState } from "./knownState.js";
|
|
44
44
|
|
|
45
45
|
/** A `LocalNode` represents a local view of a set of loaded `CoValue`s, from the perspective of a particular account (or primitive cryptographic agent).
|
|
46
46
|
|
|
@@ -380,7 +380,10 @@ export class LocalNode {
|
|
|
380
380
|
}
|
|
381
381
|
|
|
382
382
|
this.garbageCollector?.trackCoValueAccess(coValue);
|
|
383
|
-
this.syncManager.
|
|
383
|
+
this.syncManager.syncLocalTransaction(
|
|
384
|
+
coValue.verified,
|
|
385
|
+
emptyKnownState(id),
|
|
386
|
+
);
|
|
384
387
|
|
|
385
388
|
return coValue;
|
|
386
389
|
}
|
|
@@ -650,8 +653,7 @@ export class LocalNode {
|
|
|
650
653
|
);
|
|
651
654
|
|
|
652
655
|
const contentPieces =
|
|
653
|
-
groupAsInvite.core.
|
|
654
|
-
[];
|
|
656
|
+
groupAsInvite.core.newContentSince(group.core.knownState()) ?? [];
|
|
655
657
|
|
|
656
658
|
// Import the new transactions to the current localNode
|
|
657
659
|
for (const contentPiece of contentPieces) {
|
|
@@ -1,12 +1,8 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
} from "../
|
|
5
|
-
import { Transaction, VerifiedState } from "../coValueCore/verifiedState.js";
|
|
6
|
-
import { Signature } from "../crypto/crypto.js";
|
|
7
|
-
import { RawCoID, SessionID } from "../ids.js";
|
|
1
|
+
import { knownStateFromContent } from "../coValueContentMessage.js";
|
|
2
|
+
import { VerifiedState } from "../coValueCore/verifiedState.js";
|
|
3
|
+
import { RawCoID } from "../ids.js";
|
|
4
|
+
import { combineKnownStateSessions, CoValueKnownState } from "../knownState.js";
|
|
8
5
|
import { NewContentMessage } from "../sync.js";
|
|
9
|
-
import { LinkedList } from "./LinkedList.js";
|
|
10
6
|
|
|
11
7
|
/**
|
|
12
8
|
* This queue is used to batch the sync of local transactions while preserving the order of updates between CoValues.
|
|
@@ -18,65 +14,97 @@ import { LinkedList } from "./LinkedList.js";
|
|
|
18
14
|
* 2. If we do multiple updates on the same CoMap, the updates will be batched because it's safe to do so.
|
|
19
15
|
*/
|
|
20
16
|
export class LocalTransactionsSyncQueue {
|
|
21
|
-
private
|
|
17
|
+
private batch: NewContentMessage[] = [];
|
|
18
|
+
private firstChunks = new Map<RawCoID, NewContentMessage>();
|
|
19
|
+
private lastUpdatedValue: VerifiedState | undefined;
|
|
20
|
+
private lastUpdatedValueKnownState: CoValueKnownState | undefined;
|
|
22
21
|
|
|
23
22
|
constructor(private readonly sync: (content: NewContentMessage) => void) {}
|
|
24
23
|
|
|
25
|
-
|
|
26
|
-
|
|
24
|
+
syncTransaction = (
|
|
25
|
+
coValue: VerifiedState,
|
|
26
|
+
knownStateBefore: CoValueKnownState,
|
|
27
|
+
) => {
|
|
28
|
+
const lastUpdatedValue = this.lastUpdatedValue;
|
|
29
|
+
const lastUpdatedValueKnownState = this.lastUpdatedValueKnownState;
|
|
27
30
|
|
|
28
|
-
if (
|
|
29
|
-
|
|
31
|
+
if (lastUpdatedValue && lastUpdatedValueKnownState) {
|
|
32
|
+
if (lastUpdatedValue.id === coValue.id) {
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
this.addContentToBatch(lastUpdatedValue, lastUpdatedValueKnownState);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
this.lastUpdatedValue = coValue;
|
|
40
|
+
this.lastUpdatedValueKnownState = knownStateBefore;
|
|
41
|
+
|
|
42
|
+
for (const trackingSet of this.dirtyCoValuesTrackingSets) {
|
|
43
|
+
trackingSet.add(coValue.id);
|
|
30
44
|
}
|
|
31
45
|
|
|
32
|
-
this.
|
|
46
|
+
this.scheduleNextBatch();
|
|
33
47
|
};
|
|
34
48
|
|
|
35
|
-
|
|
49
|
+
private addContentToBatch(
|
|
36
50
|
coValue: VerifiedState,
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
const lastPendingSync = this.queue.tail?.value;
|
|
43
|
-
const lastSignatureIdx = coValue.getLastSignatureCheckpoint(sessionID);
|
|
44
|
-
const isSignatureCheckpoint =
|
|
45
|
-
lastSignatureIdx > -1 && lastSignatureIdx === txIdx;
|
|
46
|
-
|
|
47
|
-
if (lastPendingSync?.id === coValue.id && !isSignatureCheckpoint) {
|
|
48
|
-
addTransactionToContentMessage(
|
|
49
|
-
lastPendingSync,
|
|
50
|
-
transaction,
|
|
51
|
-
sessionID,
|
|
52
|
-
signature,
|
|
53
|
-
txIdx,
|
|
54
|
-
);
|
|
51
|
+
knownStateBefore: CoValueKnownState,
|
|
52
|
+
) {
|
|
53
|
+
const content = coValue.newContentSince(knownStateBefore, {
|
|
54
|
+
skipExpectContentUntil: true, // we need to calculate the streaming header considering the current batch
|
|
55
|
+
});
|
|
55
56
|
|
|
57
|
+
if (!content) {
|
|
56
58
|
return;
|
|
57
59
|
}
|
|
58
60
|
|
|
59
|
-
|
|
61
|
+
let firstChunk = this.firstChunks.get(coValue.id);
|
|
62
|
+
|
|
63
|
+
for (const piece of content) {
|
|
64
|
+
this.batch.push(piece);
|
|
65
|
+
|
|
66
|
+
// Check if the local content updates are in streaming, if so we need to add the info to the first chunk
|
|
67
|
+
if (firstChunk) {
|
|
68
|
+
if (!firstChunk.expectContentUntil) {
|
|
69
|
+
firstChunk.expectContentUntil =
|
|
70
|
+
knownStateFromContent(firstChunk).sessions;
|
|
71
|
+
}
|
|
72
|
+
combineKnownStateSessions(
|
|
73
|
+
firstChunk.expectContentUntil,
|
|
74
|
+
knownStateFromContent(piece).sessions,
|
|
75
|
+
);
|
|
76
|
+
} else {
|
|
77
|
+
firstChunk = piece;
|
|
78
|
+
this.firstChunks.set(coValue.id, firstChunk);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
60
82
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
sessionID,
|
|
65
|
-
signature,
|
|
66
|
-
txIdx,
|
|
67
|
-
);
|
|
83
|
+
private nextBatchScheduled = false;
|
|
84
|
+
scheduleNextBatch() {
|
|
85
|
+
if (this.nextBatchScheduled) return;
|
|
68
86
|
|
|
69
|
-
this.
|
|
70
|
-
};
|
|
87
|
+
this.nextBatchScheduled = true;
|
|
71
88
|
|
|
72
|
-
|
|
73
|
-
|
|
89
|
+
queueMicrotask(() => {
|
|
90
|
+
if (this.lastUpdatedValue && this.lastUpdatedValueKnownState) {
|
|
91
|
+
this.addContentToBatch(
|
|
92
|
+
this.lastUpdatedValue,
|
|
93
|
+
this.lastUpdatedValueKnownState,
|
|
94
|
+
);
|
|
95
|
+
}
|
|
96
|
+
const batch = this.batch;
|
|
74
97
|
|
|
75
|
-
|
|
98
|
+
this.lastUpdatedValue = undefined;
|
|
99
|
+
this.lastUpdatedValueKnownState = undefined;
|
|
100
|
+
this.firstChunks = new Map();
|
|
101
|
+
this.batch = [];
|
|
102
|
+
this.nextBatchScheduled = false;
|
|
76
103
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
104
|
+
for (const content of batch) {
|
|
105
|
+
this.sync(content);
|
|
106
|
+
}
|
|
107
|
+
});
|
|
80
108
|
}
|
|
81
109
|
|
|
82
110
|
private dirtyCoValuesTrackingSets: Set<Set<RawCoID>> = new Set();
|
|
@@ -105,23 +133,4 @@ export class LocalTransactionsSyncQueue {
|
|
|
105
133
|
},
|
|
106
134
|
};
|
|
107
135
|
};
|
|
108
|
-
|
|
109
|
-
private processingSyncs = false;
|
|
110
|
-
processPendingSyncs() {
|
|
111
|
-
if (this.processingSyncs) return;
|
|
112
|
-
|
|
113
|
-
this.processingSyncs = true;
|
|
114
|
-
|
|
115
|
-
queueMicrotask(() => {
|
|
116
|
-
while (this.queue.head) {
|
|
117
|
-
const content = this.queue.head.value;
|
|
118
|
-
|
|
119
|
-
this.sync(content);
|
|
120
|
-
|
|
121
|
-
this.queue.shift();
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
this.processingSyncs = false;
|
|
125
|
-
});
|
|
126
|
-
}
|
|
127
136
|
}
|
|
@@ -3,7 +3,7 @@ import { RawCoID } from "../ids.js";
|
|
|
3
3
|
import {
|
|
4
4
|
CoValueKnownState,
|
|
5
5
|
emptyKnownState,
|
|
6
|
-
|
|
6
|
+
areCurrentSessionsInSyncWith,
|
|
7
7
|
} from "../knownState.js";
|
|
8
8
|
|
|
9
9
|
/**
|
|
@@ -87,7 +87,7 @@ function isInSync(
|
|
|
87
87
|
return false;
|
|
88
88
|
}
|
|
89
89
|
|
|
90
|
-
return
|
|
90
|
+
return areCurrentSessionsInSyncWith(
|
|
91
91
|
knownState.sessions,
|
|
92
92
|
knownStateFromStorage.sessions,
|
|
93
93
|
);
|
package/src/sync.ts
CHANGED
|
@@ -228,7 +228,7 @@ export class SyncManager {
|
|
|
228
228
|
}
|
|
229
229
|
}
|
|
230
230
|
|
|
231
|
-
const newContentPieces = coValue.
|
|
231
|
+
const newContentPieces = coValue.newContentSince(
|
|
232
232
|
peer.getOptimisticKnownState(id),
|
|
233
233
|
);
|
|
234
234
|
|
|
@@ -585,6 +585,8 @@ export class SyncManager {
|
|
|
585
585
|
sessions: msg.expectContentUntil,
|
|
586
586
|
});
|
|
587
587
|
}
|
|
588
|
+
} else if (msg.expectContentUntil) {
|
|
589
|
+
coValue.verified.setStreamingKnownState(msg.expectContentUntil);
|
|
588
590
|
}
|
|
589
591
|
|
|
590
592
|
// At this point the CoValue must be in memory, if not we have a bug
|
|
@@ -647,6 +649,9 @@ export class SyncManager {
|
|
|
647
649
|
peerRole: peer.role,
|
|
648
650
|
id: msg.id,
|
|
649
651
|
err: result.error,
|
|
652
|
+
msgKnownState: knownStateFromContent(msg).sessions,
|
|
653
|
+
knownState: coValue.knownState().sessions,
|
|
654
|
+
newContent: validNewContent.new,
|
|
650
655
|
});
|
|
651
656
|
// TODO Mark only the session as errored, not the whole coValue
|
|
652
657
|
coValue.markErrored(peer.id, result.error);
|
|
@@ -766,7 +771,6 @@ export class SyncManager {
|
|
|
766
771
|
private syncQueue = new LocalTransactionsSyncQueue((content) =>
|
|
767
772
|
this.syncContent(content),
|
|
768
773
|
);
|
|
769
|
-
syncHeader = this.syncQueue.syncHeader;
|
|
770
774
|
syncLocalTransaction = this.syncQueue.syncTransaction;
|
|
771
775
|
trackDirtyCoValues = this.syncQueue.trackDirtyCoValues;
|
|
772
776
|
|
|
@@ -822,7 +826,7 @@ export class SyncManager {
|
|
|
822
826
|
return undefined;
|
|
823
827
|
}
|
|
824
828
|
|
|
825
|
-
return value.
|
|
829
|
+
return value.newContentSince(correction);
|
|
826
830
|
});
|
|
827
831
|
}
|
|
828
832
|
|
|
@@ -117,8 +117,7 @@ describe("PureJSCrypto", () => {
|
|
|
117
117
|
true,
|
|
118
118
|
);
|
|
119
119
|
|
|
120
|
-
const content =
|
|
121
|
-
mapInOtherSession.core.verified.newContentSince(undefined)?.[0];
|
|
120
|
+
const content = mapInOtherSession.core.newContentSince(undefined)?.[0];
|
|
122
121
|
assert(content);
|
|
123
122
|
|
|
124
123
|
client.node.syncManager.handleNewContent(content, "storage");
|
|
@@ -31,7 +31,7 @@ function getNewContentSince(
|
|
|
31
31
|
throw new Error(`CoValue ${coValue.id} is not verified`);
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
-
const contentMessage = coValue.
|
|
34
|
+
const contentMessage = coValue.newContentSince(knownState)?.[0];
|
|
35
35
|
|
|
36
36
|
if (!contentMessage) {
|
|
37
37
|
throw new Error(`No new content available for coValue ${coValue.id}`);
|
|
@@ -295,7 +295,7 @@ describe("StorageApiAsync", () => {
|
|
|
295
295
|
const contentMessage = getNewContentSince(group.core, knownState);
|
|
296
296
|
const correctionCallback = vi.fn((known) => {
|
|
297
297
|
expect(known).toEqual(emptyKnownState(group.id));
|
|
298
|
-
return group.core.
|
|
298
|
+
return group.core.newContentSince(known);
|
|
299
299
|
});
|
|
300
300
|
|
|
301
301
|
// Get initial known state
|
|
@@ -339,7 +339,7 @@ describe("StorageApiAsync", () => {
|
|
|
339
339
|
const contentMessage = getNewContentSince(group.core, knownState);
|
|
340
340
|
const correctionCallback = vi.fn((known) => {
|
|
341
341
|
expect(known).toEqual(initialKnownState);
|
|
342
|
-
return group.core.
|
|
342
|
+
return group.core.newContentSince(known);
|
|
343
343
|
});
|
|
344
344
|
|
|
345
345
|
// Get initial storage known state
|
|
@@ -539,16 +539,16 @@ describe("StorageApiAsync", () => {
|
|
|
539
539
|
}),
|
|
540
540
|
).toMatchInlineSnapshot(`
|
|
541
541
|
[
|
|
542
|
-
"test -> test-storage | CONTENT Core header: false new: After: 1 New: 1",
|
|
543
|
-
"test -> test-storage | CONTENT Core2 header: false new: After: 1 New: 1",
|
|
542
|
+
"test -> test-storage | CONTENT Core header: false new: After: 1 New: 1 expectContentUntil: header/3",
|
|
543
|
+
"test -> test-storage | CONTENT Core2 header: false new: After: 1 New: 1 expectContentUntil: header/3",
|
|
544
544
|
"test -> test-storage | CONTENT Core header: false new: After: 2 New: 1",
|
|
545
545
|
"test -> test-storage | CONTENT Core2 header: false new: After: 2 New: 1",
|
|
546
546
|
"test-storage -> test | KNOWN CORRECTION Core sessions: empty",
|
|
547
547
|
"test -> test-storage | CONTENT Core header: true new: After: 0 New: 3",
|
|
548
548
|
"test-storage -> test | KNOWN CORRECTION Core2 sessions: empty",
|
|
549
549
|
"test -> test-storage | CONTENT Core2 header: true new: After: 0 New: 3",
|
|
550
|
-
"test -> test-storage | CONTENT Core header: false new: After: 3 New: 1",
|
|
551
|
-
"test -> test-storage | CONTENT Core2 header: false new: After: 3 New: 1",
|
|
550
|
+
"test -> test-storage | CONTENT Core header: false new: After: 3 New: 1 expectContentUntil: header/5",
|
|
551
|
+
"test -> test-storage | CONTENT Core2 header: false new: After: 3 New: 1 expectContentUntil: header/5",
|
|
552
552
|
"test -> test-storage | CONTENT Core header: false new: After: 4 New: 1",
|
|
553
553
|
"test -> test-storage | CONTENT Core2 header: false new: After: 4 New: 1",
|
|
554
554
|
]
|
|
@@ -606,14 +606,14 @@ describe("StorageApiAsync", () => {
|
|
|
606
606
|
}),
|
|
607
607
|
).toMatchInlineSnapshot(`
|
|
608
608
|
[
|
|
609
|
-
"test -> test-storage | CONTENT Core header: false new: After: 1 New: 1",
|
|
610
|
-
"test -> test-storage | CONTENT Core2 header: false new: After: 1 New: 1",
|
|
609
|
+
"test -> test-storage | CONTENT Core header: false new: After: 1 New: 1 expectContentUntil: header/3",
|
|
610
|
+
"test -> test-storage | CONTENT Core2 header: false new: After: 1 New: 1 expectContentUntil: header/3",
|
|
611
611
|
"test -> test-storage | CONTENT Core header: false new: After: 2 New: 1",
|
|
612
612
|
"test -> test-storage | CONTENT Core2 header: false new: After: 2 New: 1",
|
|
613
613
|
"test-storage -> test | KNOWN CORRECTION Core sessions: empty",
|
|
614
614
|
"test -> test-storage | CONTENT Core header: true new: After: 0 New: 3",
|
|
615
|
-
"test -> test-storage | CONTENT Core header: false new: After: 3 New: 1",
|
|
616
|
-
"test -> test-storage | CONTENT Core2 header: false new: After: 3 New: 1",
|
|
615
|
+
"test -> test-storage | CONTENT Core header: false new: After: 3 New: 1 expectContentUntil: header/5",
|
|
616
|
+
"test -> test-storage | CONTENT Core2 header: false new: After: 3 New: 1 expectContentUntil: header/5",
|
|
617
617
|
"test -> test-storage | CONTENT Core header: false new: After: 4 New: 1",
|
|
618
618
|
"test -> test-storage | CONTENT Core2 header: false new: After: 4 New: 1",
|
|
619
619
|
]
|
|
@@ -26,7 +26,7 @@ function getNewContentSince(
|
|
|
26
26
|
throw new Error(`CoValue ${coValue.id} is not verified`);
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
-
const contentMessage = coValue.
|
|
29
|
+
const contentMessage = coValue.newContentSince(knownState)?.[0];
|
|
30
30
|
|
|
31
31
|
if (!contentMessage) {
|
|
32
32
|
throw new Error(`No new content available for coValue ${coValue.id}`);
|
|
@@ -274,7 +274,7 @@ describe("StorageApiSync", () => {
|
|
|
274
274
|
const contentMessage = getNewContentSince(group.core, knownState);
|
|
275
275
|
const correctionCallback = vi.fn((known) => {
|
|
276
276
|
expect(known).toEqual(emptyKnownState(group.id));
|
|
277
|
-
return group.core.
|
|
277
|
+
return group.core.newContentSince(known);
|
|
278
278
|
});
|
|
279
279
|
|
|
280
280
|
// Get initial known state
|
|
@@ -318,7 +318,7 @@ describe("StorageApiSync", () => {
|
|
|
318
318
|
const contentMessage = getNewContentSince(group.core, knownState);
|
|
319
319
|
const correctionCallback = vi.fn((known) => {
|
|
320
320
|
expect(known).toEqual(initialKnownState);
|
|
321
|
-
return group.core.
|
|
321
|
+
return group.core.newContentSince(known);
|
|
322
322
|
});
|
|
323
323
|
|
|
324
324
|
// Get initial storage known state
|
|
@@ -117,8 +117,7 @@ describe("WasmCrypto", () => {
|
|
|
117
117
|
true,
|
|
118
118
|
);
|
|
119
119
|
|
|
120
|
-
const content =
|
|
121
|
-
mapInOtherSession.core.verified.newContentSince(undefined)?.[0];
|
|
120
|
+
const content = mapInOtherSession.core.newContentSince(undefined)?.[0];
|
|
122
121
|
assert(content);
|
|
123
122
|
|
|
124
123
|
client.node.syncManager.handleNewContent(content, "storage");
|
|
@@ -371,13 +371,12 @@ test("chunks transactions when when the chars are longer than MAX_RECOMMENDED_TX
|
|
|
371
371
|
}),
|
|
372
372
|
).toMatchInlineSnapshot(`
|
|
373
373
|
[
|
|
374
|
-
"client -> storage | CONTENT CoPlainText header: true new: After: 0 New:
|
|
375
|
-
"client -> storage | CONTENT CoPlainText header: false new: After: 1 New: 1",
|
|
374
|
+
"client -> storage | CONTENT CoPlainText header: true new: After: 0 New: 2 expectContentUntil: header/42",
|
|
376
375
|
"client -> storage | CONTENT CoPlainText header: false new: After: 2 New: 1",
|
|
377
376
|
"client -> storage | CONTENT CoPlainText header: false new: After: 3 New: 1",
|
|
378
377
|
"client -> storage | CONTENT CoPlainText header: false new: After: 4 New: 1",
|
|
379
|
-
"client -> storage | CONTENT CoPlainText header: false new: After: 5 New:
|
|
380
|
-
"client -> storage | CONTENT CoPlainText header: false new: After:
|
|
378
|
+
"client -> storage | CONTENT CoPlainText header: false new: After: 5 New: 1",
|
|
379
|
+
"client -> storage | CONTENT CoPlainText header: false new: After: 6 New: 2",
|
|
381
380
|
"client -> storage | CONTENT CoPlainText header: false new: After: 8 New: 1",
|
|
382
381
|
"client -> storage | CONTENT CoPlainText header: false new: After: 9 New: 1",
|
|
383
382
|
"client -> storage | CONTENT CoPlainText header: false new: After: 10 New: 1",
|
|
@@ -389,8 +388,8 @@ test("chunks transactions when when the chars are longer than MAX_RECOMMENDED_TX
|
|
|
389
388
|
"client -> storage | CONTENT CoPlainText header: false new: After: 16 New: 1",
|
|
390
389
|
"client -> storage | CONTENT CoPlainText header: false new: After: 17 New: 1",
|
|
391
390
|
"client -> storage | CONTENT CoPlainText header: false new: After: 18 New: 1",
|
|
392
|
-
"client -> storage | CONTENT CoPlainText header: false new: After: 19 New:
|
|
393
|
-
"client -> storage | CONTENT CoPlainText header: false new: After:
|
|
391
|
+
"client -> storage | CONTENT CoPlainText header: false new: After: 19 New: 1",
|
|
392
|
+
"client -> storage | CONTENT CoPlainText header: false new: After: 20 New: 2",
|
|
394
393
|
"client -> storage | CONTENT CoPlainText header: false new: After: 22 New: 1",
|
|
395
394
|
"client -> storage | CONTENT CoPlainText header: false new: After: 23 New: 1",
|
|
396
395
|
"client -> storage | CONTENT CoPlainText header: false new: After: 24 New: 1",
|
|
@@ -406,16 +405,16 @@ test("chunks transactions when when the chars are longer than MAX_RECOMMENDED_TX
|
|
|
406
405
|
"client -> storage | CONTENT CoPlainText header: false new: After: 34 New: 1",
|
|
407
406
|
"client -> storage | CONTENT CoPlainText header: false new: After: 35 New: 1",
|
|
408
407
|
"client -> storage | CONTENT CoPlainText header: false new: After: 36 New: 1",
|
|
409
|
-
"client -> storage | CONTENT CoPlainText header: false new: After: 37 New:
|
|
410
|
-
"client -> storage | CONTENT CoPlainText header: false new: After:
|
|
408
|
+
"client -> storage | CONTENT CoPlainText header: false new: After: 37 New: 1",
|
|
409
|
+
"client -> storage | CONTENT CoPlainText header: false new: After: 38 New: 3",
|
|
411
410
|
"client -> storage | CONTENT CoPlainText header: false new: After: 41 New: 1",
|
|
412
411
|
"client -> storage | LOAD CoPlainText sessions: empty",
|
|
413
412
|
"storage -> client | CONTENT CoPlainText header: true new: After: 0 New: 2 expectContentUntil: header/42",
|
|
414
413
|
"storage -> client | CONTENT CoPlainText header: true new: After: 2 New: 1",
|
|
415
414
|
"storage -> client | CONTENT CoPlainText header: true new: After: 3 New: 1",
|
|
416
415
|
"storage -> client | CONTENT CoPlainText header: true new: After: 4 New: 1",
|
|
417
|
-
"storage -> client | CONTENT CoPlainText header: true new: After: 5 New:
|
|
418
|
-
"storage -> client | CONTENT CoPlainText header: true new: After:
|
|
416
|
+
"storage -> client | CONTENT CoPlainText header: true new: After: 5 New: 1",
|
|
417
|
+
"storage -> client | CONTENT CoPlainText header: true new: After: 6 New: 2",
|
|
419
418
|
"storage -> client | CONTENT CoPlainText header: true new: After: 8 New: 1",
|
|
420
419
|
"storage -> client | CONTENT CoPlainText header: true new: After: 9 New: 1",
|
|
421
420
|
"storage -> client | CONTENT CoPlainText header: true new: After: 10 New: 1",
|
|
@@ -427,8 +426,8 @@ test("chunks transactions when when the chars are longer than MAX_RECOMMENDED_TX
|
|
|
427
426
|
"storage -> client | CONTENT CoPlainText header: true new: After: 16 New: 1",
|
|
428
427
|
"storage -> client | CONTENT CoPlainText header: true new: After: 17 New: 1",
|
|
429
428
|
"storage -> client | CONTENT CoPlainText header: true new: After: 18 New: 1",
|
|
430
|
-
"storage -> client | CONTENT CoPlainText header: true new: After: 19 New:
|
|
431
|
-
"storage -> client | CONTENT CoPlainText header: true new: After:
|
|
429
|
+
"storage -> client | CONTENT CoPlainText header: true new: After: 19 New: 1",
|
|
430
|
+
"storage -> client | CONTENT CoPlainText header: true new: After: 20 New: 2",
|
|
432
431
|
"storage -> client | CONTENT CoPlainText header: true new: After: 22 New: 1",
|
|
433
432
|
"storage -> client | CONTENT CoPlainText header: true new: After: 23 New: 1",
|
|
434
433
|
"storage -> client | CONTENT CoPlainText header: true new: After: 24 New: 1",
|
|
@@ -444,8 +443,8 @@ test("chunks transactions when when the chars are longer than MAX_RECOMMENDED_TX
|
|
|
444
443
|
"storage -> client | CONTENT CoPlainText header: true new: After: 34 New: 1",
|
|
445
444
|
"storage -> client | CONTENT CoPlainText header: true new: After: 35 New: 1",
|
|
446
445
|
"storage -> client | CONTENT CoPlainText header: true new: After: 36 New: 1",
|
|
447
|
-
"storage -> client | CONTENT CoPlainText header: true new: After: 37 New:
|
|
448
|
-
"storage -> client | CONTENT CoPlainText header: true new: After:
|
|
446
|
+
"storage -> client | CONTENT CoPlainText header: true new: After: 37 New: 1",
|
|
447
|
+
"storage -> client | CONTENT CoPlainText header: true new: After: 38 New: 3",
|
|
449
448
|
"storage -> client | CONTENT CoPlainText header: true new: After: 41 New: 1",
|
|
450
449
|
]
|
|
451
450
|
`);
|
|
@@ -217,24 +217,24 @@ test("When adding large transactions (small fraction of MAX_RECOMMENDED_TX_SIZE)
|
|
|
217
217
|
expect(sessionEntry.signatureAfter[10]).not.toBeDefined();
|
|
218
218
|
expect(sessionEntry.signatureAfter[11]).not.toBeDefined();
|
|
219
219
|
|
|
220
|
-
const newContent = coValue.
|
|
220
|
+
const newContent = coValue.newContentSince({
|
|
221
221
|
id: coValue.id,
|
|
222
222
|
header: false,
|
|
223
223
|
sessions: {},
|
|
224
224
|
})!;
|
|
225
225
|
|
|
226
|
-
expect(newContent.length).toEqual(
|
|
226
|
+
expect(newContent.length).toEqual(4);
|
|
227
227
|
expect(newContent[0]!.header).toBeDefined();
|
|
228
|
-
expect(newContent[
|
|
228
|
+
expect(newContent[0]!.new[node.currentSessionID]!.lastSignature).toEqual(
|
|
229
229
|
sessionEntry.signatureAfter[3],
|
|
230
230
|
);
|
|
231
|
-
expect(newContent[
|
|
231
|
+
expect(newContent[1]!.new[node.currentSessionID]!.lastSignature).toEqual(
|
|
232
232
|
sessionEntry.signatureAfter[6],
|
|
233
233
|
);
|
|
234
|
-
expect(newContent[
|
|
234
|
+
expect(newContent[2]!.new[node.currentSessionID]!.lastSignature).toEqual(
|
|
235
235
|
sessionEntry.signatureAfter[9],
|
|
236
236
|
);
|
|
237
|
-
expect(newContent[
|
|
237
|
+
expect(newContent[3]!.new[node.currentSessionID]!.lastSignature).toEqual(
|
|
238
238
|
sessionEntry.lastSignature,
|
|
239
239
|
);
|
|
240
240
|
});
|
|
@@ -286,24 +286,24 @@ test("When adding large transactions (bigger than MAX_RECOMMENDED_TX_SIZE), we s
|
|
|
286
286
|
expect(sessionEntry.signatureAfter[3]).toBeDefined();
|
|
287
287
|
expect(sessionEntry.signatureAfter[4]).not.toBeDefined();
|
|
288
288
|
|
|
289
|
-
const newContent = coValue.
|
|
289
|
+
const newContent = coValue.newContentSince({
|
|
290
290
|
id: coValue.id,
|
|
291
291
|
header: false,
|
|
292
292
|
sessions: {},
|
|
293
293
|
})!;
|
|
294
294
|
|
|
295
|
-
expect(newContent.length).toEqual(
|
|
295
|
+
expect(newContent.length).toEqual(4);
|
|
296
296
|
expect(newContent[0]!.header).toBeDefined();
|
|
297
|
-
expect(newContent[
|
|
297
|
+
expect(newContent[0]!.new[node.currentSessionID]!.lastSignature).toEqual(
|
|
298
298
|
sessionEntry.signatureAfter[1],
|
|
299
299
|
);
|
|
300
|
-
expect(newContent[
|
|
300
|
+
expect(newContent[1]!.new[node.currentSessionID]!.lastSignature).toEqual(
|
|
301
301
|
sessionEntry.signatureAfter[2],
|
|
302
302
|
);
|
|
303
|
-
expect(newContent[
|
|
303
|
+
expect(newContent[2]!.new[node.currentSessionID]!.lastSignature).toEqual(
|
|
304
304
|
sessionEntry.signatureAfter[3],
|
|
305
305
|
);
|
|
306
|
-
expect(newContent[
|
|
306
|
+
expect(newContent[3]!.new[node.currentSessionID]!.lastSignature).toEqual(
|
|
307
307
|
sessionEntry.lastSignature,
|
|
308
308
|
);
|
|
309
309
|
});
|