@abraca/dabra 1.0.17 → 1.0.19
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/abracadabra-provider.cjs +46 -4
- package/dist/abracadabra-provider.cjs.map +1 -1
- package/dist/abracadabra-provider.esm.js +46 -4
- package/dist/abracadabra-provider.esm.js.map +1 -1
- package/dist/index.d.ts +6 -1
- package/package.json +1 -1
- package/src/AbracadabraProvider.ts +15 -1
- package/src/BackgroundSyncManager.ts +69 -10
- package/src/OfflineStore.ts +7 -3
|
@@ -2744,8 +2744,10 @@ var OfflineStore = class {
|
|
|
2744
2744
|
}
|
|
2745
2745
|
destroy() {
|
|
2746
2746
|
this._destroyed = true;
|
|
2747
|
+
const db = this.db;
|
|
2747
2748
|
this.db = null;
|
|
2748
2749
|
this.dbPromise = null;
|
|
2750
|
+
if (db) Promise.resolve().then(() => db.close());
|
|
2749
2751
|
}
|
|
2750
2752
|
};
|
|
2751
2753
|
|
|
@@ -3100,8 +3102,11 @@ var AbracadabraProvider = class AbracadabraProvider extends AbracadabraBaseProvi
|
|
|
3100
3102
|
}
|
|
3101
3103
|
destroy() {
|
|
3102
3104
|
this.document.off("subdocs", this.boundHandleYSubdocsChange);
|
|
3105
|
+
const childIds = [...this.childProviders.keys()];
|
|
3103
3106
|
for (const provider of this.childProviders.values()) provider.destroy();
|
|
3104
3107
|
this.childProviders.clear();
|
|
3108
|
+
const wsProviderMap = this.configuration.websocketProvider?.configuration?.providerMap;
|
|
3109
|
+
if (wsProviderMap) for (const childId of childIds) wsProviderMap.delete(childId);
|
|
3105
3110
|
this.offlineStore?.destroy();
|
|
3106
3111
|
this.offlineStore = null;
|
|
3107
3112
|
super.destroy();
|
|
@@ -8419,7 +8424,9 @@ var BackgroundSyncManager = class extends EventEmitter {
|
|
|
8419
8424
|
this.opts = {
|
|
8420
8425
|
concurrency: opts?.concurrency ?? 2,
|
|
8421
8426
|
syncTimeout: opts?.syncTimeout ?? 15e3,
|
|
8422
|
-
prefetchFiles: opts?.prefetchFiles ?? true
|
|
8427
|
+
prefetchFiles: opts?.prefetchFiles ?? true,
|
|
8428
|
+
throttleMs: opts?.throttleMs ?? 50,
|
|
8429
|
+
maxRetries: opts?.maxRetries ?? 2
|
|
8423
8430
|
};
|
|
8424
8431
|
let serverOrigin = "default";
|
|
8425
8432
|
try {
|
|
@@ -8453,7 +8460,38 @@ var BackgroundSyncManager = class extends EventEmitter {
|
|
|
8453
8460
|
for (const [docId, v] of entries) updatedAtMap.set(docId, v?.updatedAt ?? v?.createdAt ?? 0);
|
|
8454
8461
|
this._prefetchCovers(entries).catch(() => null);
|
|
8455
8462
|
const queue = this._buildQueue(entries);
|
|
8456
|
-
|
|
8463
|
+
const failed = [];
|
|
8464
|
+
let idx = 0;
|
|
8465
|
+
const next = async () => {
|
|
8466
|
+
while (idx < queue.length) {
|
|
8467
|
+
if (this._destroyed) return;
|
|
8468
|
+
const docId = queue[idx++];
|
|
8469
|
+
const updatedAt = updatedAtMap.get(docId) ?? 0;
|
|
8470
|
+
if (!await this._syncWithSemaphore(docId, updatedAt)) failed.push(docId);
|
|
8471
|
+
if (this.opts.throttleMs > 0 && idx < queue.length) await new Promise((r) => setTimeout(r, this.opts.throttleMs));
|
|
8472
|
+
}
|
|
8473
|
+
};
|
|
8474
|
+
const workers = Array.from({ length: this.opts.concurrency }, () => next());
|
|
8475
|
+
await Promise.all(workers);
|
|
8476
|
+
for (let retry = 0; retry < this.opts.maxRetries && failed.length > 0; retry++) {
|
|
8477
|
+
if (this._destroyed) return;
|
|
8478
|
+
const batch = failed.splice(0, failed.length);
|
|
8479
|
+
const backoff = 2e3 * 2 ** retry;
|
|
8480
|
+
await new Promise((r) => setTimeout(r, backoff));
|
|
8481
|
+
idx = 0;
|
|
8482
|
+
const retryQueue = batch;
|
|
8483
|
+
const retryNext = async () => {
|
|
8484
|
+
while (idx < retryQueue.length) {
|
|
8485
|
+
if (this._destroyed) return;
|
|
8486
|
+
const docId = retryQueue[idx++];
|
|
8487
|
+
const updatedAt = updatedAtMap.get(docId) ?? 0;
|
|
8488
|
+
if (!await this._syncWithSemaphore(docId, updatedAt)) failed.push(docId);
|
|
8489
|
+
if (this.opts.throttleMs > 0 && idx < retryQueue.length) await new Promise((r) => setTimeout(r, this.opts.throttleMs));
|
|
8490
|
+
}
|
|
8491
|
+
};
|
|
8492
|
+
const retryWorkers = Array.from({ length: this.opts.concurrency }, () => retryNext());
|
|
8493
|
+
await Promise.all(retryWorkers);
|
|
8494
|
+
}
|
|
8457
8495
|
}
|
|
8458
8496
|
/** Sync a single document by ID. */
|
|
8459
8497
|
async syncDoc(docId) {
|
|
@@ -8534,15 +8572,16 @@ var BackgroundSyncManager = class extends EventEmitter {
|
|
|
8534
8572
|
items.sort((a, b) => b.priority - a.priority);
|
|
8535
8573
|
return items.map((i) => i.docId);
|
|
8536
8574
|
}
|
|
8575
|
+
/** Returns true on success (or skip), false on error. */
|
|
8537
8576
|
async _syncWithSemaphore(docId, updatedAt) {
|
|
8538
|
-
if (this._destroyed) return;
|
|
8577
|
+
if (this._destroyed) return true;
|
|
8539
8578
|
const existing = this.syncStates.get(docId);
|
|
8540
8579
|
if (existing && existing.status === "synced" && existing.lastSynced !== null && existing.lastSynced >= updatedAt) {
|
|
8541
8580
|
this.emit("stateChanged", {
|
|
8542
8581
|
docId,
|
|
8543
8582
|
state: existing
|
|
8544
8583
|
});
|
|
8545
|
-
return;
|
|
8584
|
+
return true;
|
|
8546
8585
|
}
|
|
8547
8586
|
await this.semaphore.acquire();
|
|
8548
8587
|
try {
|
|
@@ -8553,6 +8592,7 @@ var BackgroundSyncManager = class extends EventEmitter {
|
|
|
8553
8592
|
docId,
|
|
8554
8593
|
state
|
|
8555
8594
|
});
|
|
8595
|
+
return state.status !== "error";
|
|
8556
8596
|
} finally {
|
|
8557
8597
|
this.semaphore.release();
|
|
8558
8598
|
}
|
|
@@ -8588,10 +8628,12 @@ var BackgroundSyncManager = class extends EventEmitter {
|
|
|
8588
8628
|
}
|
|
8589
8629
|
}
|
|
8590
8630
|
async _syncNonE2EDoc(docId) {
|
|
8631
|
+
const alreadyCached = this.rootProvider.children.has(docId);
|
|
8591
8632
|
const childProvider = await this.rootProvider.loadChild(docId);
|
|
8592
8633
|
await childProvider.ready;
|
|
8593
8634
|
await this._waitForSynced(childProvider);
|
|
8594
8635
|
if (this.opts.prefetchFiles && this.fileBlobStore) this._prefetchDocFiles(docId, childProvider.document).catch(() => null);
|
|
8636
|
+
if (!alreadyCached) this.rootProvider.unloadChild(docId);
|
|
8595
8637
|
return {
|
|
8596
8638
|
docId,
|
|
8597
8639
|
status: "synced",
|