@powersync/web 1.38.1 → 1.38.2
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/worker/SharedSyncImplementation.umd.js +66 -62
- package/dist/worker/SharedSyncImplementation.umd.js.map +1 -1
- package/dist/worker/WASQLiteDB.umd.js +66 -62
- package/dist/worker/WASQLiteDB.umd.js.map +1 -1
- package/lib/package.json +2 -2
- package/lib/tsconfig.tsbuildinfo +1 -1
- package/package.json +3 -3
|
@@ -5321,30 +5321,44 @@ function throttleTrailing(func, wait) {
|
|
|
5321
5321
|
}
|
|
5322
5322
|
};
|
|
5323
5323
|
}
|
|
5324
|
-
|
|
5325
|
-
|
|
5326
|
-
|
|
5327
|
-
|
|
5328
|
-
|
|
5329
|
-
|
|
5330
|
-
|
|
5331
|
-
|
|
5332
|
-
|
|
5333
|
-
|
|
5334
|
-
|
|
5335
|
-
|
|
5336
|
-
|
|
5337
|
-
|
|
5338
|
-
|
|
5339
|
-
|
|
5340
|
-
|
|
5341
|
-
|
|
5342
|
-
|
|
5343
|
-
|
|
5344
|
-
|
|
5345
|
-
|
|
5346
|
-
|
|
5347
|
-
|
|
5324
|
+
function asyncNotifier() {
|
|
5325
|
+
let waitingConsumer = null;
|
|
5326
|
+
let hasPendingNotification = false;
|
|
5327
|
+
return {
|
|
5328
|
+
notify() {
|
|
5329
|
+
if (waitingConsumer != null) {
|
|
5330
|
+
waitingConsumer();
|
|
5331
|
+
waitingConsumer = null;
|
|
5332
|
+
}
|
|
5333
|
+
else {
|
|
5334
|
+
hasPendingNotification = true;
|
|
5335
|
+
}
|
|
5336
|
+
},
|
|
5337
|
+
waitForNotification(signal) {
|
|
5338
|
+
return new Promise((resolve) => {
|
|
5339
|
+
if (waitingConsumer != null) {
|
|
5340
|
+
throw new Error('Illegal call to waitForNotification, already has a waiter.');
|
|
5341
|
+
}
|
|
5342
|
+
if (signal.aborted) {
|
|
5343
|
+
resolve();
|
|
5344
|
+
}
|
|
5345
|
+
else if (hasPendingNotification) {
|
|
5346
|
+
resolve();
|
|
5347
|
+
hasPendingNotification = false;
|
|
5348
|
+
}
|
|
5349
|
+
else {
|
|
5350
|
+
function complete() {
|
|
5351
|
+
signal.removeEventListener('abort', onAbort);
|
|
5352
|
+
resolve();
|
|
5353
|
+
}
|
|
5354
|
+
function onAbort() {
|
|
5355
|
+
waitingConsumer = null;
|
|
5356
|
+
resolve();
|
|
5357
|
+
}
|
|
5358
|
+
waitingConsumer = complete;
|
|
5359
|
+
signal.addEventListener('abort', onAbort);
|
|
5360
|
+
}
|
|
5361
|
+
});
|
|
5348
5362
|
}
|
|
5349
5363
|
};
|
|
5350
5364
|
}
|
|
@@ -13546,7 +13560,7 @@ function requireDist () {
|
|
|
13546
13560
|
|
|
13547
13561
|
var distExports = requireDist();
|
|
13548
13562
|
|
|
13549
|
-
var version = "1.53.
|
|
13563
|
+
var version = "1.53.2";
|
|
13550
13564
|
var PACKAGE = {
|
|
13551
13565
|
version: version};
|
|
13552
13566
|
|
|
@@ -14454,19 +14468,15 @@ const DEFAULT_STREAM_CONNECTION_OPTIONS = {
|
|
|
14454
14468
|
class AbstractStreamingSyncImplementation extends BaseObserver {
|
|
14455
14469
|
options;
|
|
14456
14470
|
abortController;
|
|
14457
|
-
// In rare cases, mostly for tests, uploads can be triggered without being properly connected.
|
|
14458
|
-
// This allows ensuring that all upload processes can be aborted.
|
|
14459
|
-
uploadAbortController;
|
|
14460
14471
|
crudUpdateListener;
|
|
14461
14472
|
streamingSyncPromise;
|
|
14462
14473
|
logger;
|
|
14463
14474
|
activeStreams;
|
|
14464
14475
|
connectionMayHaveChanged = false;
|
|
14465
|
-
|
|
14476
|
+
crudUploadNotifier = asyncNotifier();
|
|
14466
14477
|
notifyCompletedUploads;
|
|
14467
14478
|
handleActiveStreamsChange;
|
|
14468
14479
|
syncStatus;
|
|
14469
|
-
triggerCrudUpload;
|
|
14470
14480
|
constructor(options) {
|
|
14471
14481
|
super();
|
|
14472
14482
|
this.options = options;
|
|
@@ -14482,16 +14492,9 @@ class AbstractStreamingSyncImplementation extends BaseObserver {
|
|
|
14482
14492
|
}
|
|
14483
14493
|
});
|
|
14484
14494
|
this.abortController = null;
|
|
14485
|
-
|
|
14486
|
-
|
|
14487
|
-
|
|
14488
|
-
}
|
|
14489
|
-
this.isUploadingCrud = true;
|
|
14490
|
-
this._uploadAllCrud().finally(() => {
|
|
14491
|
-
this.notifyCompletedUploads?.();
|
|
14492
|
-
this.isUploadingCrud = false;
|
|
14493
|
-
});
|
|
14494
|
-
}, this.options.crudUploadThrottleMs);
|
|
14495
|
+
}
|
|
14496
|
+
triggerCrudUpload() {
|
|
14497
|
+
this.crudUploadNotifier.notify();
|
|
14495
14498
|
}
|
|
14496
14499
|
async waitForReady() { }
|
|
14497
14500
|
waitForStatus(status) {
|
|
@@ -14539,7 +14542,6 @@ class AbstractStreamingSyncImplementation extends BaseObserver {
|
|
|
14539
14542
|
super.dispose();
|
|
14540
14543
|
this.crudUpdateListener?.();
|
|
14541
14544
|
this.crudUpdateListener = undefined;
|
|
14542
|
-
this.uploadAbortController?.abort();
|
|
14543
14545
|
}
|
|
14544
14546
|
async getWriteCheckpoint() {
|
|
14545
14547
|
const clientId = await this.options.adapter.getClientId();
|
|
@@ -14549,7 +14551,17 @@ class AbstractStreamingSyncImplementation extends BaseObserver {
|
|
|
14549
14551
|
this.logger.debug(`Created write checkpoint: ${checkpoint}`);
|
|
14550
14552
|
return checkpoint;
|
|
14551
14553
|
}
|
|
14552
|
-
async
|
|
14554
|
+
async crudUploadLoop(signal) {
|
|
14555
|
+
while (!signal.aborted) {
|
|
14556
|
+
await Promise.all([
|
|
14557
|
+
// Start the initial CRUD upload on connect. Then, keep polling until we're done.
|
|
14558
|
+
this._uploadAllCrud(signal),
|
|
14559
|
+
this.delayRetry(signal, this.options.crudUploadThrottleMs)
|
|
14560
|
+
]);
|
|
14561
|
+
await this.crudUploadNotifier.waitForNotification(signal);
|
|
14562
|
+
}
|
|
14563
|
+
}
|
|
14564
|
+
async _uploadAllCrud(signal) {
|
|
14553
14565
|
return this.obtainLock({
|
|
14554
14566
|
type: LockType.CRUD,
|
|
14555
14567
|
callback: async () => {
|
|
@@ -14557,12 +14569,7 @@ class AbstractStreamingSyncImplementation extends BaseObserver {
|
|
|
14557
14569
|
* Keep track of the first item in the CRUD queue for the last `uploadCrud` iteration.
|
|
14558
14570
|
*/
|
|
14559
14571
|
let checkedCrudItem;
|
|
14560
|
-
|
|
14561
|
-
this.uploadAbortController = controller;
|
|
14562
|
-
this.abortController?.signal.addEventListener('abort', () => {
|
|
14563
|
-
controller.abort();
|
|
14564
|
-
}, { once: true });
|
|
14565
|
-
while (!controller.signal.aborted) {
|
|
14572
|
+
while (!signal.aborted) {
|
|
14566
14573
|
try {
|
|
14567
14574
|
/**
|
|
14568
14575
|
* This is the first item in the FIFO CRUD queue.
|
|
@@ -14592,7 +14599,10 @@ The next upload iteration will be delayed.`);
|
|
|
14592
14599
|
else {
|
|
14593
14600
|
// Uploading is completed
|
|
14594
14601
|
const neededUpdate = await this.options.adapter.updateLocalTarget(() => this.getWriteCheckpoint());
|
|
14595
|
-
if (neededUpdate
|
|
14602
|
+
if (neededUpdate) {
|
|
14603
|
+
this.notifyCompletedUploads?.();
|
|
14604
|
+
}
|
|
14605
|
+
else if (checkedCrudItem != null) {
|
|
14596
14606
|
// Only log this if there was something to upload
|
|
14597
14607
|
this.logger.debug('Upload complete, no write checkpoint needed.');
|
|
14598
14608
|
}
|
|
@@ -14607,7 +14617,7 @@ The next upload iteration will be delayed.`);
|
|
|
14607
14617
|
uploadError: ex
|
|
14608
14618
|
}
|
|
14609
14619
|
});
|
|
14610
|
-
await this.delayRetry(
|
|
14620
|
+
await this.delayRetry(signal);
|
|
14611
14621
|
if (!this.isConnected) {
|
|
14612
14622
|
// Exit the upload loop if the sync stream is no longer connected
|
|
14613
14623
|
break;
|
|
@@ -14622,7 +14632,6 @@ The next upload iteration will be delayed.`);
|
|
|
14622
14632
|
});
|
|
14623
14633
|
}
|
|
14624
14634
|
}
|
|
14625
|
-
this.uploadAbortController = undefined;
|
|
14626
14635
|
}
|
|
14627
14636
|
});
|
|
14628
14637
|
}
|
|
@@ -14632,7 +14641,10 @@ The next upload iteration will be delayed.`);
|
|
|
14632
14641
|
}
|
|
14633
14642
|
const controller = new AbortController();
|
|
14634
14643
|
this.abortController = controller;
|
|
14635
|
-
this.streamingSyncPromise =
|
|
14644
|
+
this.streamingSyncPromise = Promise.all([
|
|
14645
|
+
this.crudUploadLoop(controller.signal).catch((ex) => this.logger.error('Error in crud upload loop', ex)),
|
|
14646
|
+
this.streamingSync(controller.signal, options)
|
|
14647
|
+
]);
|
|
14636
14648
|
// Return a promise that resolves when the connection status is updated to indicate that we're connected.
|
|
14637
14649
|
return new Promise((resolve) => {
|
|
14638
14650
|
const disposer = this.registerListener({
|
|
@@ -14670,14 +14682,7 @@ The next upload iteration will be delayed.`);
|
|
|
14670
14682
|
this.abortController = null;
|
|
14671
14683
|
this.updateSyncStatus({ connected: false, connecting: false });
|
|
14672
14684
|
}
|
|
14673
|
-
/**
|
|
14674
|
-
* @deprecated use [connect instead]
|
|
14675
|
-
*/
|
|
14676
14685
|
async streamingSync(signal, options) {
|
|
14677
|
-
if (!signal) {
|
|
14678
|
-
this.abortController = new AbortController();
|
|
14679
|
-
signal = this.abortController.signal;
|
|
14680
|
-
}
|
|
14681
14686
|
/**
|
|
14682
14687
|
* Listen for CRUD updates and trigger upstream uploads
|
|
14683
14688
|
*/
|
|
@@ -15051,14 +15056,13 @@ The next upload iteration will be delayed.`);
|
|
|
15051
15056
|
// trigger this for all updates
|
|
15052
15057
|
this.iterateListeners((cb) => cb.statusUpdated?.(options));
|
|
15053
15058
|
}
|
|
15054
|
-
async delayRetry(signal) {
|
|
15059
|
+
async delayRetry(signal, delay = this.options.retryDelayMs) {
|
|
15055
15060
|
return new Promise((resolve) => {
|
|
15056
15061
|
if (signal?.aborted) {
|
|
15057
15062
|
// If the signal is already aborted, resolve immediately
|
|
15058
15063
|
resolve();
|
|
15059
15064
|
return;
|
|
15060
15065
|
}
|
|
15061
|
-
const { retryDelayMs } = this.options;
|
|
15062
15066
|
let timeoutId;
|
|
15063
15067
|
const endDelay = () => {
|
|
15064
15068
|
resolve();
|
|
@@ -15069,7 +15073,7 @@ The next upload iteration will be delayed.`);
|
|
|
15069
15073
|
signal?.removeEventListener('abort', endDelay);
|
|
15070
15074
|
};
|
|
15071
15075
|
signal?.addEventListener('abort', endDelay, { once: true });
|
|
15072
|
-
timeoutId = setTimeout(endDelay,
|
|
15076
|
+
timeoutId = setTimeout(endDelay, delay);
|
|
15073
15077
|
});
|
|
15074
15078
|
}
|
|
15075
15079
|
updateSubscriptions(subscriptions) {
|