@tanstack/db-sqlite-persistence-core 0.2.20 → 0.2.23
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 +131 -81
- package/dist/cjs/persisted.cjs.map +1 -1
- package/dist/cjs/persisted.d.cts +1 -0
- package/dist/esm/persisted.d.ts +1 -0
- package/dist/esm/persisted.js +131 -81
- package/dist/esm/persisted.js.map +1 -1
- package/package.json +2 -2
- package/src/persisted.ts +171 -88
package/dist/cjs/persisted.d.cts
CHANGED
|
@@ -248,6 +248,7 @@ export interface PersistedCollectionUtils extends UtilsRecord {
|
|
|
248
248
|
mutations: Array<PendingMutation<Record<string, unknown>>>;
|
|
249
249
|
}) => Promise<void> | void;
|
|
250
250
|
getLeadershipState?: () => PersistedCollectionLeadershipState;
|
|
251
|
+
/** Hydrate once without acquiring a new ongoing subset lease. */
|
|
251
252
|
forceReloadSubset?: (options: LoadSubsetOptions) => Promise<void> | void;
|
|
252
253
|
}
|
|
253
254
|
export type PersistedSyncWrappedOptions<T extends object, TKey extends string | number, TSchema extends StandardSchemaV1 = never, TUtils extends UtilsRecord = UtilsRecord> = CollectionConfig<T, TKey, TSchema, TUtils> & {
|
package/dist/esm/persisted.d.ts
CHANGED
|
@@ -248,6 +248,7 @@ export interface PersistedCollectionUtils extends UtilsRecord {
|
|
|
248
248
|
mutations: Array<PendingMutation<Record<string, unknown>>>;
|
|
249
249
|
}) => Promise<void> | void;
|
|
250
250
|
getLeadershipState?: () => PersistedCollectionLeadershipState;
|
|
251
|
+
/** Hydrate once without acquiring a new ongoing subset lease. */
|
|
251
252
|
forceReloadSubset?: (options: LoadSubsetOptions) => Promise<void> | void;
|
|
252
253
|
}
|
|
253
254
|
export type PersistedSyncWrappedOptions<T extends object, TKey extends string | number, TSchema extends StandardSchemaV1 = never, TUtils extends UtilsRecord = UtilsRecord> = CollectionConfig<T, TKey, TSchema, TUtils> & {
|
package/dist/esm/persisted.js
CHANGED
|
@@ -163,15 +163,6 @@ function toStableSerializable(value) {
|
|
|
163
163
|
function stableSerialize(value) {
|
|
164
164
|
return JSON.stringify(toStableSerializable(value) ?? null);
|
|
165
165
|
}
|
|
166
|
-
function normalizeSubsetOptionsForKey(options) {
|
|
167
|
-
return {
|
|
168
|
-
where: toStableSerializable(options.where),
|
|
169
|
-
orderBy: toStableSerializable(options.orderBy),
|
|
170
|
-
limit: options.limit,
|
|
171
|
-
cursor: toStableSerializable(options.cursor),
|
|
172
|
-
offset: options.offset
|
|
173
|
-
};
|
|
174
|
-
}
|
|
175
166
|
function normalizeSyncFnResult(result) {
|
|
176
167
|
if (typeof result === `function`) {
|
|
177
168
|
return { cleanup: result };
|
|
@@ -218,7 +209,7 @@ class PersistedCollectionRuntime {
|
|
|
218
209
|
this.pendingRemoteSubsetEnsures = /* @__PURE__ */ new Map();
|
|
219
210
|
this.queuedHydrationTransactions = [];
|
|
220
211
|
this.queuedTxCommitted = [];
|
|
221
|
-
this.
|
|
212
|
+
this.requestIds = /* @__PURE__ */ new WeakMap();
|
|
222
213
|
this.collection = null;
|
|
223
214
|
this.syncControls = {
|
|
224
215
|
begin: null,
|
|
@@ -230,15 +221,17 @@ class PersistedCollectionRuntime {
|
|
|
230
221
|
this.started = false;
|
|
231
222
|
this.startupMetadataPromise = null;
|
|
232
223
|
this.startPromise = null;
|
|
224
|
+
this.resumeBaselinePromise = null;
|
|
225
|
+
this.lifecycleGeneration = 0;
|
|
233
226
|
this.internalApplyDepth = 0;
|
|
234
227
|
this.appliedReceiptSequence = 0;
|
|
235
228
|
this.pendingAppliedReceipts = /* @__PURE__ */ new Map();
|
|
236
|
-
this.
|
|
229
|
+
this.hydratingGeneration = null;
|
|
237
230
|
this.coordinatorUnsubscribe = null;
|
|
238
231
|
this.indexAddedUnsubscribe = null;
|
|
239
232
|
this.indexRemovedUnsubscribe = null;
|
|
240
233
|
this.remoteEnsureRetryTimer = null;
|
|
241
|
-
this.
|
|
234
|
+
this.nextRequestId = 0;
|
|
242
235
|
this.latestTerm = 0;
|
|
243
236
|
this.latestSeq = 0;
|
|
244
237
|
this.latestRowVersion = 0;
|
|
@@ -247,6 +240,7 @@ class PersistedCollectionRuntime {
|
|
|
247
240
|
this.localRowVersion = 0;
|
|
248
241
|
}
|
|
249
242
|
setSyncControls(syncControls) {
|
|
243
|
+
this.advanceLifecycle();
|
|
250
244
|
const commit = syncControls.commit;
|
|
251
245
|
this.syncControls = {
|
|
252
246
|
...syncControls,
|
|
@@ -281,7 +275,7 @@ class PersistedCollectionRuntime {
|
|
|
281
275
|
};
|
|
282
276
|
}
|
|
283
277
|
isHydratingNow() {
|
|
284
|
-
return this.
|
|
278
|
+
return this.hydratingGeneration === this.lifecycleGeneration;
|
|
285
279
|
}
|
|
286
280
|
isApplyingInternally() {
|
|
287
281
|
return this.internalApplyDepth > 0;
|
|
@@ -303,49 +297,75 @@ class PersistedCollectionRuntime {
|
|
|
303
297
|
if (this.startPromise) {
|
|
304
298
|
return this.startPromise;
|
|
305
299
|
}
|
|
306
|
-
|
|
300
|
+
const lifecycleGeneration = this.lifecycleGeneration;
|
|
301
|
+
this.startPromise = this.startInternal(lifecycleGeneration);
|
|
307
302
|
return this.startPromise;
|
|
308
303
|
}
|
|
304
|
+
ensureResumeBaselineHydrated() {
|
|
305
|
+
if (this.resumeBaselinePromise) {
|
|
306
|
+
return this.resumeBaselinePromise;
|
|
307
|
+
}
|
|
308
|
+
const lifecycleGeneration = this.lifecycleGeneration;
|
|
309
|
+
this.resumeBaselinePromise = (async () => {
|
|
310
|
+
await this.ensureStarted();
|
|
311
|
+
if (lifecycleGeneration !== this.lifecycleGeneration) return;
|
|
312
|
+
if (this.syncMode !== `on-demand`) return;
|
|
313
|
+
await this.hydrateBaseline(lifecycleGeneration);
|
|
314
|
+
})();
|
|
315
|
+
return this.resumeBaselinePromise;
|
|
316
|
+
}
|
|
317
|
+
async hydrateBaseline(lifecycleGeneration) {
|
|
318
|
+
if (lifecycleGeneration !== this.lifecycleGeneration) return;
|
|
319
|
+
const baseline = {};
|
|
320
|
+
this.activeSubsets.set(this.getSubsetKey(baseline), baseline);
|
|
321
|
+
const appliedCursor = this.appliedReceiptSequence;
|
|
322
|
+
await this.applyMutex.run(async () => {
|
|
323
|
+
if (lifecycleGeneration !== this.lifecycleGeneration) return;
|
|
324
|
+
await this.hydrateSubsetUnsafe(baseline, {
|
|
325
|
+
requestRemoteEnsure: false,
|
|
326
|
+
lifecycleGeneration
|
|
327
|
+
});
|
|
328
|
+
});
|
|
329
|
+
if (lifecycleGeneration !== this.lifecycleGeneration) return;
|
|
330
|
+
await this.waitForAppliedReceiptsAfter(appliedCursor);
|
|
331
|
+
}
|
|
309
332
|
async ensureStartupMetadataLoaded() {
|
|
310
333
|
if (this.startupMetadataPromise) {
|
|
311
334
|
return this.startupMetadataPromise;
|
|
312
335
|
}
|
|
313
|
-
|
|
336
|
+
const lifecycleGeneration = this.lifecycleGeneration;
|
|
337
|
+
this.startupMetadataPromise = this.loadStartupMetadataInternal(lifecycleGeneration);
|
|
314
338
|
return this.startupMetadataPromise;
|
|
315
339
|
}
|
|
316
|
-
async startInternal() {
|
|
340
|
+
async startInternal(lifecycleGeneration) {
|
|
317
341
|
if (this.started) {
|
|
318
342
|
return;
|
|
319
343
|
}
|
|
320
344
|
this.started = true;
|
|
321
345
|
await this.ensureStartupMetadataLoaded();
|
|
346
|
+
if (lifecycleGeneration !== this.lifecycleGeneration) return;
|
|
322
347
|
const indexBootstrapSnapshot = this.collection?.getIndexMetadata() ?? [];
|
|
323
348
|
this.attachIndexLifecycleListeners();
|
|
324
349
|
await this.bootstrapPersistedIndexes(indexBootstrapSnapshot);
|
|
350
|
+
if (lifecycleGeneration !== this.lifecycleGeneration) return;
|
|
325
351
|
if (this.syncMode !== `on-demand`) {
|
|
326
|
-
this.
|
|
327
|
-
const appliedCursor = this.appliedReceiptSequence;
|
|
328
|
-
await this.applyMutex.run(
|
|
329
|
-
() => this.hydrateSubsetUnsafe({}, { requestRemoteEnsure: false })
|
|
330
|
-
);
|
|
331
|
-
await this.waitForAppliedReceiptsAfter(appliedCursor);
|
|
352
|
+
await this.hydrateBaseline(lifecycleGeneration);
|
|
332
353
|
}
|
|
333
354
|
}
|
|
334
|
-
async loadStartupMetadataInternal() {
|
|
355
|
+
async loadStartupMetadataInternal(lifecycleGeneration) {
|
|
335
356
|
if (this.persistence.adapter.getStreamPosition) {
|
|
336
357
|
const position = await this.persistence.adapter.getStreamPosition(
|
|
337
358
|
this.collectionId
|
|
338
359
|
);
|
|
360
|
+
if (lifecycleGeneration !== this.lifecycleGeneration) return;
|
|
339
361
|
this.observeStreamPosition(
|
|
340
362
|
position.latestTerm,
|
|
341
363
|
position.latestSeq,
|
|
342
364
|
position.latestRowVersion
|
|
343
365
|
);
|
|
344
366
|
}
|
|
345
|
-
await this.loadCollectionMetadataIntoCollection();
|
|
346
|
-
}
|
|
347
|
-
async loadCollectionMetadataIntoCollection() {
|
|
348
367
|
const collectionMetadata = await this.loadCollectionMetadataSnapshot();
|
|
368
|
+
if (lifecycleGeneration !== this.lifecycleGeneration) return;
|
|
349
369
|
this.replaceCollectionMetadataSnapshot(collectionMetadata);
|
|
350
370
|
}
|
|
351
371
|
async loadCollectionMetadataSnapshot() {
|
|
@@ -376,40 +396,43 @@ class PersistedCollectionRuntime {
|
|
|
376
396
|
});
|
|
377
397
|
}
|
|
378
398
|
async loadSubset(options, upstreamLoadSubset) {
|
|
399
|
+
const lifecycleGeneration = this.lifecycleGeneration;
|
|
379
400
|
this.activeSubsets.set(this.getSubsetKey(options), options);
|
|
380
401
|
const appliedCursor = this.appliedReceiptSequence;
|
|
381
402
|
await this.applyMutex.run(
|
|
382
403
|
() => this.hydrateSubsetUnsafe(options, {
|
|
383
|
-
requestRemoteEnsure: this.mode === `sync-present
|
|
404
|
+
requestRemoteEnsure: this.mode === `sync-present`,
|
|
405
|
+
lifecycleGeneration
|
|
384
406
|
})
|
|
385
407
|
);
|
|
408
|
+
if (lifecycleGeneration !== this.lifecycleGeneration) return;
|
|
386
409
|
await this.waitForAppliedReceiptsAfter(appliedCursor);
|
|
387
410
|
if (upstreamLoadSubset) {
|
|
388
411
|
try {
|
|
389
|
-
|
|
390
|
-
if (maybePromise instanceof Promise) {
|
|
391
|
-
await maybePromise.catch((error) => {
|
|
392
|
-
console.warn(
|
|
393
|
-
`Failed to load remote subset in persisted wrapper:`,
|
|
394
|
-
error
|
|
395
|
-
);
|
|
396
|
-
this.queueRemoteSubsetEnsure(options);
|
|
397
|
-
});
|
|
398
|
-
}
|
|
412
|
+
await upstreamLoadSubset(options);
|
|
399
413
|
} catch (error) {
|
|
414
|
+
if (options.signal?.aborted || typeof error === `object` && error !== null && `name` in error && error.name === `AbortError`) {
|
|
415
|
+
this.pendingRemoteSubsetEnsures.delete(this.getSubsetKey(options));
|
|
416
|
+
throw error;
|
|
417
|
+
}
|
|
400
418
|
console.warn(`Failed to trigger remote subset load:`, error);
|
|
401
419
|
this.queueRemoteSubsetEnsure(options);
|
|
420
|
+
throw error;
|
|
402
421
|
}
|
|
403
422
|
}
|
|
404
423
|
}
|
|
405
424
|
unloadSubset(options, upstreamUnloadSubset) {
|
|
406
425
|
this.activeSubsets.delete(this.getSubsetKey(options));
|
|
426
|
+
this.pendingRemoteSubsetEnsures.delete(this.getSubsetKey(options));
|
|
407
427
|
upstreamUnloadSubset?.(options);
|
|
408
428
|
}
|
|
409
429
|
async forceReloadSubset(options) {
|
|
410
|
-
this.
|
|
430
|
+
const lifecycleGeneration = this.lifecycleGeneration;
|
|
411
431
|
await this.applyMutex.run(
|
|
412
|
-
() => this.hydrateSubsetUnsafe(options, {
|
|
432
|
+
() => this.hydrateSubsetUnsafe(options, {
|
|
433
|
+
requestRemoteEnsure: false,
|
|
434
|
+
lifecycleGeneration
|
|
435
|
+
})
|
|
413
436
|
);
|
|
414
437
|
}
|
|
415
438
|
queueHydrationBufferedTransaction(transaction) {
|
|
@@ -499,6 +522,7 @@ class PersistedCollectionRuntime {
|
|
|
499
522
|
await this.persistAndConfirmCollectionMutations(collectionMutations);
|
|
500
523
|
}
|
|
501
524
|
cleanup() {
|
|
525
|
+
this.advanceLifecycle();
|
|
502
526
|
this.coordinatorUnsubscribe?.();
|
|
503
527
|
this.coordinatorUnsubscribe = null;
|
|
504
528
|
this.indexAddedUnsubscribe?.();
|
|
@@ -517,6 +541,14 @@ class PersistedCollectionRuntime {
|
|
|
517
541
|
this.queuedHydrationTransactions.length = 0;
|
|
518
542
|
this.queuedTxCommitted.length = 0;
|
|
519
543
|
this.clearSyncControls();
|
|
544
|
+
this.collection = null;
|
|
545
|
+
}
|
|
546
|
+
advanceLifecycle() {
|
|
547
|
+
this.lifecycleGeneration++;
|
|
548
|
+
this.started = false;
|
|
549
|
+
this.startupMetadataPromise = null;
|
|
550
|
+
this.startPromise = null;
|
|
551
|
+
this.resumeBaselinePromise = null;
|
|
520
552
|
}
|
|
521
553
|
withInternalApply(task) {
|
|
522
554
|
this.internalApplyDepth++;
|
|
@@ -550,12 +582,15 @@ class PersistedCollectionRuntime {
|
|
|
550
582
|
return this.applyMutex.run(() => this.scanPersistedRowsUnsafe(options));
|
|
551
583
|
}
|
|
552
584
|
async hydrateSubsetUnsafe(options, config) {
|
|
553
|
-
this.
|
|
585
|
+
this.hydratingGeneration = config.lifecycleGeneration;
|
|
554
586
|
try {
|
|
555
587
|
const rows = await this.loadSubsetRowsUnsafe(options);
|
|
588
|
+
if (config.lifecycleGeneration !== this.lifecycleGeneration) return;
|
|
556
589
|
this.applyRowsToCollection(rows);
|
|
557
590
|
} finally {
|
|
558
|
-
this.
|
|
591
|
+
if (this.hydratingGeneration === config.lifecycleGeneration) {
|
|
592
|
+
this.hydratingGeneration = null;
|
|
593
|
+
}
|
|
559
594
|
}
|
|
560
595
|
await this.flushQueuedHydrationTransactionsUnsafe();
|
|
561
596
|
await this.flushQueuedTxCommittedUnsafe();
|
|
@@ -949,21 +984,15 @@ class PersistedCollectionRuntime {
|
|
|
949
984
|
};
|
|
950
985
|
}
|
|
951
986
|
getSubsetKey(options) {
|
|
952
|
-
|
|
953
|
-
if (
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
return existingId;
|
|
957
|
-
}
|
|
958
|
-
this.nextSubscriptionId++;
|
|
959
|
-
const id = `sub:${this.nextSubscriptionId}`;
|
|
960
|
-
this.subscriptionIds.set(subscription, id);
|
|
961
|
-
return id;
|
|
987
|
+
let id = this.requestIds.get(options);
|
|
988
|
+
if (id === void 0) {
|
|
989
|
+
id = `request:${++this.nextRequestId}`;
|
|
990
|
+
this.requestIds.set(options, id);
|
|
962
991
|
}
|
|
963
|
-
return
|
|
992
|
+
return id;
|
|
964
993
|
}
|
|
965
994
|
queueRemoteSubsetEnsure(options) {
|
|
966
|
-
if (this.mode !== `sync-present` || !this.persistence.coordinator.requestEnsureRemoteSubset) {
|
|
995
|
+
if (this.mode !== `sync-present` || !this.persistence.coordinator.requestEnsureRemoteSubset || this.activeSubsets.get(this.getSubsetKey(options)) !== options) {
|
|
967
996
|
return;
|
|
968
997
|
}
|
|
969
998
|
this.pendingRemoteSubsetEnsures.set(this.getSubsetKey(options), options);
|
|
@@ -1020,7 +1049,7 @@ class PersistedCollectionRuntime {
|
|
|
1020
1049
|
const { payload } = message;
|
|
1021
1050
|
const isSelf = message.senderId === this.persistence.coordinator.getNodeId();
|
|
1022
1051
|
if (isTxCommittedPayload(payload)) {
|
|
1023
|
-
if (this.
|
|
1052
|
+
if (this.isHydratingNow()) {
|
|
1024
1053
|
this.queuedTxCommitted.push(payload);
|
|
1025
1054
|
return;
|
|
1026
1055
|
}
|
|
@@ -1190,13 +1219,16 @@ class PersistedCollectionRuntime {
|
|
|
1190
1219
|
});
|
|
1191
1220
|
}
|
|
1192
1221
|
async reloadActiveSubsetsUnsafe() {
|
|
1222
|
+
const lifecycleGeneration = this.lifecycleGeneration;
|
|
1193
1223
|
const activeSubsetOptions = this.activeSubsets.size > 0 ? Array.from(this.activeSubsets.values()) : [{}];
|
|
1194
|
-
this.
|
|
1224
|
+
this.hydratingGeneration = lifecycleGeneration;
|
|
1195
1225
|
try {
|
|
1196
1226
|
const mergedRows = /* @__PURE__ */ new Map();
|
|
1197
1227
|
const collectionMetadata = await this.loadCollectionMetadataSnapshot();
|
|
1228
|
+
if (lifecycleGeneration !== this.lifecycleGeneration) return;
|
|
1198
1229
|
for (const options of activeSubsetOptions) {
|
|
1199
1230
|
const subsetRows = await this.loadSubsetRowsUnsafe(options);
|
|
1231
|
+
if (lifecycleGeneration !== this.lifecycleGeneration) return;
|
|
1200
1232
|
for (const row of subsetRows) {
|
|
1201
1233
|
mergedRows.set(row.key, {
|
|
1202
1234
|
value: row.value,
|
|
@@ -1213,7 +1245,9 @@ class PersistedCollectionRuntime {
|
|
|
1213
1245
|
collectionMetadata
|
|
1214
1246
|
);
|
|
1215
1247
|
} finally {
|
|
1216
|
-
this.
|
|
1248
|
+
if (this.hydratingGeneration === lifecycleGeneration) {
|
|
1249
|
+
this.hydratingGeneration = null;
|
|
1250
|
+
}
|
|
1217
1251
|
}
|
|
1218
1252
|
await this.flushQueuedHydrationTransactionsUnsafe();
|
|
1219
1253
|
await this.flushQueuedTxCommittedUnsafe();
|
|
@@ -1297,23 +1331,8 @@ function createWrappedSyncConfig(sourceSyncConfig, runtime) {
|
|
|
1297
1331
|
const transactionStack = [];
|
|
1298
1332
|
const getOpenTransaction = () => transactionStack[transactionStack.length - 1];
|
|
1299
1333
|
let fullStartPromise = null;
|
|
1300
|
-
const
|
|
1301
|
-
const
|
|
1302
|
-
let nextLoadSubscriptionId = 0;
|
|
1303
|
-
const getLoadKey = (options) => {
|
|
1304
|
-
const subscription = options.subscription;
|
|
1305
|
-
if (subscription && typeof subscription === `object`) {
|
|
1306
|
-
const existingId = loadSubscriptionIds.get(subscription);
|
|
1307
|
-
if (existingId) {
|
|
1308
|
-
return `sub:${existingId}`;
|
|
1309
|
-
}
|
|
1310
|
-
nextLoadSubscriptionId++;
|
|
1311
|
-
const nextId = String(nextLoadSubscriptionId);
|
|
1312
|
-
loadSubscriptionIds.set(subscription, nextId);
|
|
1313
|
-
return `sub:${nextId}`;
|
|
1314
|
-
}
|
|
1315
|
-
return `opts:${stableSerialize(normalizeSubsetOptionsForKey(options))}`;
|
|
1316
|
-
};
|
|
1334
|
+
const startupState = { cleanedUp: false };
|
|
1335
|
+
const acquisitions = /* @__PURE__ */ new Map();
|
|
1317
1336
|
runtime.setSyncControls({
|
|
1318
1337
|
begin: params.begin,
|
|
1319
1338
|
write: params.write,
|
|
@@ -1327,9 +1346,12 @@ function createWrappedSyncConfig(sourceSyncConfig, runtime) {
|
|
|
1327
1346
|
const wrappedParams = {
|
|
1328
1347
|
...params,
|
|
1329
1348
|
markReady: () => {
|
|
1349
|
+
if (startupState.cleanedUp) return;
|
|
1330
1350
|
void (fullStartPromise ?? runtime.ensureStarted()).then(() => {
|
|
1351
|
+
if (startupState.cleanedUp) return;
|
|
1331
1352
|
params.markReady();
|
|
1332
1353
|
}).catch((error) => {
|
|
1354
|
+
if (startupState.cleanedUp) return;
|
|
1333
1355
|
console.warn(
|
|
1334
1356
|
`Failed persisted sync startup before markReady:`,
|
|
1335
1357
|
error
|
|
@@ -1338,6 +1360,7 @@ function createWrappedSyncConfig(sourceSyncConfig, runtime) {
|
|
|
1338
1360
|
});
|
|
1339
1361
|
},
|
|
1340
1362
|
begin: (options) => {
|
|
1363
|
+
if (startupState.cleanedUp) return;
|
|
1341
1364
|
const transaction = {
|
|
1342
1365
|
operations: [],
|
|
1343
1366
|
rowMetadataWrites: /* @__PURE__ */ new Map(),
|
|
@@ -1352,6 +1375,7 @@ function createWrappedSyncConfig(sourceSyncConfig, runtime) {
|
|
|
1352
1375
|
}
|
|
1353
1376
|
},
|
|
1354
1377
|
write: (message) => {
|
|
1378
|
+
if (startupState.cleanedUp) return;
|
|
1355
1379
|
const normalization = runtime.normalizeSyncWriteMessage(message);
|
|
1356
1380
|
const openTransaction = getOpenTransaction();
|
|
1357
1381
|
if (!openTransaction) {
|
|
@@ -1386,7 +1410,9 @@ function createWrappedSyncConfig(sourceSyncConfig, runtime) {
|
|
|
1386
1410
|
},
|
|
1387
1411
|
metadata: params.metadata ? {
|
|
1388
1412
|
row: {
|
|
1413
|
+
whenHydrated: () => startupState.cleanedUp ? Promise.resolve() : runtime.ensureResumeBaselineHydrated(),
|
|
1389
1414
|
get: (key) => {
|
|
1415
|
+
if (startupState.cleanedUp) return void 0;
|
|
1390
1416
|
const openTransaction = getOpenTransaction();
|
|
1391
1417
|
const pendingWrite = openTransaction?.rowMetadataWrites.get(key);
|
|
1392
1418
|
if (pendingWrite) {
|
|
@@ -1397,8 +1423,9 @@ function createWrappedSyncConfig(sourceSyncConfig, runtime) {
|
|
|
1397
1423
|
}
|
|
1398
1424
|
return params.metadata.row.get(key);
|
|
1399
1425
|
},
|
|
1400
|
-
scanPersisted: (options) => runtime.scanPersistedRows(options),
|
|
1426
|
+
scanPersisted: (options) => startupState.cleanedUp ? Promise.resolve([]) : runtime.scanPersistedRows(options),
|
|
1401
1427
|
set: (key, value) => {
|
|
1428
|
+
if (startupState.cleanedUp) return;
|
|
1402
1429
|
const openTransaction = getOpenTransaction();
|
|
1403
1430
|
if (!openTransaction) {
|
|
1404
1431
|
throw new InvalidPersistedCollectionConfigError(
|
|
@@ -1414,6 +1441,7 @@ function createWrappedSyncConfig(sourceSyncConfig, runtime) {
|
|
|
1414
1441
|
}
|
|
1415
1442
|
},
|
|
1416
1443
|
delete: (key) => {
|
|
1444
|
+
if (startupState.cleanedUp) return;
|
|
1417
1445
|
const openTransaction = getOpenTransaction();
|
|
1418
1446
|
if (!openTransaction) {
|
|
1419
1447
|
throw new InvalidPersistedCollectionConfigError(
|
|
@@ -1430,6 +1458,7 @@ function createWrappedSyncConfig(sourceSyncConfig, runtime) {
|
|
|
1430
1458
|
},
|
|
1431
1459
|
collection: {
|
|
1432
1460
|
get: (key) => {
|
|
1461
|
+
if (startupState.cleanedUp) return void 0;
|
|
1433
1462
|
const openTransaction = getOpenTransaction();
|
|
1434
1463
|
const pendingWrite = openTransaction?.collectionMetadataWrites.get(key);
|
|
1435
1464
|
if (pendingWrite) {
|
|
@@ -1438,6 +1467,7 @@ function createWrappedSyncConfig(sourceSyncConfig, runtime) {
|
|
|
1438
1467
|
return params.metadata.collection.get(key);
|
|
1439
1468
|
},
|
|
1440
1469
|
set: (key, value) => {
|
|
1470
|
+
if (startupState.cleanedUp) return;
|
|
1441
1471
|
const openTransaction = getOpenTransaction();
|
|
1442
1472
|
if (!openTransaction) {
|
|
1443
1473
|
throw new InvalidPersistedCollectionConfigError(
|
|
@@ -1453,6 +1483,7 @@ function createWrappedSyncConfig(sourceSyncConfig, runtime) {
|
|
|
1453
1483
|
}
|
|
1454
1484
|
},
|
|
1455
1485
|
delete: (key) => {
|
|
1486
|
+
if (startupState.cleanedUp) return;
|
|
1456
1487
|
const openTransaction = getOpenTransaction();
|
|
1457
1488
|
if (!openTransaction) {
|
|
1458
1489
|
throw new InvalidPersistedCollectionConfigError(
|
|
@@ -1467,6 +1498,7 @@ function createWrappedSyncConfig(sourceSyncConfig, runtime) {
|
|
|
1467
1498
|
}
|
|
1468
1499
|
},
|
|
1469
1500
|
list: (prefix) => {
|
|
1501
|
+
if (startupState.cleanedUp) return [];
|
|
1470
1502
|
const merged = new Map(
|
|
1471
1503
|
params.metadata.collection.list().map(({ key, value }) => [key, value])
|
|
1472
1504
|
);
|
|
@@ -1491,6 +1523,7 @@ function createWrappedSyncConfig(sourceSyncConfig, runtime) {
|
|
|
1491
1523
|
}
|
|
1492
1524
|
} : void 0,
|
|
1493
1525
|
truncate: () => {
|
|
1526
|
+
if (startupState.cleanedUp) return;
|
|
1494
1527
|
const openTransaction = getOpenTransaction();
|
|
1495
1528
|
if (!openTransaction) {
|
|
1496
1529
|
params.truncate();
|
|
@@ -1504,6 +1537,7 @@ function createWrappedSyncConfig(sourceSyncConfig, runtime) {
|
|
|
1504
1537
|
}
|
|
1505
1538
|
},
|
|
1506
1539
|
commit: (signal) => {
|
|
1540
|
+
if (startupState.cleanedUp) return true;
|
|
1507
1541
|
const openTransaction = transactionStack.pop();
|
|
1508
1542
|
if (!openTransaction) {
|
|
1509
1543
|
return params.commit(signal);
|
|
@@ -1553,7 +1587,6 @@ function createWrappedSyncConfig(sourceSyncConfig, runtime) {
|
|
|
1553
1587
|
}
|
|
1554
1588
|
};
|
|
1555
1589
|
let sourceResult = {};
|
|
1556
|
-
const startupState = { cleanedUp: false };
|
|
1557
1590
|
fullStartPromise = runtime.ensureStarted();
|
|
1558
1591
|
const sourceResultPromise = (async () => {
|
|
1559
1592
|
await runtime.ensureStartupMetadataLoaded();
|
|
@@ -1568,23 +1601,40 @@ function createWrappedSyncConfig(sourceSyncConfig, runtime) {
|
|
|
1568
1601
|
return {
|
|
1569
1602
|
cleanup: () => {
|
|
1570
1603
|
startupState.cleanedUp = true;
|
|
1604
|
+
acquisitions.clear();
|
|
1571
1605
|
sourceResult.cleanup?.();
|
|
1572
1606
|
runtime.cleanup();
|
|
1573
1607
|
runtime.clearSyncControls();
|
|
1574
1608
|
},
|
|
1575
1609
|
loadSubset: async (options) => {
|
|
1576
|
-
const
|
|
1577
|
-
|
|
1610
|
+
const acquisition = { forwarded: false };
|
|
1611
|
+
acquisitions.set(options, acquisition);
|
|
1578
1612
|
await fullStartPromise;
|
|
1579
1613
|
const resolvedSourceResult = await sourceResultPromise;
|
|
1580
|
-
if (startupState.cleanedUp ||
|
|
1614
|
+
if (startupState.cleanedUp || acquisitions.get(options) !== acquisition) {
|
|
1581
1615
|
return;
|
|
1582
1616
|
}
|
|
1583
|
-
|
|
1617
|
+
return runtime.loadSubset(options, (loadOptions) => {
|
|
1618
|
+
if (startupState.cleanedUp || acquisitions.get(options) !== acquisition) {
|
|
1619
|
+
return true;
|
|
1620
|
+
}
|
|
1621
|
+
if (!resolvedSourceResult.loadSubset) return true;
|
|
1622
|
+
acquisition.forwarded = true;
|
|
1623
|
+
try {
|
|
1624
|
+
return resolvedSourceResult.loadSubset(loadOptions);
|
|
1625
|
+
} catch (error) {
|
|
1626
|
+
acquisition.forwarded = false;
|
|
1627
|
+
throw error;
|
|
1628
|
+
}
|
|
1629
|
+
});
|
|
1584
1630
|
},
|
|
1585
1631
|
unloadSubset: (options) => {
|
|
1586
|
-
|
|
1587
|
-
|
|
1632
|
+
const acquisition = acquisitions.get(options);
|
|
1633
|
+
acquisitions.delete(options);
|
|
1634
|
+
runtime.unloadSubset(
|
|
1635
|
+
options,
|
|
1636
|
+
acquisition?.forwarded ? sourceResult.unloadSubset : void 0
|
|
1637
|
+
);
|
|
1588
1638
|
}
|
|
1589
1639
|
};
|
|
1590
1640
|
}
|