@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
|
@@ -2714,8 +2714,10 @@ var OfflineStore = class {
|
|
|
2714
2714
|
}
|
|
2715
2715
|
destroy() {
|
|
2716
2716
|
this._destroyed = true;
|
|
2717
|
+
const db = this.db;
|
|
2717
2718
|
this.db = null;
|
|
2718
2719
|
this.dbPromise = null;
|
|
2720
|
+
if (db) Promise.resolve().then(() => db.close());
|
|
2719
2721
|
}
|
|
2720
2722
|
};
|
|
2721
2723
|
|
|
@@ -3070,8 +3072,11 @@ var AbracadabraProvider = class AbracadabraProvider extends AbracadabraBaseProvi
|
|
|
3070
3072
|
}
|
|
3071
3073
|
destroy() {
|
|
3072
3074
|
this.document.off("subdocs", this.boundHandleYSubdocsChange);
|
|
3075
|
+
const childIds = [...this.childProviders.keys()];
|
|
3073
3076
|
for (const provider of this.childProviders.values()) provider.destroy();
|
|
3074
3077
|
this.childProviders.clear();
|
|
3078
|
+
const wsProviderMap = this.configuration.websocketProvider?.configuration?.providerMap;
|
|
3079
|
+
if (wsProviderMap) for (const childId of childIds) wsProviderMap.delete(childId);
|
|
3075
3080
|
this.offlineStore?.destroy();
|
|
3076
3081
|
this.offlineStore = null;
|
|
3077
3082
|
super.destroy();
|
|
@@ -8367,7 +8372,9 @@ var BackgroundSyncManager = class extends EventEmitter {
|
|
|
8367
8372
|
this.opts = {
|
|
8368
8373
|
concurrency: opts?.concurrency ?? 2,
|
|
8369
8374
|
syncTimeout: opts?.syncTimeout ?? 15e3,
|
|
8370
|
-
prefetchFiles: opts?.prefetchFiles ?? true
|
|
8375
|
+
prefetchFiles: opts?.prefetchFiles ?? true,
|
|
8376
|
+
throttleMs: opts?.throttleMs ?? 50,
|
|
8377
|
+
maxRetries: opts?.maxRetries ?? 2
|
|
8371
8378
|
};
|
|
8372
8379
|
let serverOrigin = "default";
|
|
8373
8380
|
try {
|
|
@@ -8401,7 +8408,38 @@ var BackgroundSyncManager = class extends EventEmitter {
|
|
|
8401
8408
|
for (const [docId, v] of entries) updatedAtMap.set(docId, v?.updatedAt ?? v?.createdAt ?? 0);
|
|
8402
8409
|
this._prefetchCovers(entries).catch(() => null);
|
|
8403
8410
|
const queue = this._buildQueue(entries);
|
|
8404
|
-
|
|
8411
|
+
const failed = [];
|
|
8412
|
+
let idx = 0;
|
|
8413
|
+
const next = async () => {
|
|
8414
|
+
while (idx < queue.length) {
|
|
8415
|
+
if (this._destroyed) return;
|
|
8416
|
+
const docId = queue[idx++];
|
|
8417
|
+
const updatedAt = updatedAtMap.get(docId) ?? 0;
|
|
8418
|
+
if (!await this._syncWithSemaphore(docId, updatedAt)) failed.push(docId);
|
|
8419
|
+
if (this.opts.throttleMs > 0 && idx < queue.length) await new Promise((r) => setTimeout(r, this.opts.throttleMs));
|
|
8420
|
+
}
|
|
8421
|
+
};
|
|
8422
|
+
const workers = Array.from({ length: this.opts.concurrency }, () => next());
|
|
8423
|
+
await Promise.all(workers);
|
|
8424
|
+
for (let retry = 0; retry < this.opts.maxRetries && failed.length > 0; retry++) {
|
|
8425
|
+
if (this._destroyed) return;
|
|
8426
|
+
const batch = failed.splice(0, failed.length);
|
|
8427
|
+
const backoff = 2e3 * 2 ** retry;
|
|
8428
|
+
await new Promise((r) => setTimeout(r, backoff));
|
|
8429
|
+
idx = 0;
|
|
8430
|
+
const retryQueue = batch;
|
|
8431
|
+
const retryNext = async () => {
|
|
8432
|
+
while (idx < retryQueue.length) {
|
|
8433
|
+
if (this._destroyed) return;
|
|
8434
|
+
const docId = retryQueue[idx++];
|
|
8435
|
+
const updatedAt = updatedAtMap.get(docId) ?? 0;
|
|
8436
|
+
if (!await this._syncWithSemaphore(docId, updatedAt)) failed.push(docId);
|
|
8437
|
+
if (this.opts.throttleMs > 0 && idx < retryQueue.length) await new Promise((r) => setTimeout(r, this.opts.throttleMs));
|
|
8438
|
+
}
|
|
8439
|
+
};
|
|
8440
|
+
const retryWorkers = Array.from({ length: this.opts.concurrency }, () => retryNext());
|
|
8441
|
+
await Promise.all(retryWorkers);
|
|
8442
|
+
}
|
|
8405
8443
|
}
|
|
8406
8444
|
/** Sync a single document by ID. */
|
|
8407
8445
|
async syncDoc(docId) {
|
|
@@ -8482,15 +8520,16 @@ var BackgroundSyncManager = class extends EventEmitter {
|
|
|
8482
8520
|
items.sort((a, b) => b.priority - a.priority);
|
|
8483
8521
|
return items.map((i) => i.docId);
|
|
8484
8522
|
}
|
|
8523
|
+
/** Returns true on success (or skip), false on error. */
|
|
8485
8524
|
async _syncWithSemaphore(docId, updatedAt) {
|
|
8486
|
-
if (this._destroyed) return;
|
|
8525
|
+
if (this._destroyed) return true;
|
|
8487
8526
|
const existing = this.syncStates.get(docId);
|
|
8488
8527
|
if (existing && existing.status === "synced" && existing.lastSynced !== null && existing.lastSynced >= updatedAt) {
|
|
8489
8528
|
this.emit("stateChanged", {
|
|
8490
8529
|
docId,
|
|
8491
8530
|
state: existing
|
|
8492
8531
|
});
|
|
8493
|
-
return;
|
|
8532
|
+
return true;
|
|
8494
8533
|
}
|
|
8495
8534
|
await this.semaphore.acquire();
|
|
8496
8535
|
try {
|
|
@@ -8501,6 +8540,7 @@ var BackgroundSyncManager = class extends EventEmitter {
|
|
|
8501
8540
|
docId,
|
|
8502
8541
|
state
|
|
8503
8542
|
});
|
|
8543
|
+
return state.status !== "error";
|
|
8504
8544
|
} finally {
|
|
8505
8545
|
this.semaphore.release();
|
|
8506
8546
|
}
|
|
@@ -8536,10 +8576,12 @@ var BackgroundSyncManager = class extends EventEmitter {
|
|
|
8536
8576
|
}
|
|
8537
8577
|
}
|
|
8538
8578
|
async _syncNonE2EDoc(docId) {
|
|
8579
|
+
const alreadyCached = this.rootProvider.children.has(docId);
|
|
8539
8580
|
const childProvider = await this.rootProvider.loadChild(docId);
|
|
8540
8581
|
await childProvider.ready;
|
|
8541
8582
|
await this._waitForSynced(childProvider);
|
|
8542
8583
|
if (this.opts.prefetchFiles && this.fileBlobStore) this._prefetchDocFiles(docId, childProvider.document).catch(() => null);
|
|
8584
|
+
if (!alreadyCached) this.rootProvider.unloadChild(docId);
|
|
8543
8585
|
return {
|
|
8544
8586
|
docId,
|
|
8545
8587
|
status: "synced",
|