@tanstack/db-sqlite-persistence-core 0.4.3 → 0.4.5

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/README.md CHANGED
@@ -260,12 +260,20 @@ source publication and its durable suffix. A source may mark a transaction
260
260
  optimistic layer. The wrapper still gives that transaction one FIFO turn and
261
261
  writes its durable suffix before admitting the next source turn.
262
262
 
263
- The wrapper deliberately rejects schedules that would require a second
264
- ordering mechanism. An `immediate` source transaction cannot enter while an
265
- earlier normal source publication is waiting, and a source transaction cannot
266
- cross a hydration cycle. These cases throw
267
- `InvalidPersistedCollectionConfigError` instead of reordering data or waiting
268
- in a dependency cycle.
263
+ Persisted rows establish a baseline for newer changes from the sync adapter.
264
+ Once an ordinary sync transaction is accepted at `commit()`, queued reads of
265
+ that baseline cannot revoke acceptance. This includes subset reads and rereads
266
+ requested by coordinator reset or full-reload notifications. This rule assumes
267
+ a compatible baseline; it does not authorize using an invalidated resume point.
268
+ A truncate replay replaces earlier source rows in the same sync run. Sync
269
+ transactions ordered after that replacement apply to the replacement.
270
+
271
+ An `immediate` sync transaction cannot enter while an earlier normal source
272
+ publication is waiting. The wrapper also currently rejects a sync transaction
273
+ that remains open across another persistence read. These admission restrictions
274
+ throw `InvalidPersistedCollectionConfigError`; an internal wait after accepted
275
+ `commit()` is not an admission failure. The open-transaction restriction is
276
+ separate from the accepted-transaction precedence rule.
269
277
 
270
278
  ### Atomic resume snapshots
271
279
 
@@ -1 +1 @@
1
- {"version":3,"file":"errors.cjs","sources":["../../src/errors.ts"],"sourcesContent":["import { TanStackDBError } from '@tanstack/db'\n\nexport class PersistedCollectionCoreError extends TanStackDBError {\n constructor(message: string) {\n super(message)\n this.name = `PersistedCollectionCoreError`\n }\n}\n\nexport class InvalidPersistedCollectionConfigError extends PersistedCollectionCoreError {\n constructor(message: string) {\n super(message)\n this.name = `InvalidPersistedCollectionConfigError`\n }\n}\n\nexport class InvalidSyncConfigError extends InvalidPersistedCollectionConfigError {\n constructor(details?: string) {\n super(\n details\n ? `Invalid sync config: ${details}`\n : `Invalid sync config: expected an object with a callable sync function`,\n )\n this.name = `InvalidSyncConfigError`\n }\n}\n\nexport class InvalidPersistedCollectionCoordinatorError extends InvalidPersistedCollectionConfigError {\n constructor(methodName: string) {\n super(\n `Invalid persisted collection coordinator: missing required \"${methodName}\" method`,\n )\n this.name = `InvalidPersistedCollectionCoordinatorError`\n }\n}\n\nexport class InvalidPersistenceAdapterError extends InvalidPersistedCollectionConfigError {\n constructor(methodName: string) {\n super(\n `Invalid persistence adapter: missing required \"${methodName}\" method`,\n )\n this.name = `InvalidPersistenceAdapterError`\n }\n}\n\nexport type PersistedCollectionDurabilityErrorOptions = {\n cause?: unknown\n code?: unknown\n path?: unknown\n}\n\nexport class PersistedCollectionDurabilityError extends PersistedCollectionCoreError {\n override readonly cause: unknown\n readonly code: unknown\n readonly path: unknown\n\n constructor(\n message: string,\n options: PersistedCollectionDurabilityErrorOptions = {},\n ) {\n super(message)\n this.name = `PersistedCollectionDurabilityError`\n this.cause = options.cause\n this.code = options.code\n this.path = options.path\n }\n}\n\nexport function toPersistedCollectionDurabilityError(\n collectionId: string,\n cause: unknown,\n): PersistedCollectionDurabilityError {\n if (cause instanceof PersistedCollectionDurabilityError) {\n return cause\n }\n\n const details =\n typeof cause === `object` && cause !== null\n ? (cause as Record<string, unknown>)\n : undefined\n const message = cause instanceof Error ? cause.message : String(cause)\n return new PersistedCollectionDurabilityError(\n `Failed to durably persist collection \"${collectionId}\": ${message}`,\n {\n cause,\n code: details?.code,\n path: details?.path,\n },\n )\n}\n\nexport type IndeterminateCommitRequestType =\n | `rpc:applyLocalMutations:req`\n | `rpc:applyCommittedTx:req`\n\nexport type IndeterminateCommitErrorOptions = {\n collectionId: string\n requestType: IndeterminateCommitRequestType\n previousLeaderId: string | null\n previousTerm: number | null\n currentLeaderId: string | null\n currentTerm: number | null\n cause: unknown\n}\n\nexport class IndeterminateCommitError extends PersistedCollectionCoreError {\n readonly code: `INDETERMINATE_COMMIT` = `INDETERMINATE_COMMIT`\n readonly collectionId: string\n readonly requestType: IndeterminateCommitRequestType\n readonly previousLeaderId: string | null\n readonly previousTerm: number | null\n readonly currentLeaderId: string | null\n readonly currentTerm: number | null\n override readonly cause: unknown\n\n constructor(options: IndeterminateCommitErrorOptions) {\n super(\n `Commit outcome is indeterminate for collection \"${options.collectionId}\": ${options.requestType} crossed leadership from ${formatLeader(options.previousLeaderId, options.previousTerm)} to ${formatLeader(options.currentLeaderId, options.currentTerm)}`,\n )\n this.name = `IndeterminateCommitError`\n this.collectionId = options.collectionId\n this.requestType = options.requestType\n this.previousLeaderId = options.previousLeaderId\n this.previousTerm = options.previousTerm\n this.currentLeaderId = options.currentLeaderId\n this.currentTerm = options.currentTerm\n this.cause = options.cause\n }\n}\n\nfunction formatLeader(leaderId: string | null, term: number | null): string {\n return `${leaderId ?? `unknown leader`} (term ${term ?? `unknown`})`\n}\n\nexport class DuplicateRemoteSubsetOwnerError extends PersistedCollectionCoreError {\n readonly collectionId: string\n\n constructor(collectionId: string) {\n super(\n `A remote subset owner is already registered for collection \"${collectionId}\"`,\n )\n this.name = `DuplicateRemoteSubsetOwnerError`\n this.collectionId = collectionId\n }\n}\n\nexport class RetryableRemoteSubsetAcquisitionError extends PersistedCollectionCoreError {\n override readonly cause: unknown\n\n constructor(message: string, cause?: unknown) {\n super(message)\n this.name = `RetryableRemoteSubsetAcquisitionError`\n this.cause = cause\n }\n}\n\nexport class InvalidPersistedStorageKeyError extends InvalidPersistedCollectionConfigError {\n constructor(key: string | number) {\n super(\n `Invalid persisted storage key \"${String(key)}\": numeric keys must be finite`,\n )\n this.name = `InvalidPersistedStorageKeyError`\n }\n}\n\nexport class InvalidPersistedStorageKeyEncodingError extends InvalidPersistedCollectionConfigError {\n constructor(encoded: string) {\n super(\n `Invalid persisted storage key encoding \"${encoded}\": expected prefix \"n:\" or \"s:\"`,\n )\n this.name = `InvalidPersistedStorageKeyEncodingError`\n }\n}\n\nexport class SQLiteBigIntOutOfRangeError extends PersistedCollectionCoreError {\n constructor(value: bigint, minimum: bigint, maximum: bigint) {\n super(\n `SQLite BigInt value ${value} is outside the signed 64-bit range [${minimum}, ${maximum}]`,\n )\n this.name = `SQLiteBigIntOutOfRangeError`\n }\n}\n\nexport class PersistenceUnavailableError extends PersistedCollectionCoreError {\n constructor(details?: string) {\n super(\n details\n ? `Persistence unavailable: ${details}`\n : `Persistence unavailable in this runtime`,\n )\n this.name = `PersistenceUnavailableError`\n }\n}\n"],"names":["TanStackDBError"],"mappings":"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"}
1
+ {"version":3,"file":"errors.cjs","sources":["../../src/errors.ts"],"sourcesContent":["import { TanStackDBError } from '@tanstack/db'\n\nexport class PersistedCollectionCoreError extends TanStackDBError {\n constructor(message: string) {\n super(message)\n this.name = `PersistedCollectionCoreError`\n }\n}\n\nexport class InvalidPersistedCollectionConfigError extends PersistedCollectionCoreError {\n constructor(message: string) {\n super(message)\n this.name = `InvalidPersistedCollectionConfigError`\n }\n}\n\nexport class InvalidSyncConfigError extends InvalidPersistedCollectionConfigError {\n constructor(details?: string) {\n super(\n details\n ? `Invalid sync config: ${details}`\n : `Invalid sync config: expected an object with a callable sync function`,\n )\n this.name = `InvalidSyncConfigError`\n }\n}\n\nexport class InvalidPersistedCollectionCoordinatorError extends InvalidPersistedCollectionConfigError {\n constructor(methodName: string) {\n super(\n `Invalid persisted collection coordinator: missing required \"${methodName}\" method`,\n )\n this.name = `InvalidPersistedCollectionCoordinatorError`\n }\n}\n\nexport class InvalidPersistenceAdapterError extends InvalidPersistedCollectionConfigError {\n constructor(methodName: string) {\n super(\n `Invalid persistence adapter: missing required \"${methodName}\" method`,\n )\n this.name = `InvalidPersistenceAdapterError`\n }\n}\n\nexport type PersistedCollectionDurabilityErrorOptions = {\n cause?: unknown\n code?: unknown\n path?: unknown\n}\n\nexport class PersistedCollectionDurabilityError extends PersistedCollectionCoreError {\n override readonly cause: unknown\n readonly code: unknown\n readonly path: unknown\n\n constructor(\n message: string,\n options: PersistedCollectionDurabilityErrorOptions = {},\n ) {\n super(message)\n this.name = `PersistedCollectionDurabilityError`\n this.cause = options.cause\n this.code = options.code\n this.path = options.path\n }\n}\n\nexport function toPersistedCollectionDurabilityError(\n collectionId: string,\n cause: unknown,\n): PersistedCollectionDurabilityError {\n if (cause instanceof PersistedCollectionDurabilityError) {\n return cause\n }\n\n const details =\n typeof cause === `object` && cause !== null\n ? (cause as Record<string, unknown>)\n : undefined\n const message = cause instanceof Error ? cause.message : String(cause)\n return new PersistedCollectionDurabilityError(\n `Failed to durably persist collection \"${collectionId}\": ${message}`,\n {\n cause,\n code: details?.code,\n path: details?.path,\n },\n )\n}\n\nexport type IndeterminateCommitRequestType =\n `rpc:applyLocalMutations:req` | `rpc:applyCommittedTx:req`\n\nexport type IndeterminateCommitErrorOptions = {\n collectionId: string\n requestType: IndeterminateCommitRequestType\n previousLeaderId: string | null\n previousTerm: number | null\n currentLeaderId: string | null\n currentTerm: number | null\n cause: unknown\n}\n\nexport class IndeterminateCommitError extends PersistedCollectionCoreError {\n readonly code: `INDETERMINATE_COMMIT` = `INDETERMINATE_COMMIT`\n readonly collectionId: string\n readonly requestType: IndeterminateCommitRequestType\n readonly previousLeaderId: string | null\n readonly previousTerm: number | null\n readonly currentLeaderId: string | null\n readonly currentTerm: number | null\n override readonly cause: unknown\n\n constructor(options: IndeterminateCommitErrorOptions) {\n super(\n `Commit outcome is indeterminate for collection \"${options.collectionId}\": ${options.requestType} crossed leadership from ${formatLeader(options.previousLeaderId, options.previousTerm)} to ${formatLeader(options.currentLeaderId, options.currentTerm)}`,\n )\n this.name = `IndeterminateCommitError`\n this.collectionId = options.collectionId\n this.requestType = options.requestType\n this.previousLeaderId = options.previousLeaderId\n this.previousTerm = options.previousTerm\n this.currentLeaderId = options.currentLeaderId\n this.currentTerm = options.currentTerm\n this.cause = options.cause\n }\n}\n\nfunction formatLeader(leaderId: string | null, term: number | null): string {\n return `${leaderId ?? `unknown leader`} (term ${term ?? `unknown`})`\n}\n\nexport class DuplicateRemoteSubsetOwnerError extends PersistedCollectionCoreError {\n readonly collectionId: string\n\n constructor(collectionId: string) {\n super(\n `A remote subset owner is already registered for collection \"${collectionId}\"`,\n )\n this.name = `DuplicateRemoteSubsetOwnerError`\n this.collectionId = collectionId\n }\n}\n\nexport class RetryableRemoteSubsetAcquisitionError extends PersistedCollectionCoreError {\n override readonly cause: unknown\n\n constructor(message: string, cause?: unknown) {\n super(message)\n this.name = `RetryableRemoteSubsetAcquisitionError`\n this.cause = cause\n }\n}\n\nexport class InvalidPersistedStorageKeyError extends InvalidPersistedCollectionConfigError {\n constructor(key: string | number) {\n super(\n `Invalid persisted storage key \"${String(key)}\": numeric keys must be finite`,\n )\n this.name = `InvalidPersistedStorageKeyError`\n }\n}\n\nexport class InvalidPersistedStorageKeyEncodingError extends InvalidPersistedCollectionConfigError {\n constructor(encoded: string) {\n super(\n `Invalid persisted storage key encoding \"${encoded}\": expected prefix \"n:\" or \"s:\"`,\n )\n this.name = `InvalidPersistedStorageKeyEncodingError`\n }\n}\n\nexport class SQLiteBigIntOutOfRangeError extends PersistedCollectionCoreError {\n constructor(value: bigint, minimum: bigint, maximum: bigint) {\n super(\n `SQLite BigInt value ${value} is outside the signed 64-bit range [${minimum}, ${maximum}]`,\n )\n this.name = `SQLiteBigIntOutOfRangeError`\n }\n}\n\nexport class PersistenceUnavailableError extends PersistedCollectionCoreError {\n constructor(details?: string) {\n super(\n details\n ? `Persistence unavailable: ${details}`\n : `Persistence unavailable in this runtime`,\n )\n this.name = `PersistenceUnavailableError`\n }\n}\n"],"names":["TanStackDBError"],"mappings":"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"}
@@ -37,10 +37,15 @@ exports.PERSISTED_VALUE_TAG = sqliteValue.PERSISTED_VALUE_TAG;
37
37
  exports.SQLITE_BIGINT_MAX = sqliteValue.SQLITE_BIGINT_MAX;
38
38
  exports.SQLITE_BIGINT_MIN = sqliteValue.SQLITE_BIGINT_MIN;
39
39
  exports.assertSQLiteBigIntInRange = sqliteValue.assertSQLiteBigIntInRange;
40
+ exports.reviveSQLiteTemporal = sqliteValue.reviveSQLiteTemporal;
40
41
  exports.serializeSQLiteBigInt = sqliteValue.serializeSQLiteBigInt;
42
+ exports.serializeSQLiteTemporal = sqliteValue.serializeSQLiteTemporal;
43
+ exports.sqliteTemporalIdentity = sqliteValue.sqliteTemporalIdentity;
44
+ exports.sqliteTemporalKind = sqliteValue.sqliteTemporalKind;
41
45
  exports.RemoteSubsetWireValueError = remoteSubsetWire.RemoteSubsetWireValueError;
42
46
  exports.toProcessLocalLoadSubsetOptions = remoteSubsetWire.toProcessLocalLoadSubsetOptions;
43
47
  exports.toTransportedLoadSubsetOptions = remoteSubsetWire.toTransportedLoadSubsetOptions;
48
+ exports.validateRemoteSubsetOptions = remoteSubsetWire.validateRemoteSubsetOptions;
44
49
  Object.defineProperty(exports, "safeRandomUUID", {
45
50
  enumerable: true,
46
51
  get: () => db.safeRandomUUID
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"index.cjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -178,8 +178,8 @@ class SingleProcessCoordinator {
178
178
  setAdapterForCollection(collectionId, adapter) {
179
179
  this.collectionAdapters.set(collectionId, adapter);
180
180
  }
181
- async requestApplyCommittedTx(collectionId, tx) {
182
- const adapter = this.collectionAdapters.get(collectionId);
181
+ async requestApplyCommittedTx(collectionId, tx, scopedAdapter) {
182
+ const adapter = scopedAdapter ?? this.collectionAdapters.get(collectionId);
183
183
  if (!adapter) {
184
184
  throw new errors.InvalidPersistedCollectionConfigError(
185
185
  `SingleProcessCoordinator has no persistence adapter configured for collection "${collectionId}"`
@@ -335,6 +335,8 @@ function toStableSerializable(value) {
335
335
  case `undefined`:
336
336
  return void 0;
337
337
  }
338
+ const temporal = sqliteValue.serializeSQLiteTemporal(value);
339
+ if (temporal) return temporal;
338
340
  if (value instanceof Date) {
339
341
  return value.toISOString();
340
342
  }
@@ -442,7 +444,6 @@ class PersistedCollectionRuntime {
442
444
  this.resumeGenerationOwner = /* @__PURE__ */ Symbol(`persisted resume generation owner`);
443
445
  this.lifecycleGeneration = 0;
444
446
  this.internalApplyDepth = 0;
445
- this.sourcePublicationWaitDepth = 0;
446
447
  this.appliedReceiptSequence = 0;
447
448
  this.syncErrorReported = false;
448
449
  this.pendingAppliedReceipts = /* @__PURE__ */ new Map();
@@ -501,11 +502,14 @@ class PersistedCollectionRuntime {
501
502
  void receipt.then(removeReceipt, removeReceipt);
502
503
  return receipt;
503
504
  }
504
- async waitForAppliedReceiptsAfter(cursor) {
505
+ // Startup waits for acceptance: a local mutation's handler can wait for
506
+ // startup, and the rows publish when that mutation settles. Readiness waits
507
+ // for them in core. A subset load waits for visibility.
508
+ async waitForAppliedReceiptsAfter(cursor, until = `visible`) {
505
509
  await Promise.all(
506
510
  Array.from(
507
511
  this.pendingAppliedReceipts,
508
- ([sequence, receipt]) => sequence > cursor ? receipt : void 0
512
+ ([sequence, receipt]) => sequence <= cursor ? void 0 : until === `accepted` ? db.whenSyncAccepted(receipt) : receipt
509
513
  )
510
514
  );
511
515
  }
@@ -666,7 +670,10 @@ class PersistedCollectionRuntime {
666
670
  startup.completedLocalIndexSignatures
667
671
  );
668
672
  if (startup.appliedCursor !== void 0 && lifecycleGeneration === this.lifecycleGeneration) {
669
- await this.waitForAppliedReceiptsAfter(startup.appliedCursor);
673
+ await this.waitForAppliedReceiptsAfter(
674
+ startup.appliedCursor,
675
+ `accepted`
676
+ );
670
677
  }
671
678
  }
672
679
  if (lifecycleGeneration === this.lifecycleGeneration) {
@@ -701,7 +708,7 @@ class PersistedCollectionRuntime {
701
708
  return result;
702
709
  });
703
710
  if (appliedCursor !== void 0 && lifecycleGeneration === this.lifecycleGeneration) {
704
- await this.waitForAppliedReceiptsAfter(appliedCursor);
711
+ await this.waitForAppliedReceiptsAfter(appliedCursor, `accepted`);
705
712
  }
706
713
  })().catch((error) => {
707
714
  throw this.markTerminalFailure(error, lifecycleGeneration);
@@ -742,7 +749,6 @@ class PersistedCollectionRuntime {
742
749
  await this.hydrateSubsetUnsafe(
743
750
  baseline,
744
751
  {
745
- requestRemoteEnsure: false,
746
752
  lifecycleGeneration,
747
753
  bindKeySetEvidence: true
748
754
  },
@@ -790,7 +796,7 @@ class PersistedCollectionRuntime {
790
796
  const applied = this.replaceCollectionMetadataSnapshot(
791
797
  snapshot.collectionMetadata
792
798
  );
793
- if (applied !== true) await applied;
799
+ await db.whenSyncAccepted(applied);
794
800
  }
795
801
  async loadCollectionMetadataSnapshot(adapter) {
796
802
  if (!adapter.loadCollectionMetadata) {
@@ -807,7 +813,7 @@ class PersistedCollectionRuntime {
807
813
  );
808
814
  const currentKeys = this.syncControls.metadata.collection.list().map(({ key }) => key);
809
815
  return this.withInternalApply(() => {
810
- this.syncControls.begin?.({ immediate: true });
816
+ this.syncControls.begin?.();
811
817
  currentKeys.forEach((key) => {
812
818
  if (!nextMetadata.has(key)) {
813
819
  this.syncControls.metadata?.collection.delete(key);
@@ -825,6 +831,7 @@ class PersistedCollectionRuntime {
825
831
  const subsetKey = this.getSubsetKey(options);
826
832
  const truncateGeneration = this.sourceTruncateGeneration;
827
833
  const routeRemoteDemandDuringHydration = this.canRouteRemoteDemandThroughCoordinator();
834
+ if (routeRemoteDemandDuringHydration) remoteSubsetWire.validateRemoteSubsetOptions(options);
828
835
  this.activeSubsets.set(subsetKey, options);
829
836
  const appliedCursor = this.appliedReceiptSequence;
830
837
  try {
@@ -834,7 +841,6 @@ class PersistedCollectionRuntime {
834
841
  (adapter) => this.hydrateSubsetUnsafe(
835
842
  options,
836
843
  {
837
- requestRemoteEnsure: this.mode === `sync-present` && !routeRemoteDemandDuringHydration,
838
844
  lifecycleGeneration,
839
845
  requestLocalLoadFailure: true,
840
846
  rejectBufferedReplayFailure: true
@@ -850,6 +856,9 @@ class PersistedCollectionRuntime {
850
856
  });
851
857
  if (lifecycleGeneration !== this.lifecycleGeneration) return;
852
858
  await this.waitForAppliedReceiptsAfter(appliedCursor);
859
+ if (!routeRemoteDemandDuringHydration && this.canRouteRemoteDemandThroughCoordinator()) {
860
+ remoteSubsetWire.validateRemoteSubsetOptions(options);
861
+ }
853
862
  } catch (error) {
854
863
  if (this.activeSubsets.get(subsetKey) === options) {
855
864
  this.activeSubsets.delete(subsetKey);
@@ -959,7 +968,6 @@ class PersistedCollectionRuntime {
959
968
  (adapter) => this.hydrateSubsetUnsafe(
960
969
  options,
961
970
  {
962
- requestRemoteEnsure: false,
963
971
  lifecycleGeneration,
964
972
  rejectBufferedReplayFailure: true
965
973
  },
@@ -982,13 +990,6 @@ class PersistedCollectionRuntime {
982
990
  applyHydrationBufferedTransaction(transaction) {
983
991
  const failure = this.getCurrentTerminalFailure();
984
992
  if (failure) return Promise.reject(failure.error);
985
- if (transaction.beginOptions?.immediate && this.sourcePublicationWaitDepth > 0) {
986
- return Promise.reject(
987
- new errors.InvalidPersistedCollectionConfigError(
988
- `immediate persisted source replay cannot enter while an earlier source publication is waiting`
989
- )
990
- );
991
- }
992
993
  return this.applyMutex.run(async () => {
993
994
  await this.applyBufferedSyncTransactionUnsafe(transaction);
994
995
  });
@@ -1209,7 +1210,7 @@ class PersistedCollectionRuntime {
1209
1210
  hydrationContext.suppliedRowKeys.add(row.key);
1210
1211
  }
1211
1212
  const applied = this.applyRowsToCollection(rows);
1212
- if (applied !== true) await applied;
1213
+ await db.whenSyncAccepted(applied);
1213
1214
  }
1214
1215
  } finally {
1215
1216
  if (this.activeHydrationContext === hydrationContext && this.hydratingGeneration === config.lifecycleGeneration) {
@@ -1219,9 +1220,6 @@ class PersistedCollectionRuntime {
1219
1220
  if (config.lifecycleGeneration !== this.lifecycleGeneration) return;
1220
1221
  replayFailure = await this.flushQueuedHydrationTransactionsUnsafe(adapter);
1221
1222
  if (config.lifecycleGeneration !== this.lifecycleGeneration) return;
1222
- if (config.requestRemoteEnsure && !replayFailure) {
1223
- this.queueRemoteSubsetEnsure(options);
1224
- }
1225
1223
  } catch (error) {
1226
1224
  if (config.requestLocalLoadFailure && !rowsLoaded) {
1227
1225
  this.hydratingGeneration = config.lifecycleGeneration;
@@ -1352,7 +1350,7 @@ class PersistedCollectionRuntime {
1352
1350
  return true;
1353
1351
  }
1354
1352
  return this.withInternalApply(() => {
1355
- this.syncControls.begin?.({ immediate: true });
1353
+ this.syncControls.begin?.();
1356
1354
  for (const row of rows) {
1357
1355
  if (this.collection?._hasHydratedKey(row.key)) {
1358
1356
  continue;
@@ -1398,7 +1396,7 @@ class PersistedCollectionRuntime {
1398
1396
  );
1399
1397
  const currentKeys = this.syncControls.metadata.collection.list().map(({ key }) => key);
1400
1398
  return this.withInternalApply(() => {
1401
- this.syncControls.begin?.({ immediate: true });
1399
+ this.syncControls.begin?.();
1402
1400
  this.syncControls.truncate?.();
1403
1401
  for (const row of rows) {
1404
1402
  this.syncControls.write?.({
@@ -1452,14 +1450,9 @@ class PersistedCollectionRuntime {
1452
1450
  const applied = transaction.internal ? this.withInternalApply(transaction.applyToCollection) : transaction.applyToCollection();
1453
1451
  applicationReturned = true;
1454
1452
  abortedDuringApplication = transaction.signal?.aborted === true;
1455
- if (applied !== true) {
1456
- this.sourcePublicationWaitDepth++;
1457
- try {
1458
- await applied;
1459
- } finally {
1460
- this.sourcePublicationWaitDepth--;
1461
- }
1462
- }
1453
+ if (transaction.internal) await db.whenSyncAccepted(applied);
1454
+ else if (applied !== true && !this.collection?._state.hasPersistingTransaction())
1455
+ await applied;
1463
1456
  this.throwIfLifecycleReplaced(transaction.lifecycleGeneration);
1464
1457
  if (!transaction.internal) {
1465
1458
  await this.persistAndBroadcastExternalSyncTransactionUnsafe(
@@ -1629,7 +1622,7 @@ class PersistedCollectionRuntime {
1629
1622
  return;
1630
1623
  }
1631
1624
  const applied = this.withInternalApply(() => {
1632
- this.syncControls.begin?.({ immediate: true });
1625
+ this.syncControls.begin?.();
1633
1626
  for (const mutation of mutations) {
1634
1627
  if (mutation.type === `delete`) {
1635
1628
  this.syncControls.write?.({
@@ -1645,9 +1638,8 @@ class PersistedCollectionRuntime {
1645
1638
  }
1646
1639
  return this.syncControls.commit?.() ?? true;
1647
1640
  });
1648
- if (applied !== true) {
1649
- await applied;
1650
- }
1641
+ const accepted = db.whenSyncAccepted(applied);
1642
+ if (accepted !== true) await accepted;
1651
1643
  }
1652
1644
  filterMutationsForCollection(mutations) {
1653
1645
  const collection = this.collection;
@@ -1820,6 +1812,7 @@ class PersistedCollectionRuntime {
1820
1812
  }
1821
1813
  const subsetKey = this.getSubsetKey(options);
1822
1814
  if (this.activeSubsets.get(subsetKey) !== options) return;
1815
+ remoteSubsetWire.validateRemoteSubsetOptions(options);
1823
1816
  this.pendingRemoteSubsetEnsures.set(subsetKey, options);
1824
1817
  void this.flushPendingRemoteSubsetEnsures();
1825
1818
  }
@@ -2035,11 +2028,11 @@ class PersistedCollectionRuntime {
2035
2028
  this.resetSequence++;
2036
2029
  if (this.syncControls.begin && this.syncControls.commit) {
2037
2030
  const applied = this.withInternalApply(() => {
2038
- this.syncControls.begin?.({ immediate: true });
2031
+ this.syncControls.begin?.();
2039
2032
  this.syncControls.truncate?.();
2040
2033
  return this.syncControls.commit?.() ?? true;
2041
2034
  });
2042
- if (applied !== true) await applied;
2035
+ await db.whenSyncAccepted(applied);
2043
2036
  }
2044
2037
  if (lifecycleGeneration !== this.lifecycleGeneration) return;
2045
2038
  await this.reloadActiveSubsetsUnsafe(adapter);
@@ -2072,7 +2065,7 @@ class PersistedCollectionRuntime {
2072
2065
  (opt) => opt.where ? db.compileSingleRowExpression(opt.where) : null
2073
2066
  );
2074
2067
  const applied = this.withInternalApply(() => {
2075
- this.syncControls.begin?.({ immediate: true });
2068
+ this.syncControls.begin?.();
2076
2069
  for (const {
2077
2070
  key: changedKey,
2078
2071
  value: newValue
@@ -2112,7 +2105,7 @@ class PersistedCollectionRuntime {
2112
2105
  });
2113
2106
  return this.syncControls.commit?.() ?? true;
2114
2107
  });
2115
- if (applied !== true) await applied;
2108
+ await db.whenSyncAccepted(applied);
2116
2109
  }
2117
2110
  async reloadActiveSubsetsUnsafe(adapter) {
2118
2111
  const lifecycleGeneration = this.lifecycleGeneration;
@@ -2148,7 +2141,7 @@ class PersistedCollectionRuntime {
2148
2141
  })),
2149
2142
  collectionMetadata
2150
2143
  );
2151
- if (applied !== true) await applied;
2144
+ await db.whenSyncAccepted(applied);
2152
2145
  } finally {
2153
2146
  if (this.activeHydrationContext === hydrationContext && this.hydratingGeneration === lifecycleGeneration) {
2154
2147
  this.hydratingGeneration = null;
@@ -2222,8 +2215,8 @@ class PersistedCollectionRuntime {
2222
2215
  await this.requestCoordinatorPersistedIndex(indexMetadata, completedLocally);
2223
2216
  }
2224
2217
  async ensureLocalPersistedIndex(indexMetadata, adapter) {
2225
- const spec = this.buildPersistedIndexSpec(indexMetadata);
2226
2218
  try {
2219
+ const spec = this.buildPersistedIndexSpec(indexMetadata);
2227
2220
  await adapter.ensureIndex(
2228
2221
  this.collectionId,
2229
2222
  indexMetadata.signature,
@@ -2236,8 +2229,8 @@ class PersistedCollectionRuntime {
2236
2229
  }
2237
2230
  }
2238
2231
  async requestCoordinatorPersistedIndex(indexMetadata, completedLocally) {
2239
- const spec = this.buildPersistedIndexSpec(indexMetadata);
2240
2232
  try {
2233
+ const spec = this.buildPersistedIndexSpec(indexMetadata);
2241
2234
  await this.persistence.coordinator.requestEnsurePersistedIndex(
2242
2235
  this.collectionId,
2243
2236
  indexMetadata.signature,
@@ -2314,6 +2307,14 @@ function createWrappedSyncConfig(sourceSyncConfig, runtime, persistedReadiness)
2314
2307
  const settlePendingTransaction = (transaction) => {
2315
2308
  removePendingPublicationTransaction(transaction);
2316
2309
  };
2310
+ const visibleAfterDurable = (transaction, durable) => {
2311
+ const visible = durable.then(async () => {
2312
+ const receipt = transaction.applicationReceipt;
2313
+ if (receipt !== void 0 && receipt !== true) await receipt;
2314
+ });
2315
+ void visible.catch(() => void 0);
2316
+ return db.withAcceptedReceipt(visible, durable);
2317
+ };
2317
2318
  const settleRuntimeTransaction = (transaction, applied) => {
2318
2319
  void applied.then(
2319
2320
  () => settlePendingTransaction(transaction),
@@ -2421,9 +2422,7 @@ function createWrappedSyncConfig(sourceSyncConfig, runtime, persistedReadiness)
2421
2422
  }
2422
2423
  }
2423
2424
  transaction.deferredHydrationMetadataDeleteKeys.clear();
2424
- params.begin(
2425
- transaction.queuedBecauseHydrating ? { immediate: true } : transaction.beginOptions
2426
- );
2425
+ params.begin();
2427
2426
  if (transaction.truncate) params.truncate();
2428
2427
  for (const operation of transaction.operations) {
2429
2428
  if (operation.type === `delete`) {
@@ -2449,14 +2448,8 @@ function createWrappedSyncConfig(sourceSyncConfig, runtime, persistedReadiness)
2449
2448
  }
2450
2449
  const applied = params.commit(signal);
2451
2450
  transaction.applicationReceipt = applied;
2452
- if (applied === true) {
2453
- removePendingPublicationTransaction(transaction);
2454
- } else {
2455
- void applied.then(
2456
- () => removePendingPublicationTransaction(transaction),
2457
- () => removePendingPublicationTransaction(transaction)
2458
- );
2459
- }
2451
+ removePendingPublicationTransaction(transaction);
2452
+ if (applied !== true) void applied.catch(() => void 0);
2460
2453
  return applied;
2461
2454
  } catch (error) {
2462
2455
  removePendingPublicationTransaction(transaction);
@@ -2477,6 +2470,11 @@ function createWrappedSyncConfig(sourceSyncConfig, runtime, persistedReadiness)
2477
2470
  const persistenceCapability = {
2478
2471
  protocol: db.SYNC_PERSISTENCE_PROTOCOL,
2479
2472
  version: db.SYNC_PERSISTENCE_VERSION,
2473
+ reserveCommitTurn: () => {
2474
+ const openTransaction = getOpenTransaction();
2475
+ if (openTransaction && !openTransaction.internal)
2476
+ openTransaction.reservesCommitTurn = true;
2477
+ },
2480
2478
  hydrateBaseline: async () => {
2481
2479
  if (startupState.cleanedUp) return;
2482
2480
  try {
@@ -2526,7 +2524,7 @@ function createWrappedSyncConfig(sourceSyncConfig, runtime, persistedReadiness)
2526
2524
  params.markReady();
2527
2525
  }).catch(() => void 0);
2528
2526
  },
2529
- begin: (options) => {
2527
+ begin: () => {
2530
2528
  if (startupState.cleanedUp) return void 0;
2531
2529
  const terminalFailure = getTerminalFailure();
2532
2530
  const internal = runtime.isApplyingInternally();
@@ -2539,7 +2537,6 @@ function createWrappedSyncConfig(sourceSyncConfig, runtime, persistedReadiness)
2539
2537
  truncate: false,
2540
2538
  internal,
2541
2539
  lifecycleGeneration: runtime.getLifecycleGeneration(),
2542
- beginOptions: options,
2543
2540
  operationKeys: /* @__PURE__ */ new Set(),
2544
2541
  hasDependentSuccessor: false,
2545
2542
  queuedBecauseHydrating: terminalFailure === void 0 && !internal && runtime.isHydratingNow(),
@@ -2798,7 +2795,6 @@ function createWrappedSyncConfig(sourceSyncConfig, runtime, persistedReadiness)
2798
2795
  truncate: openTransaction.truncate,
2799
2796
  internal: false,
2800
2797
  lifecycleGeneration: openTransaction.lifecycleGeneration,
2801
- beginOptions: openTransaction.beginOptions,
2802
2798
  expectedResumeGenerationOwner: openTransaction.expectedResumeGenerationOwner,
2803
2799
  signal,
2804
2800
  prependHydrationRows: (rows) => {
@@ -2840,8 +2836,9 @@ function createWrappedSyncConfig(sourceSyncConfig, runtime, persistedReadiness)
2840
2836
  });
2841
2837
  settlePublicationAdmissionWaiters(openTransaction);
2842
2838
  settleRuntimeTransaction(openTransaction, applied2);
2843
- return applied2;
2839
+ return visibleAfterDurable(openTransaction, applied2);
2844
2840
  }
2841
+ openTransaction.hydrationSequence = void 0;
2845
2842
  let applied;
2846
2843
  try {
2847
2844
  applied = runtime.applyHydrationBufferedTransaction(transaction);
@@ -2851,7 +2848,7 @@ function createWrappedSyncConfig(sourceSyncConfig, runtime, persistedReadiness)
2851
2848
  }
2852
2849
  settlePublicationAdmissionWaiters(openTransaction);
2853
2850
  settleRuntimeTransaction(openTransaction, applied);
2854
- return applied;
2851
+ return visibleAfterDurable(openTransaction, applied);
2855
2852
  }
2856
2853
  };
2857
2854
  let sourceResult = {};
@@ -2959,7 +2956,7 @@ function createWrappedSyncConfig(sourceSyncConfig, runtime, persistedReadiness)
2959
2956
  }
2960
2957
  };
2961
2958
  const openTransaction = getOpenTransaction();
2962
- const needsPublicationAdmission = openTransaction && !openTransaction.internal && openTransaction.beginOptions?.immediate;
2959
+ const needsPublicationAdmission = openTransaction?.reservesCommitTurn === true;
2963
2960
  const hydrated = sourceResultSettled && !needsPublicationAdmission ? runtime.loadHydratedSubset(
2964
2961
  options,
2965
2962
  (loadOptions) => forwardUpstream(sourceResult, loadOptions)
@@ -2974,7 +2971,7 @@ function createWrappedSyncConfig(sourceSyncConfig, runtime, persistedReadiness)
2974
2971
  return;
2975
2972
  }
2976
2973
  const currentTransaction = getOpenTransaction();
2977
- if (currentTransaction && !currentTransaction.internal && currentTransaction.beginOptions?.immediate) {
2974
+ if (currentTransaction?.reservesCommitTurn) {
2978
2975
  await waitForPublicationAdmission(
2979
2976
  currentTransaction,
2980
2977
  options,