@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
|
@@ -4163,30 +4163,44 @@ function throttleTrailing(func, wait) {
|
|
|
4163
4163
|
}
|
|
4164
4164
|
};
|
|
4165
4165
|
}
|
|
4166
|
-
|
|
4167
|
-
|
|
4168
|
-
|
|
4169
|
-
|
|
4170
|
-
|
|
4171
|
-
|
|
4172
|
-
|
|
4173
|
-
|
|
4174
|
-
|
|
4175
|
-
|
|
4176
|
-
|
|
4177
|
-
|
|
4178
|
-
|
|
4179
|
-
|
|
4180
|
-
|
|
4181
|
-
|
|
4182
|
-
|
|
4183
|
-
|
|
4184
|
-
|
|
4185
|
-
|
|
4186
|
-
|
|
4187
|
-
|
|
4188
|
-
|
|
4189
|
-
|
|
4166
|
+
function asyncNotifier() {
|
|
4167
|
+
let waitingConsumer = null;
|
|
4168
|
+
let hasPendingNotification = false;
|
|
4169
|
+
return {
|
|
4170
|
+
notify() {
|
|
4171
|
+
if (waitingConsumer != null) {
|
|
4172
|
+
waitingConsumer();
|
|
4173
|
+
waitingConsumer = null;
|
|
4174
|
+
}
|
|
4175
|
+
else {
|
|
4176
|
+
hasPendingNotification = true;
|
|
4177
|
+
}
|
|
4178
|
+
},
|
|
4179
|
+
waitForNotification(signal) {
|
|
4180
|
+
return new Promise((resolve) => {
|
|
4181
|
+
if (waitingConsumer != null) {
|
|
4182
|
+
throw new Error('Illegal call to waitForNotification, already has a waiter.');
|
|
4183
|
+
}
|
|
4184
|
+
if (signal.aborted) {
|
|
4185
|
+
resolve();
|
|
4186
|
+
}
|
|
4187
|
+
else if (hasPendingNotification) {
|
|
4188
|
+
resolve();
|
|
4189
|
+
hasPendingNotification = false;
|
|
4190
|
+
}
|
|
4191
|
+
else {
|
|
4192
|
+
function complete() {
|
|
4193
|
+
signal.removeEventListener('abort', onAbort);
|
|
4194
|
+
resolve();
|
|
4195
|
+
}
|
|
4196
|
+
function onAbort() {
|
|
4197
|
+
waitingConsumer = null;
|
|
4198
|
+
resolve();
|
|
4199
|
+
}
|
|
4200
|
+
waitingConsumer = complete;
|
|
4201
|
+
signal.addEventListener('abort', onAbort);
|
|
4202
|
+
}
|
|
4203
|
+
});
|
|
4190
4204
|
}
|
|
4191
4205
|
};
|
|
4192
4206
|
}
|
|
@@ -12388,7 +12402,7 @@ function requireDist () {
|
|
|
12388
12402
|
|
|
12389
12403
|
var distExports = requireDist();
|
|
12390
12404
|
|
|
12391
|
-
var version = "1.53.
|
|
12405
|
+
var version = "1.53.2";
|
|
12392
12406
|
var PACKAGE = {
|
|
12393
12407
|
version: version};
|
|
12394
12408
|
|
|
@@ -13296,19 +13310,15 @@ const DEFAULT_STREAM_CONNECTION_OPTIONS = {
|
|
|
13296
13310
|
class AbstractStreamingSyncImplementation extends BaseObserver {
|
|
13297
13311
|
options;
|
|
13298
13312
|
abortController;
|
|
13299
|
-
// In rare cases, mostly for tests, uploads can be triggered without being properly connected.
|
|
13300
|
-
// This allows ensuring that all upload processes can be aborted.
|
|
13301
|
-
uploadAbortController;
|
|
13302
13313
|
crudUpdateListener;
|
|
13303
13314
|
streamingSyncPromise;
|
|
13304
13315
|
logger;
|
|
13305
13316
|
activeStreams;
|
|
13306
13317
|
connectionMayHaveChanged = false;
|
|
13307
|
-
|
|
13318
|
+
crudUploadNotifier = asyncNotifier();
|
|
13308
13319
|
notifyCompletedUploads;
|
|
13309
13320
|
handleActiveStreamsChange;
|
|
13310
13321
|
syncStatus;
|
|
13311
|
-
triggerCrudUpload;
|
|
13312
13322
|
constructor(options) {
|
|
13313
13323
|
super();
|
|
13314
13324
|
this.options = options;
|
|
@@ -13324,16 +13334,9 @@ class AbstractStreamingSyncImplementation extends BaseObserver {
|
|
|
13324
13334
|
}
|
|
13325
13335
|
});
|
|
13326
13336
|
this.abortController = null;
|
|
13327
|
-
|
|
13328
|
-
|
|
13329
|
-
|
|
13330
|
-
}
|
|
13331
|
-
this.isUploadingCrud = true;
|
|
13332
|
-
this._uploadAllCrud().finally(() => {
|
|
13333
|
-
this.notifyCompletedUploads?.();
|
|
13334
|
-
this.isUploadingCrud = false;
|
|
13335
|
-
});
|
|
13336
|
-
}, this.options.crudUploadThrottleMs);
|
|
13337
|
+
}
|
|
13338
|
+
triggerCrudUpload() {
|
|
13339
|
+
this.crudUploadNotifier.notify();
|
|
13337
13340
|
}
|
|
13338
13341
|
async waitForReady() { }
|
|
13339
13342
|
waitForStatus(status) {
|
|
@@ -13381,7 +13384,6 @@ class AbstractStreamingSyncImplementation extends BaseObserver {
|
|
|
13381
13384
|
super.dispose();
|
|
13382
13385
|
this.crudUpdateListener?.();
|
|
13383
13386
|
this.crudUpdateListener = undefined;
|
|
13384
|
-
this.uploadAbortController?.abort();
|
|
13385
13387
|
}
|
|
13386
13388
|
async getWriteCheckpoint() {
|
|
13387
13389
|
const clientId = await this.options.adapter.getClientId();
|
|
@@ -13391,7 +13393,17 @@ class AbstractStreamingSyncImplementation extends BaseObserver {
|
|
|
13391
13393
|
this.logger.debug(`Created write checkpoint: ${checkpoint}`);
|
|
13392
13394
|
return checkpoint;
|
|
13393
13395
|
}
|
|
13394
|
-
async
|
|
13396
|
+
async crudUploadLoop(signal) {
|
|
13397
|
+
while (!signal.aborted) {
|
|
13398
|
+
await Promise.all([
|
|
13399
|
+
// Start the initial CRUD upload on connect. Then, keep polling until we're done.
|
|
13400
|
+
this._uploadAllCrud(signal),
|
|
13401
|
+
this.delayRetry(signal, this.options.crudUploadThrottleMs)
|
|
13402
|
+
]);
|
|
13403
|
+
await this.crudUploadNotifier.waitForNotification(signal);
|
|
13404
|
+
}
|
|
13405
|
+
}
|
|
13406
|
+
async _uploadAllCrud(signal) {
|
|
13395
13407
|
return this.obtainLock({
|
|
13396
13408
|
type: LockType.CRUD,
|
|
13397
13409
|
callback: async () => {
|
|
@@ -13399,12 +13411,7 @@ class AbstractStreamingSyncImplementation extends BaseObserver {
|
|
|
13399
13411
|
* Keep track of the first item in the CRUD queue for the last `uploadCrud` iteration.
|
|
13400
13412
|
*/
|
|
13401
13413
|
let checkedCrudItem;
|
|
13402
|
-
|
|
13403
|
-
this.uploadAbortController = controller;
|
|
13404
|
-
this.abortController?.signal.addEventListener('abort', () => {
|
|
13405
|
-
controller.abort();
|
|
13406
|
-
}, { once: true });
|
|
13407
|
-
while (!controller.signal.aborted) {
|
|
13414
|
+
while (!signal.aborted) {
|
|
13408
13415
|
try {
|
|
13409
13416
|
/**
|
|
13410
13417
|
* This is the first item in the FIFO CRUD queue.
|
|
@@ -13434,7 +13441,10 @@ The next upload iteration will be delayed.`);
|
|
|
13434
13441
|
else {
|
|
13435
13442
|
// Uploading is completed
|
|
13436
13443
|
const neededUpdate = await this.options.adapter.updateLocalTarget(() => this.getWriteCheckpoint());
|
|
13437
|
-
if (neededUpdate
|
|
13444
|
+
if (neededUpdate) {
|
|
13445
|
+
this.notifyCompletedUploads?.();
|
|
13446
|
+
}
|
|
13447
|
+
else if (checkedCrudItem != null) {
|
|
13438
13448
|
// Only log this if there was something to upload
|
|
13439
13449
|
this.logger.debug('Upload complete, no write checkpoint needed.');
|
|
13440
13450
|
}
|
|
@@ -13449,7 +13459,7 @@ The next upload iteration will be delayed.`);
|
|
|
13449
13459
|
uploadError: ex
|
|
13450
13460
|
}
|
|
13451
13461
|
});
|
|
13452
|
-
await this.delayRetry(
|
|
13462
|
+
await this.delayRetry(signal);
|
|
13453
13463
|
if (!this.isConnected) {
|
|
13454
13464
|
// Exit the upload loop if the sync stream is no longer connected
|
|
13455
13465
|
break;
|
|
@@ -13464,7 +13474,6 @@ The next upload iteration will be delayed.`);
|
|
|
13464
13474
|
});
|
|
13465
13475
|
}
|
|
13466
13476
|
}
|
|
13467
|
-
this.uploadAbortController = undefined;
|
|
13468
13477
|
}
|
|
13469
13478
|
});
|
|
13470
13479
|
}
|
|
@@ -13474,7 +13483,10 @@ The next upload iteration will be delayed.`);
|
|
|
13474
13483
|
}
|
|
13475
13484
|
const controller = new AbortController();
|
|
13476
13485
|
this.abortController = controller;
|
|
13477
|
-
this.streamingSyncPromise =
|
|
13486
|
+
this.streamingSyncPromise = Promise.all([
|
|
13487
|
+
this.crudUploadLoop(controller.signal).catch((ex) => this.logger.error('Error in crud upload loop', ex)),
|
|
13488
|
+
this.streamingSync(controller.signal, options)
|
|
13489
|
+
]);
|
|
13478
13490
|
// Return a promise that resolves when the connection status is updated to indicate that we're connected.
|
|
13479
13491
|
return new Promise((resolve) => {
|
|
13480
13492
|
const disposer = this.registerListener({
|
|
@@ -13512,14 +13524,7 @@ The next upload iteration will be delayed.`);
|
|
|
13512
13524
|
this.abortController = null;
|
|
13513
13525
|
this.updateSyncStatus({ connected: false, connecting: false });
|
|
13514
13526
|
}
|
|
13515
|
-
/**
|
|
13516
|
-
* @deprecated use [connect instead]
|
|
13517
|
-
*/
|
|
13518
13527
|
async streamingSync(signal, options) {
|
|
13519
|
-
if (!signal) {
|
|
13520
|
-
this.abortController = new AbortController();
|
|
13521
|
-
signal = this.abortController.signal;
|
|
13522
|
-
}
|
|
13523
13528
|
/**
|
|
13524
13529
|
* Listen for CRUD updates and trigger upstream uploads
|
|
13525
13530
|
*/
|
|
@@ -13893,14 +13898,13 @@ The next upload iteration will be delayed.`);
|
|
|
13893
13898
|
// trigger this for all updates
|
|
13894
13899
|
this.iterateListeners((cb) => cb.statusUpdated?.(options));
|
|
13895
13900
|
}
|
|
13896
|
-
async delayRetry(signal) {
|
|
13901
|
+
async delayRetry(signal, delay = this.options.retryDelayMs) {
|
|
13897
13902
|
return new Promise((resolve) => {
|
|
13898
13903
|
if (signal?.aborted) {
|
|
13899
13904
|
// If the signal is already aborted, resolve immediately
|
|
13900
13905
|
resolve();
|
|
13901
13906
|
return;
|
|
13902
13907
|
}
|
|
13903
|
-
const { retryDelayMs } = this.options;
|
|
13904
13908
|
let timeoutId;
|
|
13905
13909
|
const endDelay = () => {
|
|
13906
13910
|
resolve();
|
|
@@ -13911,7 +13915,7 @@ The next upload iteration will be delayed.`);
|
|
|
13911
13915
|
signal?.removeEventListener('abort', endDelay);
|
|
13912
13916
|
};
|
|
13913
13917
|
signal?.addEventListener('abort', endDelay, { once: true });
|
|
13914
|
-
timeoutId = setTimeout(endDelay,
|
|
13918
|
+
timeoutId = setTimeout(endDelay, delay);
|
|
13915
13919
|
});
|
|
13916
13920
|
}
|
|
13917
13921
|
updateSubscriptions(subscriptions) {
|