cojson 0.16.2 → 0.16.4
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 +9 -0
- package/dist/coValue.d.ts +1 -1
- package/dist/coValueContentMessage.d.ts +10 -0
- package/dist/coValueContentMessage.d.ts.map +1 -0
- package/dist/coValueContentMessage.js +46 -0
- package/dist/coValueContentMessage.js.map +1 -0
- package/dist/coValueCore/coValueCore.d.ts.map +1 -1
- package/dist/coValueCore/coValueCore.js +5 -3
- package/dist/coValueCore/coValueCore.js.map +1 -1
- package/dist/coValueCore/verifiedState.d.ts +1 -0
- package/dist/coValueCore/verifiedState.d.ts.map +1 -1
- package/dist/coValueCore/verifiedState.js +14 -27
- package/dist/coValueCore/verifiedState.js.map +1 -1
- package/dist/coValues/group.d.ts.map +1 -1
- package/dist/coValues/group.js +16 -8
- package/dist/coValues/group.js.map +1 -1
- package/dist/localNode.d.ts +6 -1
- package/dist/localNode.d.ts.map +1 -1
- package/dist/localNode.js +7 -2
- package/dist/localNode.js.map +1 -1
- package/dist/queue/LocalTransactionsSyncQueue.d.ts +24 -0
- package/dist/queue/LocalTransactionsSyncQueue.d.ts.map +1 -0
- package/dist/queue/LocalTransactionsSyncQueue.js +55 -0
- package/dist/queue/LocalTransactionsSyncQueue.js.map +1 -0
- package/dist/queue/StoreQueue.d.ts +9 -6
- package/dist/queue/StoreQueue.d.ts.map +1 -1
- package/dist/queue/StoreQueue.js +10 -2
- package/dist/queue/StoreQueue.js.map +1 -1
- package/dist/storage/storageAsync.d.ts +11 -3
- package/dist/storage/storageAsync.d.ts.map +1 -1
- package/dist/storage/storageAsync.js +59 -46
- package/dist/storage/storageAsync.js.map +1 -1
- package/dist/storage/storageSync.d.ts +9 -3
- package/dist/storage/storageSync.d.ts.map +1 -1
- package/dist/storage/storageSync.js +48 -35
- package/dist/storage/storageSync.js.map +1 -1
- package/dist/storage/syncUtils.d.ts +2 -1
- package/dist/storage/syncUtils.d.ts.map +1 -1
- package/dist/storage/syncUtils.js +4 -0
- package/dist/storage/syncUtils.js.map +1 -1
- package/dist/storage/types.d.ts +3 -2
- package/dist/storage/types.d.ts.map +1 -1
- package/dist/sync.d.ts +6 -6
- package/dist/sync.d.ts.map +1 -1
- package/dist/sync.js +33 -56
- package/dist/sync.js.map +1 -1
- package/dist/tests/StorageApiAsync.test.d.ts +2 -0
- package/dist/tests/StorageApiAsync.test.d.ts.map +1 -0
- package/dist/tests/StorageApiAsync.test.js +574 -0
- package/dist/tests/StorageApiAsync.test.js.map +1 -0
- package/dist/tests/StorageApiSync.test.d.ts +2 -0
- package/dist/tests/StorageApiSync.test.d.ts.map +1 -0
- package/dist/tests/StorageApiSync.test.js +426 -0
- package/dist/tests/StorageApiSync.test.js.map +1 -0
- package/dist/tests/StoreQueue.test.js +9 -21
- package/dist/tests/StoreQueue.test.js.map +1 -1
- package/dist/tests/SyncStateManager.test.js +18 -8
- package/dist/tests/SyncStateManager.test.js.map +1 -1
- package/dist/tests/group.inheritance.test.js +79 -2
- package/dist/tests/group.inheritance.test.js.map +1 -1
- package/dist/tests/sync.auth.test.js +22 -10
- package/dist/tests/sync.auth.test.js.map +1 -1
- package/dist/tests/sync.load.test.js +25 -23
- package/dist/tests/sync.load.test.js.map +1 -1
- package/dist/tests/sync.mesh.test.js +12 -6
- package/dist/tests/sync.mesh.test.js.map +1 -1
- package/dist/tests/sync.peerReconciliation.test.js +6 -4
- package/dist/tests/sync.peerReconciliation.test.js.map +1 -1
- package/dist/tests/sync.storage.test.js +8 -14
- package/dist/tests/sync.storage.test.js.map +1 -1
- package/dist/tests/sync.storageAsync.test.js +31 -14
- package/dist/tests/sync.storageAsync.test.js.map +1 -1
- package/dist/tests/sync.test.js +5 -9
- package/dist/tests/sync.test.js.map +1 -1
- package/dist/tests/sync.upload.test.js +31 -1
- package/dist/tests/sync.upload.test.js.map +1 -1
- package/dist/tests/testStorage.d.ts +2 -3
- package/dist/tests/testStorage.d.ts.map +1 -1
- package/dist/tests/testStorage.js +16 -8
- package/dist/tests/testStorage.js.map +1 -1
- package/dist/tests/testUtils.d.ts +3 -0
- package/dist/tests/testUtils.d.ts.map +1 -1
- package/dist/tests/testUtils.js +17 -4
- package/dist/tests/testUtils.js.map +1 -1
- package/package.json +1 -1
- package/src/coValueContentMessage.ts +73 -0
- package/src/coValueCore/coValueCore.ts +14 -5
- package/src/coValueCore/verifiedState.ts +28 -35
- package/src/coValues/group.ts +20 -9
- package/src/localNode.ts +8 -3
- package/src/queue/LocalTransactionsSyncQueue.ts +96 -0
- package/src/queue/StoreQueue.ts +22 -12
- package/src/storage/storageAsync.ts +78 -56
- package/src/storage/storageSync.ts +66 -45
- package/src/storage/syncUtils.ts +9 -1
- package/src/storage/types.ts +6 -5
- package/src/sync.ts +47 -67
- package/src/tests/StorageApiAsync.test.ts +829 -0
- package/src/tests/StorageApiSync.test.ts +628 -0
- package/src/tests/StoreQueue.test.ts +10 -24
- package/src/tests/SyncStateManager.test.ts +22 -21
- package/src/tests/group.inheritance.test.ts +136 -1
- package/src/tests/sync.auth.test.ts +22 -10
- package/src/tests/sync.load.test.ts +27 -24
- package/src/tests/sync.mesh.test.ts +12 -6
- package/src/tests/sync.peerReconciliation.test.ts +6 -4
- package/src/tests/sync.storage.test.ts +8 -14
- package/src/tests/sync.storageAsync.test.ts +39 -14
- package/src/tests/sync.test.ts +6 -14
- package/src/tests/sync.upload.test.ts +38 -1
- package/src/tests/testStorage.ts +19 -13
- package/src/tests/testUtils.ts +24 -5
|
@@ -1,20 +1,29 @@
|
|
|
1
1
|
import { UpDownCounter, metrics } from "@opentelemetry/api";
|
|
2
|
+
import {
|
|
3
|
+
createContentMessage,
|
|
4
|
+
exceedsRecommendedSize,
|
|
5
|
+
getTransactionSize,
|
|
6
|
+
} from "../coValueContentMessage.js";
|
|
2
7
|
import {
|
|
3
8
|
CoValueCore,
|
|
4
|
-
MAX_RECOMMENDED_TX_SIZE,
|
|
5
9
|
RawCoID,
|
|
6
10
|
type SessionID,
|
|
7
11
|
type StorageAPI,
|
|
12
|
+
logger,
|
|
8
13
|
} from "../exports.js";
|
|
9
|
-
import { getPriorityFromHeader } from "../priority.js";
|
|
10
14
|
import {
|
|
11
15
|
CoValueKnownState,
|
|
12
16
|
NewContentMessage,
|
|
13
17
|
emptyKnownState,
|
|
14
18
|
} from "../sync.js";
|
|
15
19
|
import { StorageKnownState } from "./knownState.js";
|
|
16
|
-
import {
|
|
20
|
+
import {
|
|
21
|
+
collectNewTxs,
|
|
22
|
+
getDependedOnCoValues,
|
|
23
|
+
getNewTransactionsSize,
|
|
24
|
+
} from "./syncUtils.js";
|
|
17
25
|
import type {
|
|
26
|
+
CorrectionCallback,
|
|
18
27
|
DBClientInterfaceSync,
|
|
19
28
|
SignatureAfterRow,
|
|
20
29
|
StoredCoValueRow,
|
|
@@ -84,6 +93,7 @@ export class StorageApiSync implements StorageAPI {
|
|
|
84
93
|
}
|
|
85
94
|
|
|
86
95
|
const knownState = this.knwonStates.getKnownState(coValueRow.id);
|
|
96
|
+
knownState.header = true;
|
|
87
97
|
|
|
88
98
|
for (const sessionRow of allCoValueSessions) {
|
|
89
99
|
knownState.sessions[sessionRow.sessionID] = sessionRow.lastIdx;
|
|
@@ -91,13 +101,7 @@ export class StorageApiSync implements StorageAPI {
|
|
|
91
101
|
|
|
92
102
|
this.loadedCoValues.add(coValueRow.id);
|
|
93
103
|
|
|
94
|
-
let contentMessage =
|
|
95
|
-
action: "content",
|
|
96
|
-
id: coValueRow.id,
|
|
97
|
-
header: coValueRow.header,
|
|
98
|
-
new: {},
|
|
99
|
-
priority: getPriorityFromHeader(coValueRow.header),
|
|
100
|
-
} as NewContentMessage;
|
|
104
|
+
let contentMessage = createContentMessage(coValueRow.id, coValueRow.header);
|
|
101
105
|
|
|
102
106
|
if (contentStreaming) {
|
|
103
107
|
this.streamingCounter.add(1);
|
|
@@ -137,13 +141,10 @@ export class StorageApiSync implements StorageAPI {
|
|
|
137
141
|
contentMessage,
|
|
138
142
|
callback,
|
|
139
143
|
);
|
|
140
|
-
contentMessage =
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
new: {},
|
|
145
|
-
priority: getPriorityFromHeader(coValueRow.header),
|
|
146
|
-
} satisfies NewContentMessage;
|
|
144
|
+
contentMessage = createContentMessage(
|
|
145
|
+
coValueRow.id,
|
|
146
|
+
coValueRow.header,
|
|
147
|
+
);
|
|
147
148
|
|
|
148
149
|
// Introduce a delay to not block the main thread
|
|
149
150
|
// for the entire content processing
|
|
@@ -189,22 +190,49 @@ export class StorageApiSync implements StorageAPI {
|
|
|
189
190
|
pushCallback(contentMessage);
|
|
190
191
|
}
|
|
191
192
|
|
|
192
|
-
store(
|
|
193
|
-
|
|
194
|
-
|
|
193
|
+
store(msg: NewContentMessage, correctionCallback: CorrectionCallback) {
|
|
194
|
+
return this.storeSingle(msg, correctionCallback);
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
* This function is called when the storage lacks the information required to store the incoming content.
|
|
199
|
+
*
|
|
200
|
+
* It triggers a `correctionCallback` to ask the syncManager to provide the missing information.
|
|
201
|
+
*/
|
|
202
|
+
private handleCorrection(
|
|
203
|
+
knownState: CoValueKnownState,
|
|
204
|
+
correctionCallback: CorrectionCallback,
|
|
195
205
|
) {
|
|
196
|
-
|
|
197
|
-
|
|
206
|
+
const correction = correctionCallback(knownState);
|
|
207
|
+
|
|
208
|
+
if (!correction) {
|
|
209
|
+
logger.error("Correction callback returned undefined", {
|
|
210
|
+
knownState,
|
|
211
|
+
correction: correction ?? null,
|
|
212
|
+
});
|
|
213
|
+
return false;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
for (const msg of correction) {
|
|
217
|
+
const success = this.storeSingle(msg, (knownState) => {
|
|
218
|
+
logger.error("Double correction requested", {
|
|
219
|
+
msg,
|
|
220
|
+
knownState,
|
|
221
|
+
});
|
|
222
|
+
return undefined;
|
|
223
|
+
});
|
|
198
224
|
|
|
199
225
|
if (!success) {
|
|
200
226
|
return false;
|
|
201
227
|
}
|
|
202
228
|
}
|
|
229
|
+
|
|
230
|
+
return true;
|
|
203
231
|
}
|
|
204
232
|
|
|
205
233
|
private storeSingle(
|
|
206
234
|
msg: NewContentMessage,
|
|
207
|
-
correctionCallback:
|
|
235
|
+
correctionCallback: CorrectionCallback,
|
|
208
236
|
): boolean {
|
|
209
237
|
const id = msg.id;
|
|
210
238
|
const coValueRow = this.dbClient.getCoValue(id);
|
|
@@ -214,11 +242,9 @@ export class StorageApiSync implements StorageAPI {
|
|
|
214
242
|
|
|
215
243
|
if (invalidAssumptionOnHeaderPresence) {
|
|
216
244
|
const knownState = emptyKnownState(id as RawCoID);
|
|
217
|
-
correctionCallback(knownState);
|
|
218
|
-
|
|
219
245
|
this.knwonStates.setKnownState(id, knownState);
|
|
220
246
|
|
|
221
|
-
return
|
|
247
|
+
return this.handleCorrection(knownState, correctionCallback);
|
|
222
248
|
}
|
|
223
249
|
|
|
224
250
|
const storedCoValueRowID: number = coValueRow
|
|
@@ -258,8 +284,7 @@ export class StorageApiSync implements StorageAPI {
|
|
|
258
284
|
this.knwonStates.handleUpdate(id, knownState);
|
|
259
285
|
|
|
260
286
|
if (invalidAssumptions) {
|
|
261
|
-
|
|
262
|
-
return false;
|
|
287
|
+
return this.handleCorrection(knownState, correctionCallback);
|
|
263
288
|
}
|
|
264
289
|
|
|
265
290
|
return true;
|
|
@@ -272,35 +297,29 @@ export class StorageApiSync implements StorageAPI {
|
|
|
272
297
|
storedCoValueRowID: number,
|
|
273
298
|
) {
|
|
274
299
|
const newTransactions = msg.new[sessionID]?.newTransactions || [];
|
|
300
|
+
const lastIdx = sessionRow?.lastIdx || 0;
|
|
275
301
|
|
|
276
|
-
const actuallyNewOffset =
|
|
277
|
-
(sessionRow?.lastIdx || 0) - (msg.new[sessionID]?.after || 0);
|
|
302
|
+
const actuallyNewOffset = lastIdx - (msg.new[sessionID]?.after || 0);
|
|
278
303
|
|
|
279
304
|
const actuallyNewTransactions = newTransactions.slice(actuallyNewOffset);
|
|
280
305
|
|
|
281
306
|
if (actuallyNewTransactions.length === 0) {
|
|
282
|
-
return
|
|
307
|
+
return lastIdx;
|
|
283
308
|
}
|
|
284
309
|
|
|
285
|
-
let
|
|
286
|
-
|
|
287
|
-
actuallyNewTransactions.reduce(
|
|
288
|
-
(sum, tx) =>
|
|
289
|
-
sum +
|
|
290
|
-
(tx.privacy === "private"
|
|
291
|
-
? tx.encryptedChanges.length
|
|
292
|
-
: tx.changes.length),
|
|
293
|
-
0,
|
|
294
|
-
);
|
|
310
|
+
let bytesSinceLastSignature = sessionRow?.bytesSinceLastSignature || 0;
|
|
311
|
+
const newTransactionsSize = getNewTransactionsSize(actuallyNewTransactions);
|
|
295
312
|
|
|
296
313
|
const newLastIdx =
|
|
297
314
|
(sessionRow?.lastIdx || 0) + actuallyNewTransactions.length;
|
|
298
315
|
|
|
299
316
|
let shouldWriteSignature = false;
|
|
300
317
|
|
|
301
|
-
if (
|
|
318
|
+
if (exceedsRecommendedSize(bytesSinceLastSignature, newTransactionsSize)) {
|
|
302
319
|
shouldWriteSignature = true;
|
|
303
|
-
|
|
320
|
+
bytesSinceLastSignature = 0;
|
|
321
|
+
} else {
|
|
322
|
+
bytesSinceLastSignature += newTransactionsSize;
|
|
304
323
|
}
|
|
305
324
|
|
|
306
325
|
const nextIdx = sessionRow?.lastIdx || 0;
|
|
@@ -312,7 +331,7 @@ export class StorageApiSync implements StorageAPI {
|
|
|
312
331
|
sessionID,
|
|
313
332
|
lastIdx: newLastIdx,
|
|
314
333
|
lastSignature: msg.new[sessionID].lastSignature,
|
|
315
|
-
bytesSinceLastSignature
|
|
334
|
+
bytesSinceLastSignature,
|
|
316
335
|
};
|
|
317
336
|
|
|
318
337
|
const sessionRowID: number = this.dbClient.addSessionUpdate({
|
|
@@ -339,5 +358,7 @@ export class StorageApiSync implements StorageAPI {
|
|
|
339
358
|
return this.knwonStates.waitForSync(id, coValue);
|
|
340
359
|
}
|
|
341
360
|
|
|
342
|
-
close() {
|
|
361
|
+
close() {
|
|
362
|
+
return undefined;
|
|
363
|
+
}
|
|
343
364
|
}
|
package/src/storage/syncUtils.ts
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
|
+
import { getTransactionSize } from "../coValueContentMessage.js";
|
|
1
2
|
import { getDependedOnCoValuesFromRawData } from "../coValueCore/utils.js";
|
|
2
|
-
import type {
|
|
3
|
+
import type {
|
|
4
|
+
CoValueHeader,
|
|
5
|
+
Transaction,
|
|
6
|
+
} from "../coValueCore/verifiedState.js";
|
|
3
7
|
import type { Signature } from "../crypto/crypto.js";
|
|
4
8
|
import type { SessionID } from "../exports.js";
|
|
5
9
|
import type { NewContentMessage } from "../sync.js";
|
|
@@ -48,3 +52,7 @@ export function getDependedOnCoValues(
|
|
|
48
52
|
|
|
49
53
|
return getDependedOnCoValuesFromRawData(id, header, sessionIDs, transactions);
|
|
50
54
|
}
|
|
55
|
+
|
|
56
|
+
export function getNewTransactionsSize(newTxs: Transaction[]) {
|
|
57
|
+
return newTxs.reduce((sum, tx) => sum + getTransactionSize(tx), 0);
|
|
58
|
+
}
|
package/src/storage/types.ts
CHANGED
|
@@ -6,6 +6,10 @@ import { Signature } from "../crypto/crypto.js";
|
|
|
6
6
|
import type { CoValueCore, RawCoID, SessionID } from "../exports.js";
|
|
7
7
|
import { CoValueKnownState, NewContentMessage } from "../sync.js";
|
|
8
8
|
|
|
9
|
+
export type CorrectionCallback = (
|
|
10
|
+
correction: CoValueKnownState,
|
|
11
|
+
) => NewContentMessage[] | undefined;
|
|
12
|
+
|
|
9
13
|
/**
|
|
10
14
|
* The StorageAPI is the interface that the StorageSync and StorageAsync classes implement.
|
|
11
15
|
*
|
|
@@ -18,16 +22,13 @@ export interface StorageAPI {
|
|
|
18
22
|
callback: (data: NewContentMessage) => void,
|
|
19
23
|
done?: (found: boolean) => void,
|
|
20
24
|
): void;
|
|
21
|
-
store(
|
|
22
|
-
data: NewContentMessage[] | undefined,
|
|
23
|
-
handleCorrection: (correction: CoValueKnownState) => void,
|
|
24
|
-
): void;
|
|
25
|
+
store(data: NewContentMessage, handleCorrection: CorrectionCallback): void;
|
|
25
26
|
|
|
26
27
|
getKnownState(id: string): CoValueKnownState;
|
|
27
28
|
|
|
28
29
|
waitForSync(id: string, coValue: CoValueCore): Promise<void>;
|
|
29
30
|
|
|
30
|
-
close():
|
|
31
|
+
close(): Promise<unknown> | undefined;
|
|
31
32
|
}
|
|
32
33
|
|
|
33
34
|
export type CoValueRow = {
|
package/src/sync.ts
CHANGED
|
@@ -1,15 +1,24 @@
|
|
|
1
1
|
import { Histogram, ValueType, metrics } from "@opentelemetry/api";
|
|
2
2
|
import { PeerState } from "./PeerState.js";
|
|
3
3
|
import { SyncStateManager } from "./SyncStateManager.js";
|
|
4
|
+
import {
|
|
5
|
+
getTransactionSize,
|
|
6
|
+
knownStateFromContent,
|
|
7
|
+
} from "./coValueContentMessage.js";
|
|
4
8
|
import { CoValueCore } from "./coValueCore/coValueCore.js";
|
|
5
9
|
import { getDependedOnCoValuesFromRawData } from "./coValueCore/utils.js";
|
|
6
|
-
import {
|
|
10
|
+
import {
|
|
11
|
+
CoValueHeader,
|
|
12
|
+
Transaction,
|
|
13
|
+
VerifiedState,
|
|
14
|
+
} from "./coValueCore/verifiedState.js";
|
|
7
15
|
import { Signature } from "./crypto/crypto.js";
|
|
8
|
-
import { RawCoID, SessionID } from "./ids.js";
|
|
16
|
+
import { RawCoID, SessionID, isRawCoID } from "./ids.js";
|
|
9
17
|
import { LocalNode } from "./localNode.js";
|
|
10
18
|
import { logger } from "./logger.js";
|
|
11
19
|
import { CoValuePriority } from "./priority.js";
|
|
12
20
|
import { IncomingMessagesQueue } from "./queue/IncomingMessagesQueue.js";
|
|
21
|
+
import { LocalTransactionsSyncQueue } from "./queue/LocalTransactionsSyncQueue.js";
|
|
13
22
|
import { accountOrAgentIDfromSessionID } from "./typeUtils/accountOrAgentIDfromSessionID.js";
|
|
14
23
|
import { isAccountID } from "./typeUtils/isAccountID.js";
|
|
15
24
|
|
|
@@ -57,10 +66,12 @@ export type NewContentMessage = {
|
|
|
57
66
|
};
|
|
58
67
|
|
|
59
68
|
export type SessionNewContent = {
|
|
69
|
+
// The index where to start appending the new transactions. The index counting starts from 1.
|
|
60
70
|
after: number;
|
|
61
71
|
newTransactions: Transaction[];
|
|
62
72
|
lastSignature: Signature;
|
|
63
73
|
};
|
|
74
|
+
|
|
64
75
|
export type DoneMessage = {
|
|
65
76
|
action: "done";
|
|
66
77
|
id: RawCoID;
|
|
@@ -162,13 +173,9 @@ export class SyncManager {
|
|
|
162
173
|
}
|
|
163
174
|
|
|
164
175
|
handleSyncMessage(msg: SyncMessage, peer: PeerState) {
|
|
165
|
-
if (msg.id
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
});
|
|
169
|
-
return;
|
|
170
|
-
} else if (!msg.id.startsWith("co_z")) {
|
|
171
|
-
logger.warn("Received sync message with invalid id", {
|
|
176
|
+
if (!isRawCoID(msg.id)) {
|
|
177
|
+
const errorType = msg.id ? "invalid" : "undefined";
|
|
178
|
+
logger.warn(`Received sync message with ${errorType} id`, {
|
|
172
179
|
msg,
|
|
173
180
|
});
|
|
174
181
|
return;
|
|
@@ -431,12 +438,9 @@ export class SyncManager {
|
|
|
431
438
|
|
|
432
439
|
recordTransactionsSize(newTransactions: Transaction[], source: string) {
|
|
433
440
|
for (const tx of newTransactions) {
|
|
434
|
-
const
|
|
435
|
-
tx.privacy === "private"
|
|
436
|
-
? tx.encryptedChanges.length
|
|
437
|
-
: tx.changes.length;
|
|
441
|
+
const size = getTransactionSize(tx);
|
|
438
442
|
|
|
439
|
-
this.transactionsSizeHistogram.record(
|
|
443
|
+
this.transactionsSizeHistogram.record(size, {
|
|
440
444
|
source,
|
|
441
445
|
});
|
|
442
446
|
}
|
|
@@ -674,7 +678,7 @@ export class SyncManager {
|
|
|
674
678
|
const syncedPeers = [];
|
|
675
679
|
|
|
676
680
|
if (from !== "storage") {
|
|
677
|
-
this.
|
|
681
|
+
this.storeContent(msg);
|
|
678
682
|
}
|
|
679
683
|
|
|
680
684
|
for (const peer of this.peersInPriorityOrder()) {
|
|
@@ -736,60 +740,18 @@ export class SyncManager {
|
|
|
736
740
|
};
|
|
737
741
|
}
|
|
738
742
|
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
for (const trackingSet of this.dirtyCoValuesTrackingSets) {
|
|
746
|
-
trackingSet.add(coValue.id);
|
|
747
|
-
}
|
|
748
|
-
|
|
749
|
-
queueMicrotask(() => {
|
|
750
|
-
if (this.requestedSyncs.has(coValue.id)) {
|
|
751
|
-
this.syncCoValue(coValue);
|
|
752
|
-
}
|
|
753
|
-
});
|
|
754
|
-
|
|
755
|
-
this.requestedSyncs.add(coValue.id);
|
|
756
|
-
}
|
|
757
|
-
|
|
758
|
-
storeCoValue(coValue: CoValueCore, data: NewContentMessage[] | undefined) {
|
|
759
|
-
const storage = this.local.storage;
|
|
760
|
-
|
|
761
|
-
if (!storage || !data) return;
|
|
762
|
-
|
|
763
|
-
// Try to store the content as-is for performance
|
|
764
|
-
// In case that some transactions are missing, a correction will be requested, but it's an edge case
|
|
765
|
-
storage.store(data, (correction) => {
|
|
766
|
-
if (!coValue.hasVerifiedContent()) return;
|
|
767
|
-
|
|
768
|
-
const newContentPieces = coValue.verified.newContentSince(correction);
|
|
769
|
-
|
|
770
|
-
if (!newContentPieces) return;
|
|
743
|
+
private syncQueue = new LocalTransactionsSyncQueue((content) =>
|
|
744
|
+
this.syncContent(content),
|
|
745
|
+
);
|
|
746
|
+
syncHeader = this.syncQueue.syncHeader;
|
|
747
|
+
syncLocalTransaction = this.syncQueue.syncTransaction;
|
|
771
748
|
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
"Correction requested by storage after sending a correction content",
|
|
775
|
-
{
|
|
776
|
-
response,
|
|
777
|
-
knownState: coValue.knownState(),
|
|
778
|
-
},
|
|
779
|
-
);
|
|
780
|
-
});
|
|
781
|
-
});
|
|
782
|
-
}
|
|
749
|
+
syncContent(content: NewContentMessage) {
|
|
750
|
+
const coValue = this.local.getCoValue(content.id);
|
|
783
751
|
|
|
784
|
-
|
|
785
|
-
this.requestedSyncs.delete(coValue.id);
|
|
752
|
+
this.storeContent(content);
|
|
786
753
|
|
|
787
|
-
|
|
788
|
-
const knownState = this.local.storage.getKnownState(coValue.id);
|
|
789
|
-
const newContentPieces = coValue.verified.newContentSince(knownState);
|
|
790
|
-
|
|
791
|
-
this.storeCoValue(coValue, newContentPieces);
|
|
792
|
-
}
|
|
754
|
+
const contentKnownState = knownStateFromContent(content);
|
|
793
755
|
|
|
794
756
|
for (const peer of this.peersInPriorityOrder()) {
|
|
795
757
|
if (peer.closed) continue;
|
|
@@ -803,7 +765,11 @@ export class SyncManager {
|
|
|
803
765
|
continue;
|
|
804
766
|
}
|
|
805
767
|
|
|
806
|
-
this
|
|
768
|
+
// We assume that the peer already knows anything before this content
|
|
769
|
+
// Any eventual reconciliation will be handled through the known state messages exchange
|
|
770
|
+
this.trySendToPeer(peer, content);
|
|
771
|
+
peer.combineOptimisticWith(coValue.id, contentKnownState);
|
|
772
|
+
peer.trackToldKnownState(coValue.id);
|
|
807
773
|
}
|
|
808
774
|
|
|
809
775
|
for (const peer of this.getPeers()) {
|
|
@@ -811,6 +777,20 @@ export class SyncManager {
|
|
|
811
777
|
}
|
|
812
778
|
}
|
|
813
779
|
|
|
780
|
+
private storeContent(content: NewContentMessage) {
|
|
781
|
+
const storage = this.local.storage;
|
|
782
|
+
|
|
783
|
+
if (!storage) return;
|
|
784
|
+
|
|
785
|
+
// Try to store the content as-is for performance
|
|
786
|
+
// In case that some transactions are missing, a correction will be requested, but it's an edge case
|
|
787
|
+
storage.store(content, (correction) => {
|
|
788
|
+
return this.local
|
|
789
|
+
.getCoValue(content.id)
|
|
790
|
+
.verified?.newContentSince(correction);
|
|
791
|
+
});
|
|
792
|
+
}
|
|
793
|
+
|
|
814
794
|
waitForSyncWithPeer(peerId: PeerID, id: RawCoID, timeout: number) {
|
|
815
795
|
const { syncState } = this;
|
|
816
796
|
const currentSyncState = syncState.getCurrentSyncState(peerId, id);
|