cojson 0.20.9 → 0.20.10
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 +20 -0
- package/dist/PeerState.d.ts +2 -2
- package/dist/PeerState.d.ts.map +1 -1
- package/dist/PeerState.js +3 -3
- package/dist/PeerState.js.map +1 -1
- package/dist/StorageReconciliationAckTracker.d.ts +14 -0
- package/dist/StorageReconciliationAckTracker.d.ts.map +1 -0
- package/dist/StorageReconciliationAckTracker.js +72 -0
- package/dist/StorageReconciliationAckTracker.js.map +1 -0
- package/dist/SyncStateManager.js +2 -2
- package/dist/SyncStateManager.js.map +1 -1
- package/dist/coValueCore/coValueCore.d.ts +2 -1
- package/dist/coValueCore/coValueCore.d.ts.map +1 -1
- package/dist/coValueCore/coValueCore.js +43 -10
- package/dist/coValueCore/coValueCore.js.map +1 -1
- package/dist/coValues/coList.d.ts +2 -0
- package/dist/coValues/coList.d.ts.map +1 -1
- package/dist/coValues/coList.js +28 -0
- package/dist/coValues/coList.js.map +1 -1
- package/dist/coValues/group.d.ts +4 -1
- package/dist/coValues/group.d.ts.map +1 -1
- package/dist/coValues/group.js +15 -1
- package/dist/coValues/group.js.map +1 -1
- package/dist/config.d.ts +8 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +14 -0
- package/dist/config.js.map +1 -1
- package/dist/exports.d.ts +9 -1
- package/dist/exports.d.ts.map +1 -1
- package/dist/exports.js +5 -1
- package/dist/exports.js.map +1 -1
- package/dist/localNode.d.ts +7 -3
- package/dist/localNode.d.ts.map +1 -1
- package/dist/localNode.js +13 -5
- package/dist/localNode.js.map +1 -1
- package/dist/permissions.d.ts +1 -0
- package/dist/permissions.d.ts.map +1 -1
- package/dist/queue/LinkedList.d.ts +2 -0
- package/dist/queue/LinkedList.d.ts.map +1 -1
- package/dist/queue/LinkedList.js +7 -0
- package/dist/queue/LinkedList.js.map +1 -1
- package/dist/queue/OutgoingLoadQueue.d.ts +4 -1
- package/dist/queue/OutgoingLoadQueue.d.ts.map +1 -1
- package/dist/queue/OutgoingLoadQueue.js +41 -13
- package/dist/queue/OutgoingLoadQueue.js.map +1 -1
- package/dist/queue/PriorityBasedMessageQueue.d.ts +1 -0
- package/dist/queue/PriorityBasedMessageQueue.d.ts.map +1 -1
- package/dist/queue/PriorityBasedMessageQueue.js +11 -1
- package/dist/queue/PriorityBasedMessageQueue.js.map +1 -1
- package/dist/storage/knownState.d.ts +2 -0
- package/dist/storage/knownState.d.ts.map +1 -1
- package/dist/storage/knownState.js +11 -0
- package/dist/storage/knownState.js.map +1 -1
- package/dist/storage/sqlite/client.d.ts +10 -1
- package/dist/storage/sqlite/client.d.ts.map +1 -1
- package/dist/storage/sqlite/client.js +84 -0
- package/dist/storage/sqlite/client.js.map +1 -1
- package/dist/storage/sqlite/sqliteMigrations.d.ts.map +1 -1
- package/dist/storage/sqlite/sqliteMigrations.js +11 -0
- package/dist/storage/sqlite/sqliteMigrations.js.map +1 -1
- package/dist/storage/sqliteAsync/client.d.ts +10 -1
- package/dist/storage/sqliteAsync/client.d.ts.map +1 -1
- package/dist/storage/sqliteAsync/client.js +86 -0
- package/dist/storage/sqliteAsync/client.js.map +1 -1
- package/dist/storage/storageAsync.d.ts +9 -2
- package/dist/storage/storageAsync.d.ts.map +1 -1
- package/dist/storage/storageAsync.js +19 -0
- package/dist/storage/storageAsync.js.map +1 -1
- package/dist/storage/storageSync.d.ts +9 -2
- package/dist/storage/storageSync.d.ts.map +1 -1
- package/dist/storage/storageSync.js +20 -13
- package/dist/storage/storageSync.js.map +1 -1
- package/dist/storage/types.d.ts +64 -0
- package/dist/storage/types.d.ts.map +1 -1
- package/dist/storage/types.js.map +1 -1
- package/dist/sync.d.ts +44 -2
- package/dist/sync.d.ts.map +1 -1
- package/dist/sync.js +268 -44
- package/dist/sync.js.map +1 -1
- package/dist/tests/OutgoingLoadQueue.test.js +137 -39
- package/dist/tests/OutgoingLoadQueue.test.js.map +1 -1
- package/dist/tests/SQLiteClientAsync.test.js +1 -1
- package/dist/tests/SQLiteClientAsync.test.js.map +1 -1
- package/dist/tests/StorageApiAsync.test.js +138 -0
- package/dist/tests/StorageApiAsync.test.js.map +1 -1
- package/dist/tests/StorageApiSync.test.js +154 -0
- package/dist/tests/StorageApiSync.test.js.map +1 -1
- package/dist/tests/StorageReconciliationAckTracker.test.d.ts +2 -0
- package/dist/tests/StorageReconciliationAckTracker.test.d.ts.map +1 -0
- package/dist/tests/StorageReconciliationAckTracker.test.js +74 -0
- package/dist/tests/StorageReconciliationAckTracker.test.js.map +1 -0
- package/dist/tests/SyncStateManager.test.js +18 -0
- package/dist/tests/SyncStateManager.test.js.map +1 -1
- package/dist/tests/coList.test.js +112 -1
- package/dist/tests/coList.test.js.map +1 -1
- package/dist/tests/coValueCore.loadFromStorage.test.js +36 -0
- package/dist/tests/coValueCore.loadFromStorage.test.js.map +1 -1
- package/dist/tests/group.test.js +44 -0
- package/dist/tests/group.test.js.map +1 -1
- package/dist/tests/knownState.lazyLoading.test.js +6 -0
- package/dist/tests/knownState.lazyLoading.test.js.map +1 -1
- package/dist/tests/messagesTestUtils.d.ts.map +1 -1
- package/dist/tests/messagesTestUtils.js +4 -0
- package/dist/tests/messagesTestUtils.js.map +1 -1
- package/dist/tests/sync.concurrentLoad.test.js +333 -1
- package/dist/tests/sync.concurrentLoad.test.js.map +1 -1
- package/dist/tests/sync.garbageCollection.test.js +4 -0
- package/dist/tests/sync.garbageCollection.test.js.map +1 -1
- package/dist/tests/sync.load.test.js +19 -0
- package/dist/tests/sync.load.test.js.map +1 -1
- package/dist/tests/sync.mesh.test.js +1 -0
- package/dist/tests/sync.mesh.test.js.map +1 -1
- package/dist/tests/sync.multipleServers.test.js +41 -3
- package/dist/tests/sync.multipleServers.test.js.map +1 -1
- package/dist/tests/sync.storage.test.js +2 -0
- package/dist/tests/sync.storage.test.js.map +1 -1
- package/dist/tests/sync.storageAsync.test.js +1 -0
- package/dist/tests/sync.storageAsync.test.js.map +1 -1
- package/dist/tests/sync.storageReconciliation.test.d.ts +2 -0
- package/dist/tests/sync.storageReconciliation.test.d.ts.map +1 -0
- package/dist/tests/sync.storageReconciliation.test.js +501 -0
- package/dist/tests/sync.storageReconciliation.test.js.map +1 -0
- package/dist/tests/testUtils.d.ts +1 -0
- package/dist/tests/testUtils.d.ts.map +1 -1
- package/dist/tests/testUtils.js +3 -2
- package/dist/tests/testUtils.js.map +1 -1
- package/package.json +4 -4
- package/src/PeerState.ts +10 -3
- package/src/StorageReconciliationAckTracker.ts +83 -0
- package/src/SyncStateManager.ts +3 -3
- package/src/coValueCore/coValueCore.ts +47 -16
- package/src/coValues/coList.ts +23 -0
- package/src/coValues/group.ts +18 -0
- package/src/config.ts +18 -0
- package/src/exports.ts +8 -0
- package/src/localNode.ts +18 -0
- package/src/permissions.ts +1 -1
- package/src/queue/LinkedList.ts +10 -0
- package/src/queue/OutgoingLoadQueue.ts +57 -15
- package/src/queue/PriorityBasedMessageQueue.ts +15 -1
- package/src/storage/knownState.ts +14 -0
- package/src/storage/sqlite/client.ts +128 -0
- package/src/storage/sqlite/sqliteMigrations.ts +11 -0
- package/src/storage/sqliteAsync/client.ts +139 -0
- package/src/storage/storageAsync.ts +37 -0
- package/src/storage/storageSync.ts +41 -16
- package/src/storage/types.ts +110 -0
- package/src/sync.ts +311 -14
- package/src/tests/OutgoingLoadQueue.test.ts +226 -59
- package/src/tests/SQLiteClientAsync.test.ts +1 -1
- package/src/tests/StorageApiAsync.test.ts +161 -1
- package/src/tests/StorageApiSync.test.ts +176 -0
- package/src/tests/StorageReconciliationAckTracker.test.ts +99 -0
- package/src/tests/SyncStateManager.test.ts +25 -0
- package/src/tests/coList.test.ts +138 -0
- package/src/tests/coValueCore.loadFromStorage.test.ts +72 -1
- package/src/tests/group.test.ts +87 -0
- package/src/tests/knownState.lazyLoading.test.ts +36 -1
- package/src/tests/messagesTestUtils.ts +4 -0
- package/src/tests/sync.concurrentLoad.test.ts +491 -0
- package/src/tests/sync.garbageCollection.test.ts +4 -0
- package/src/tests/sync.load.test.ts +26 -0
- package/src/tests/sync.mesh.test.ts +1 -0
- package/src/tests/sync.multipleServers.test.ts +60 -2
- package/src/tests/sync.storage.test.ts +2 -0
- package/src/tests/sync.storageAsync.test.ts +1 -0
- package/src/tests/sync.storageReconciliation.test.ts +697 -0
- package/src/tests/testUtils.ts +10 -1
|
@@ -29,6 +29,7 @@ import type {
|
|
|
29
29
|
SignatureAfterRow,
|
|
30
30
|
StoredCoValueRow,
|
|
31
31
|
StoredSessionRow,
|
|
32
|
+
StorageReconciliationAcquireResult,
|
|
32
33
|
} from "./types.js";
|
|
33
34
|
import { DeletedCoValuesEraserScheduler } from "./DeletedCoValuesEraserScheduler.js";
|
|
34
35
|
import {
|
|
@@ -68,26 +69,48 @@ export class StorageApiSync implements StorageAPI {
|
|
|
68
69
|
return this.knownStates.getKnownState(id);
|
|
69
70
|
}
|
|
70
71
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
72
|
+
getCoValueIDs(
|
|
73
|
+
limit: number,
|
|
74
|
+
offset: number,
|
|
75
|
+
callback: (batch: { id: RawCoID }[]) => void,
|
|
74
76
|
): void {
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
callback(cached);
|
|
79
|
-
return;
|
|
80
|
-
}
|
|
77
|
+
const batch = this.dbClient.getCoValueIDs(limit, offset);
|
|
78
|
+
callback(batch);
|
|
79
|
+
}
|
|
81
80
|
|
|
82
|
-
|
|
83
|
-
|
|
81
|
+
getCoValueCount(callback: (count: number) => void): void {
|
|
82
|
+
callback(this.dbClient.getCoValueCount());
|
|
83
|
+
}
|
|
84
84
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
85
|
+
tryAcquireStorageReconciliationLock(
|
|
86
|
+
sessionId: SessionID,
|
|
87
|
+
peerId: PeerID,
|
|
88
|
+
callback: (result: StorageReconciliationAcquireResult) => void,
|
|
89
|
+
): void {
|
|
90
|
+
const result = this.dbClient.tryAcquireStorageReconciliationLock(
|
|
91
|
+
sessionId,
|
|
92
|
+
peerId,
|
|
93
|
+
);
|
|
94
|
+
callback(result);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
renewStorageReconciliationLock(
|
|
98
|
+
sessionId: SessionID,
|
|
99
|
+
peerId: PeerID,
|
|
100
|
+
offset: number,
|
|
101
|
+
): void {
|
|
102
|
+
this.dbClient.renewStorageReconciliationLock(sessionId, peerId, offset);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
releaseStorageReconciliationLock(sessionId: SessionID, peerId: PeerID): void {
|
|
106
|
+
this.dbClient.releaseStorageReconciliationLock(sessionId, peerId);
|
|
107
|
+
}
|
|
89
108
|
|
|
90
|
-
|
|
109
|
+
loadKnownState(
|
|
110
|
+
id: string,
|
|
111
|
+
callback: (knownState: CoValueKnownState | undefined) => void,
|
|
112
|
+
): void {
|
|
113
|
+
callback(this.dbClient.getCoValueKnownState(id));
|
|
91
114
|
}
|
|
92
115
|
|
|
93
116
|
async load(
|
|
@@ -515,11 +538,13 @@ export class StorageApiSync implements StorageAPI {
|
|
|
515
538
|
|
|
516
539
|
onCoValueUnmounted(id: RawCoID): void {
|
|
517
540
|
this.inMemoryCoValues.delete(id);
|
|
541
|
+
this.knownStates.deleteKnownState(id);
|
|
518
542
|
}
|
|
519
543
|
|
|
520
544
|
close() {
|
|
521
545
|
this.deletedCoValuesEraserScheduler?.dispose();
|
|
522
546
|
this.inMemoryCoValues.clear();
|
|
547
|
+
this.knownStates.clear();
|
|
523
548
|
return undefined;
|
|
524
549
|
}
|
|
525
550
|
}
|
package/src/storage/types.ts
CHANGED
|
@@ -13,6 +13,10 @@ export type CorrectionCallback = (
|
|
|
13
13
|
correction: CoValueKnownState,
|
|
14
14
|
) => NewContentMessage[] | undefined;
|
|
15
15
|
|
|
16
|
+
export type StorageReconciliationAcquireResult =
|
|
17
|
+
| { acquired: true; lastProcessedOffset: number }
|
|
18
|
+
| { acquired: false; reason: "not_due" | "lock_held" };
|
|
19
|
+
|
|
16
20
|
/**
|
|
17
21
|
* Deletion work queue status for `deletedCoValues` (SQLite).
|
|
18
22
|
*
|
|
@@ -86,6 +90,52 @@ export interface StorageAPI {
|
|
|
86
90
|
*/
|
|
87
91
|
stopTrackingSyncState(id: RawCoID): void;
|
|
88
92
|
|
|
93
|
+
/**
|
|
94
|
+
* Get a batch of CoValue IDs from storage.
|
|
95
|
+
* Used for full storage reconciliation. Call repeatedly with increasing offset
|
|
96
|
+
* until the returned batch has length < limit (or 0) to enumerate all IDs.
|
|
97
|
+
* @param limit - Max number of IDs to return (e.g. 100).
|
|
98
|
+
* @param offset - Number of IDs to skip (0 for first batch).
|
|
99
|
+
* @param callback - Called with the batch. Ordering must be stable (e.g. by id).
|
|
100
|
+
*/
|
|
101
|
+
getCoValueIDs(
|
|
102
|
+
limit: number,
|
|
103
|
+
offset: number,
|
|
104
|
+
callback: (batch: { id: RawCoID }[]) => void,
|
|
105
|
+
): void;
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Get the total number of CoValues in storage.
|
|
109
|
+
*/
|
|
110
|
+
getCoValueCount(callback: (count: number) => void): void;
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Try to acquire the storage reconciliation lock for a given peer.
|
|
114
|
+
* Atomically checks if reconciliation is due for this peer (lastRun older than 30 days or missing)
|
|
115
|
+
* and if no other process/tab holds the lock for this peer, then acquires it.
|
|
116
|
+
*/
|
|
117
|
+
tryAcquireStorageReconciliationLock(
|
|
118
|
+
sessionId: SessionID,
|
|
119
|
+
peerId: PeerID,
|
|
120
|
+
callback: (result: StorageReconciliationAcquireResult) => void,
|
|
121
|
+
): void;
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Update the last processed offset for the storage reconciliation lock held for this peer.
|
|
125
|
+
* Only call after a batch has been acked; used to resume from this offset on interrupt.
|
|
126
|
+
*/
|
|
127
|
+
renewStorageReconciliationLock(
|
|
128
|
+
sessionId: SessionID,
|
|
129
|
+
peerId: PeerID,
|
|
130
|
+
offset: number,
|
|
131
|
+
): void;
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Release the storage reconciliation lock for a peer and record completion. Only call on successful completion.
|
|
135
|
+
* On failure/interrupt, do not call; the lock expires after LOCK_TTL_MS and another process can retry for this peer.
|
|
136
|
+
*/
|
|
137
|
+
releaseStorageReconciliationLock(sessionId: SessionID, peerId: PeerID): void;
|
|
138
|
+
|
|
89
139
|
/**
|
|
90
140
|
* Load only the knownState (header presence + session counters) for a CoValue.
|
|
91
141
|
* This is more efficient than load() when we only need to check if a peer needs new content.
|
|
@@ -136,6 +186,15 @@ export type SignatureAfterRow = {
|
|
|
136
186
|
signature: Signature;
|
|
137
187
|
};
|
|
138
188
|
|
|
189
|
+
export type StorageReconciliationLockRow = {
|
|
190
|
+
key: string;
|
|
191
|
+
holderSessionId: SessionID;
|
|
192
|
+
acquiredAt: number;
|
|
193
|
+
releasedAt?: number;
|
|
194
|
+
/** Offset up to which all batches have been acked; used to resume after interrupt. */
|
|
195
|
+
lastProcessedOffset: number;
|
|
196
|
+
};
|
|
197
|
+
|
|
139
198
|
export interface DBTransactionInterfaceAsync {
|
|
140
199
|
getSingleCoValueSession(
|
|
141
200
|
coValueRowId: number,
|
|
@@ -176,6 +235,14 @@ export interface DBTransactionInterfaceAsync {
|
|
|
176
235
|
deleteCoValueContent(
|
|
177
236
|
coValueRow: Pick<StoredCoValueRow, "rowID" | "id">,
|
|
178
237
|
): Promise<unknown>;
|
|
238
|
+
|
|
239
|
+
getStorageReconciliationLock(
|
|
240
|
+
key: string,
|
|
241
|
+
): Promise<StorageReconciliationLockRow | undefined>;
|
|
242
|
+
|
|
243
|
+
putStorageReconciliationLock(
|
|
244
|
+
entry: StorageReconciliationLockRow,
|
|
245
|
+
): Promise<void>;
|
|
179
246
|
}
|
|
180
247
|
|
|
181
248
|
export interface DBClientInterfaceAsync {
|
|
@@ -232,6 +299,26 @@ export interface DBClientInterfaceAsync {
|
|
|
232
299
|
getCoValueKnownState(
|
|
233
300
|
coValueId: string,
|
|
234
301
|
): Promise<CoValueKnownState | undefined>;
|
|
302
|
+
|
|
303
|
+
getCoValueIDs(limit: number, offset: number): Promise<{ id: RawCoID }[]>;
|
|
304
|
+
|
|
305
|
+
getCoValueCount(): Promise<number>;
|
|
306
|
+
|
|
307
|
+
tryAcquireStorageReconciliationLock(
|
|
308
|
+
sessionId: SessionID,
|
|
309
|
+
peerId: PeerID,
|
|
310
|
+
): Promise<StorageReconciliationAcquireResult>;
|
|
311
|
+
|
|
312
|
+
renewStorageReconciliationLock(
|
|
313
|
+
sessionId: SessionID,
|
|
314
|
+
peerId: PeerID,
|
|
315
|
+
offset: number,
|
|
316
|
+
): Promise<void>;
|
|
317
|
+
|
|
318
|
+
releaseStorageReconciliationLock(
|
|
319
|
+
sessionId: SessionID,
|
|
320
|
+
peerId: PeerID,
|
|
321
|
+
): Promise<void>;
|
|
235
322
|
}
|
|
236
323
|
|
|
237
324
|
export interface DBTransactionInterfaceSync {
|
|
@@ -270,6 +357,12 @@ export interface DBTransactionInterfaceSync {
|
|
|
270
357
|
idx: number;
|
|
271
358
|
signature: Signature;
|
|
272
359
|
}): number | undefined | unknown;
|
|
360
|
+
|
|
361
|
+
getStorageReconciliationLock(
|
|
362
|
+
key: string,
|
|
363
|
+
): StorageReconciliationLockRow | undefined;
|
|
364
|
+
|
|
365
|
+
putStorageReconciliationLock(entry: StorageReconciliationLockRow): void;
|
|
273
366
|
}
|
|
274
367
|
|
|
275
368
|
export interface DBClientInterfaceSync {
|
|
@@ -317,4 +410,21 @@ export interface DBClientInterfaceSync {
|
|
|
317
410
|
* Returns undefined if the CoValue doesn't exist.
|
|
318
411
|
*/
|
|
319
412
|
getCoValueKnownState(coValueId: string): CoValueKnownState | undefined;
|
|
413
|
+
|
|
414
|
+
getCoValueIDs(limit: number, offset: number): { id: RawCoID }[];
|
|
415
|
+
|
|
416
|
+
getCoValueCount(): number;
|
|
417
|
+
|
|
418
|
+
tryAcquireStorageReconciliationLock(
|
|
419
|
+
sessionId: SessionID,
|
|
420
|
+
peerId: PeerID,
|
|
421
|
+
): StorageReconciliationAcquireResult;
|
|
422
|
+
|
|
423
|
+
renewStorageReconciliationLock(
|
|
424
|
+
sessionId: SessionID,
|
|
425
|
+
peerId: PeerID,
|
|
426
|
+
offset: number,
|
|
427
|
+
): void;
|
|
428
|
+
|
|
429
|
+
releaseStorageReconciliationLock(sessionId: SessionID, peerId: PeerID): void;
|
|
320
430
|
}
|