@tanstack/db-sqlite-persistence-core 0.2.17 → 0.2.18
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/dist/cjs/persisted.cjs +106 -37
- package/dist/cjs/persisted.cjs.map +1 -1
- package/dist/esm/persisted.js +107 -38
- package/dist/esm/persisted.js.map +1 -1
- package/package.json +2 -2
- package/src/persisted.ts +114 -40
package/dist/esm/persisted.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { safeRandomUUID, withCollectionConfigFactory, compileSingleRowExpression, toBooleanPredicate } from "@tanstack/db";
|
|
1
|
+
import { safeRandomUUID, withCollectionConfigFactory, SyncTransactionAbortedError, compileSingleRowExpression, toBooleanPredicate } from "@tanstack/db";
|
|
2
2
|
import { InvalidPersistedCollectionCoordinatorError, InvalidPersistedCollectionConfigError, InvalidSyncConfigError, InvalidPersistedStorageKeyError, InvalidPersistedStorageKeyEncodingError, InvalidPersistenceAdapterError } from "./errors.js";
|
|
3
3
|
const REQUIRED_COORDINATOR_METHODS = [
|
|
4
4
|
`getNodeId`,
|
|
@@ -231,6 +231,8 @@ class PersistedCollectionRuntime {
|
|
|
231
231
|
this.startupMetadataPromise = null;
|
|
232
232
|
this.startPromise = null;
|
|
233
233
|
this.internalApplyDepth = 0;
|
|
234
|
+
this.appliedReceiptSequence = 0;
|
|
235
|
+
this.pendingAppliedReceipts = /* @__PURE__ */ new Map();
|
|
234
236
|
this.isHydrating = false;
|
|
235
237
|
this.coordinatorUnsubscribe = null;
|
|
236
238
|
this.indexAddedUnsubscribe = null;
|
|
@@ -245,7 +247,29 @@ class PersistedCollectionRuntime {
|
|
|
245
247
|
this.localRowVersion = 0;
|
|
246
248
|
}
|
|
247
249
|
setSyncControls(syncControls) {
|
|
248
|
-
|
|
250
|
+
const commit = syncControls.commit;
|
|
251
|
+
this.syncControls = {
|
|
252
|
+
...syncControls,
|
|
253
|
+
commit: commit ? (signal) => this.trackAppliedReceipt(commit(signal)) : null
|
|
254
|
+
};
|
|
255
|
+
}
|
|
256
|
+
trackAppliedReceipt(receipt) {
|
|
257
|
+
const sequence = ++this.appliedReceiptSequence;
|
|
258
|
+
if (receipt === true) {
|
|
259
|
+
return true;
|
|
260
|
+
}
|
|
261
|
+
this.pendingAppliedReceipts.set(sequence, receipt);
|
|
262
|
+
const removeReceipt = () => this.pendingAppliedReceipts.delete(sequence);
|
|
263
|
+
void receipt.then(removeReceipt, removeReceipt);
|
|
264
|
+
return receipt;
|
|
265
|
+
}
|
|
266
|
+
async waitForAppliedReceiptsAfter(cursor) {
|
|
267
|
+
await Promise.all(
|
|
268
|
+
Array.from(
|
|
269
|
+
this.pendingAppliedReceipts,
|
|
270
|
+
([sequence, receipt]) => sequence > cursor ? receipt : void 0
|
|
271
|
+
)
|
|
272
|
+
);
|
|
249
273
|
}
|
|
250
274
|
clearSyncControls() {
|
|
251
275
|
this.syncControls = {
|
|
@@ -300,9 +324,11 @@ class PersistedCollectionRuntime {
|
|
|
300
324
|
await this.bootstrapPersistedIndexes(indexBootstrapSnapshot);
|
|
301
325
|
if (this.syncMode !== `on-demand`) {
|
|
302
326
|
this.activeSubsets.set(this.getSubsetKey({}), {});
|
|
327
|
+
const appliedCursor = this.appliedReceiptSequence;
|
|
303
328
|
await this.applyMutex.run(
|
|
304
329
|
() => this.hydrateSubsetUnsafe({}, { requestRemoteEnsure: false })
|
|
305
330
|
);
|
|
331
|
+
await this.waitForAppliedReceiptsAfter(appliedCursor);
|
|
306
332
|
}
|
|
307
333
|
}
|
|
308
334
|
async loadStartupMetadataInternal() {
|
|
@@ -351,16 +377,18 @@ class PersistedCollectionRuntime {
|
|
|
351
377
|
}
|
|
352
378
|
async loadSubset(options, upstreamLoadSubset) {
|
|
353
379
|
this.activeSubsets.set(this.getSubsetKey(options), options);
|
|
380
|
+
const appliedCursor = this.appliedReceiptSequence;
|
|
354
381
|
await this.applyMutex.run(
|
|
355
382
|
() => this.hydrateSubsetUnsafe(options, {
|
|
356
383
|
requestRemoteEnsure: this.mode === `sync-present`
|
|
357
384
|
})
|
|
358
385
|
);
|
|
386
|
+
await this.waitForAppliedReceiptsAfter(appliedCursor);
|
|
359
387
|
if (upstreamLoadSubset) {
|
|
360
388
|
try {
|
|
361
389
|
const maybePromise = upstreamLoadSubset(options);
|
|
362
390
|
if (maybePromise instanceof Promise) {
|
|
363
|
-
maybePromise.catch((error) => {
|
|
391
|
+
await maybePromise.catch((error) => {
|
|
364
392
|
console.warn(
|
|
365
393
|
`Failed to load remote subset in persisted wrapper:`,
|
|
366
394
|
error
|
|
@@ -483,6 +511,9 @@ class PersistedCollectionRuntime {
|
|
|
483
511
|
}
|
|
484
512
|
this.pendingRemoteSubsetEnsures.clear();
|
|
485
513
|
this.activeSubsets.clear();
|
|
514
|
+
for (const transaction of this.queuedHydrationTransactions) {
|
|
515
|
+
transaction.rejectApplied?.(new SyncTransactionAbortedError());
|
|
516
|
+
}
|
|
486
517
|
this.queuedHydrationTransactions.length = 0;
|
|
487
518
|
this.queuedTxCommitted.length = 0;
|
|
488
519
|
this.clearSyncControls();
|
|
@@ -490,7 +521,7 @@ class PersistedCollectionRuntime {
|
|
|
490
521
|
withInternalApply(task) {
|
|
491
522
|
this.internalApplyDepth++;
|
|
492
523
|
try {
|
|
493
|
-
task();
|
|
524
|
+
return task();
|
|
494
525
|
} finally {
|
|
495
526
|
this.internalApplyDepth--;
|
|
496
527
|
}
|
|
@@ -586,26 +617,41 @@ class PersistedCollectionRuntime {
|
|
|
586
617
|
if (!transaction) {
|
|
587
618
|
continue;
|
|
588
619
|
}
|
|
589
|
-
|
|
620
|
+
try {
|
|
621
|
+
await this.applyBufferedSyncTransactionUnsafe(transaction);
|
|
622
|
+
} catch (error) {
|
|
623
|
+
transaction.rejectApplied?.(error);
|
|
624
|
+
for (const abandoned of this.queuedHydrationTransactions) {
|
|
625
|
+
abandoned.rejectApplied?.(error);
|
|
626
|
+
}
|
|
627
|
+
this.queuedHydrationTransactions.length = 0;
|
|
628
|
+
throw error;
|
|
629
|
+
}
|
|
590
630
|
}
|
|
591
631
|
}
|
|
592
632
|
async applyBufferedSyncTransactionUnsafe(transaction) {
|
|
593
|
-
if (
|
|
633
|
+
if (transaction.signal?.aborted) {
|
|
634
|
+
transaction.rejectApplied?.(new SyncTransactionAbortedError());
|
|
635
|
+
return;
|
|
636
|
+
}
|
|
637
|
+
const { begin, write, commit, truncate, metadata } = this.syncControls;
|
|
638
|
+
if (!begin || !write || !commit) {
|
|
639
|
+
transaction.rejectApplied?.(new SyncTransactionAbortedError());
|
|
594
640
|
return;
|
|
595
641
|
}
|
|
596
642
|
const applyToCollection = () => {
|
|
597
|
-
|
|
643
|
+
begin();
|
|
598
644
|
if (transaction.truncate) {
|
|
599
|
-
|
|
645
|
+
truncate?.();
|
|
600
646
|
}
|
|
601
647
|
for (const operation of transaction.operations) {
|
|
602
648
|
if (operation.type === `delete`) {
|
|
603
|
-
|
|
649
|
+
write({
|
|
604
650
|
type: `delete`,
|
|
605
651
|
key: operation.key
|
|
606
652
|
});
|
|
607
653
|
} else {
|
|
608
|
-
|
|
654
|
+
write({
|
|
609
655
|
type: `update`,
|
|
610
656
|
value: operation.value,
|
|
611
657
|
metadata: operation.metadata
|
|
@@ -614,26 +660,33 @@ class PersistedCollectionRuntime {
|
|
|
614
660
|
}
|
|
615
661
|
for (const [key, metadataWrite] of transaction.rowMetadataWrites) {
|
|
616
662
|
if (metadataWrite.type === `delete`) {
|
|
617
|
-
|
|
663
|
+
metadata?.row.delete(key);
|
|
618
664
|
} else {
|
|
619
|
-
|
|
665
|
+
metadata?.row.set(key, metadataWrite.value);
|
|
620
666
|
}
|
|
621
667
|
}
|
|
622
668
|
for (const [key, metadataWrite] of transaction.collectionMetadataWrites) {
|
|
623
669
|
if (metadataWrite.type === `delete`) {
|
|
624
|
-
|
|
670
|
+
metadata?.collection.delete(key);
|
|
625
671
|
} else {
|
|
626
|
-
|
|
672
|
+
metadata?.collection.set(key, metadataWrite.value);
|
|
627
673
|
}
|
|
628
674
|
}
|
|
629
|
-
|
|
675
|
+
return commit(transaction.signal);
|
|
630
676
|
};
|
|
631
|
-
|
|
632
|
-
this.withInternalApply(applyToCollection);
|
|
633
|
-
|
|
677
|
+
try {
|
|
678
|
+
const applied = transaction.internal ? this.withInternalApply(applyToCollection) : applyToCollection();
|
|
679
|
+
if (applied !== true) {
|
|
680
|
+
await applied;
|
|
681
|
+
}
|
|
682
|
+
if (!transaction.internal) {
|
|
683
|
+
await this.persistAndBroadcastExternalSyncTransactionUnsafe(transaction);
|
|
684
|
+
}
|
|
685
|
+
transaction.resolveApplied?.();
|
|
686
|
+
} catch (error) {
|
|
687
|
+
transaction.rejectApplied?.(error);
|
|
688
|
+
throw error;
|
|
634
689
|
}
|
|
635
|
-
applyToCollection();
|
|
636
|
-
await this.persistAndBroadcastExternalSyncTransactionUnsafe(transaction);
|
|
637
690
|
}
|
|
638
691
|
async persistAndBroadcastExternalSyncTransactionUnsafe(transaction) {
|
|
639
692
|
if (transaction.internal) {
|
|
@@ -1450,37 +1503,53 @@ function createWrappedSyncConfig(sourceSyncConfig, runtime) {
|
|
|
1450
1503
|
params.truncate();
|
|
1451
1504
|
}
|
|
1452
1505
|
},
|
|
1453
|
-
commit: () => {
|
|
1506
|
+
commit: (signal) => {
|
|
1454
1507
|
const openTransaction = transactionStack.pop();
|
|
1455
1508
|
if (!openTransaction) {
|
|
1456
|
-
params.commit();
|
|
1457
|
-
return;
|
|
1509
|
+
return params.commit(signal);
|
|
1458
1510
|
}
|
|
1459
1511
|
if (openTransaction.queuedBecauseHydrating) {
|
|
1512
|
+
if (signal?.aborted) {
|
|
1513
|
+
const aborted = Promise.reject(new SyncTransactionAbortedError());
|
|
1514
|
+
void aborted.catch(() => void 0);
|
|
1515
|
+
return aborted;
|
|
1516
|
+
}
|
|
1517
|
+
let resolveApplied;
|
|
1518
|
+
let rejectApplied;
|
|
1519
|
+
const applied2 = new Promise((resolve, reject) => {
|
|
1520
|
+
resolveApplied = resolve;
|
|
1521
|
+
rejectApplied = reject;
|
|
1522
|
+
});
|
|
1523
|
+
void applied2.catch(() => void 0);
|
|
1460
1524
|
runtime.queueHydrationBufferedTransaction({
|
|
1461
1525
|
operations: openTransaction.operations,
|
|
1462
1526
|
rowMetadataWrites: openTransaction.rowMetadataWrites,
|
|
1463
1527
|
collectionMetadataWrites: openTransaction.collectionMetadataWrites,
|
|
1464
1528
|
truncate: openTransaction.truncate,
|
|
1465
|
-
internal: openTransaction.internal
|
|
1529
|
+
internal: openTransaction.internal,
|
|
1530
|
+
signal,
|
|
1531
|
+
resolveApplied,
|
|
1532
|
+
rejectApplied
|
|
1466
1533
|
});
|
|
1467
|
-
return;
|
|
1534
|
+
return applied2;
|
|
1468
1535
|
}
|
|
1469
|
-
params.commit();
|
|
1536
|
+
const applied = params.commit(signal);
|
|
1470
1537
|
if (!openTransaction.internal) {
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1538
|
+
const persistAfterApplication = async () => {
|
|
1539
|
+
if (applied !== true) await applied;
|
|
1540
|
+
await runtime.persistAndBroadcastExternalSyncTransaction({
|
|
1541
|
+
operations: openTransaction.operations,
|
|
1542
|
+
rowMetadataWrites: openTransaction.rowMetadataWrites,
|
|
1543
|
+
collectionMetadataWrites: openTransaction.collectionMetadataWrites,
|
|
1544
|
+
truncate: openTransaction.truncate,
|
|
1545
|
+
internal: false
|
|
1546
|
+
});
|
|
1547
|
+
};
|
|
1548
|
+
const persisted = persistAfterApplication();
|
|
1549
|
+
void persisted.catch(() => void 0);
|
|
1550
|
+
return persisted;
|
|
1483
1551
|
}
|
|
1552
|
+
return applied;
|
|
1484
1553
|
}
|
|
1485
1554
|
};
|
|
1486
1555
|
let sourceResult = {};
|