@powersync/common 1.53.0 → 1.53.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/bundle.cjs +72 -63
- package/dist/bundle.cjs.map +1 -1
- package/dist/bundle.mjs +72 -63
- package/dist/bundle.mjs.map +1 -1
- package/dist/bundle.node.cjs +72 -63
- package/dist/bundle.node.cjs.map +1 -1
- package/dist/bundle.node.mjs +72 -63
- package/dist/bundle.node.mjs.map +1 -1
- package/dist/index.d.cts +6 -9
- package/lib/client/sync/stream/AbstractStreamingSyncImplementation.d.ts +6 -9
- package/lib/client/sync/stream/AbstractStreamingSyncImplementation.js +28 -43
- package/lib/client/sync/stream/AbstractStreamingSyncImplementation.js.map +1 -1
- package/lib/utils/async.d.ts +13 -7
- package/lib/utils/async.js +38 -24
- package/lib/utils/async.js.map +1 -1
- package/lib/utils/stream_transform.js +6 -1
- package/lib/utils/stream_transform.js.map +1 -1
- package/package.json +1 -1
- package/src/client/sync/stream/AbstractStreamingSyncImplementation.ts +31 -54
- package/src/utils/async.ts +51 -24
- package/src/utils/stream_transform.ts +7 -1
package/dist/bundle.mjs
CHANGED
|
@@ -2428,30 +2428,44 @@ function throttleTrailing(func, wait) {
|
|
|
2428
2428
|
}
|
|
2429
2429
|
};
|
|
2430
2430
|
}
|
|
2431
|
-
|
|
2432
|
-
|
|
2433
|
-
|
|
2434
|
-
|
|
2435
|
-
|
|
2436
|
-
|
|
2437
|
-
|
|
2438
|
-
|
|
2439
|
-
|
|
2440
|
-
|
|
2441
|
-
|
|
2442
|
-
|
|
2443
|
-
|
|
2444
|
-
|
|
2445
|
-
|
|
2446
|
-
|
|
2447
|
-
|
|
2448
|
-
|
|
2449
|
-
|
|
2450
|
-
|
|
2451
|
-
|
|
2452
|
-
|
|
2453
|
-
|
|
2454
|
-
|
|
2431
|
+
function asyncNotifier() {
|
|
2432
|
+
let waitingConsumer = null;
|
|
2433
|
+
let hasPendingNotification = false;
|
|
2434
|
+
return {
|
|
2435
|
+
notify() {
|
|
2436
|
+
if (waitingConsumer != null) {
|
|
2437
|
+
waitingConsumer();
|
|
2438
|
+
waitingConsumer = null;
|
|
2439
|
+
}
|
|
2440
|
+
else {
|
|
2441
|
+
hasPendingNotification = true;
|
|
2442
|
+
}
|
|
2443
|
+
},
|
|
2444
|
+
waitForNotification(signal) {
|
|
2445
|
+
return new Promise((resolve) => {
|
|
2446
|
+
if (waitingConsumer != null) {
|
|
2447
|
+
throw new Error('Illegal call to waitForNotification, already has a waiter.');
|
|
2448
|
+
}
|
|
2449
|
+
if (signal.aborted) {
|
|
2450
|
+
resolve();
|
|
2451
|
+
}
|
|
2452
|
+
else if (hasPendingNotification) {
|
|
2453
|
+
resolve();
|
|
2454
|
+
hasPendingNotification = false;
|
|
2455
|
+
}
|
|
2456
|
+
else {
|
|
2457
|
+
function complete() {
|
|
2458
|
+
signal.removeEventListener('abort', onAbort);
|
|
2459
|
+
resolve();
|
|
2460
|
+
}
|
|
2461
|
+
function onAbort() {
|
|
2462
|
+
waitingConsumer = null;
|
|
2463
|
+
resolve();
|
|
2464
|
+
}
|
|
2465
|
+
waitingConsumer = complete;
|
|
2466
|
+
signal.addEventListener('abort', onAbort);
|
|
2467
|
+
}
|
|
2468
|
+
});
|
|
2455
2469
|
}
|
|
2456
2470
|
};
|
|
2457
2471
|
}
|
|
@@ -10653,7 +10667,7 @@ function requireDist () {
|
|
|
10653
10667
|
|
|
10654
10668
|
var distExports = requireDist();
|
|
10655
10669
|
|
|
10656
|
-
var version = "1.53.
|
|
10670
|
+
var version = "1.53.2";
|
|
10657
10671
|
var PACKAGE = {
|
|
10658
10672
|
version: version};
|
|
10659
10673
|
|
|
@@ -10837,6 +10851,7 @@ function injectable(source) {
|
|
|
10837
10851
|
let waiter = undefined; // An active, waiting next() call.
|
|
10838
10852
|
// A pending upstream event that couldn't be dispatched because inject() has been called before it was resolved.
|
|
10839
10853
|
let pendingSourceEvent = null;
|
|
10854
|
+
let sourceFetchInFlight = false;
|
|
10840
10855
|
let pendingInjectedEvents = [];
|
|
10841
10856
|
const consumeWaiter = () => {
|
|
10842
10857
|
const pending = waiter;
|
|
@@ -10845,6 +10860,7 @@ function injectable(source) {
|
|
|
10845
10860
|
};
|
|
10846
10861
|
const fetchFromSource = () => {
|
|
10847
10862
|
const resolveWaiter = (propagate) => {
|
|
10863
|
+
sourceFetchInFlight = false;
|
|
10848
10864
|
const active = consumeWaiter();
|
|
10849
10865
|
if (active) {
|
|
10850
10866
|
propagate(active);
|
|
@@ -10853,6 +10869,7 @@ function injectable(source) {
|
|
|
10853
10869
|
pendingSourceEvent = propagate;
|
|
10854
10870
|
}
|
|
10855
10871
|
};
|
|
10872
|
+
sourceFetchInFlight = true;
|
|
10856
10873
|
const nextFromSource = source.next();
|
|
10857
10874
|
nextFromSource.then((value) => {
|
|
10858
10875
|
sourceIsDone = value.done == true;
|
|
@@ -10879,7 +10896,9 @@ function injectable(source) {
|
|
|
10879
10896
|
}
|
|
10880
10897
|
// Nothing pending? Fetch from source
|
|
10881
10898
|
waiter = { resolve, reject };
|
|
10882
|
-
|
|
10899
|
+
if (!sourceFetchInFlight) {
|
|
10900
|
+
fetchFromSource();
|
|
10901
|
+
}
|
|
10883
10902
|
});
|
|
10884
10903
|
},
|
|
10885
10904
|
inject: (event) => {
|
|
@@ -11556,19 +11575,15 @@ const DEFAULT_STREAM_CONNECTION_OPTIONS = {
|
|
|
11556
11575
|
class AbstractStreamingSyncImplementation extends BaseObserver {
|
|
11557
11576
|
options;
|
|
11558
11577
|
abortController;
|
|
11559
|
-
// In rare cases, mostly for tests, uploads can be triggered without being properly connected.
|
|
11560
|
-
// This allows ensuring that all upload processes can be aborted.
|
|
11561
|
-
uploadAbortController;
|
|
11562
11578
|
crudUpdateListener;
|
|
11563
11579
|
streamingSyncPromise;
|
|
11564
11580
|
logger;
|
|
11565
11581
|
activeStreams;
|
|
11566
11582
|
connectionMayHaveChanged = false;
|
|
11567
|
-
|
|
11583
|
+
crudUploadNotifier = asyncNotifier();
|
|
11568
11584
|
notifyCompletedUploads;
|
|
11569
11585
|
handleActiveStreamsChange;
|
|
11570
11586
|
syncStatus;
|
|
11571
|
-
triggerCrudUpload;
|
|
11572
11587
|
constructor(options) {
|
|
11573
11588
|
super();
|
|
11574
11589
|
this.options = options;
|
|
@@ -11584,16 +11599,9 @@ class AbstractStreamingSyncImplementation extends BaseObserver {
|
|
|
11584
11599
|
}
|
|
11585
11600
|
});
|
|
11586
11601
|
this.abortController = null;
|
|
11587
|
-
|
|
11588
|
-
|
|
11589
|
-
|
|
11590
|
-
}
|
|
11591
|
-
this.isUploadingCrud = true;
|
|
11592
|
-
this._uploadAllCrud().finally(() => {
|
|
11593
|
-
this.notifyCompletedUploads?.();
|
|
11594
|
-
this.isUploadingCrud = false;
|
|
11595
|
-
});
|
|
11596
|
-
}, this.options.crudUploadThrottleMs);
|
|
11602
|
+
}
|
|
11603
|
+
triggerCrudUpload() {
|
|
11604
|
+
this.crudUploadNotifier.notify();
|
|
11597
11605
|
}
|
|
11598
11606
|
async waitForReady() { }
|
|
11599
11607
|
waitForStatus(status) {
|
|
@@ -11641,7 +11649,6 @@ class AbstractStreamingSyncImplementation extends BaseObserver {
|
|
|
11641
11649
|
super.dispose();
|
|
11642
11650
|
this.crudUpdateListener?.();
|
|
11643
11651
|
this.crudUpdateListener = undefined;
|
|
11644
|
-
this.uploadAbortController?.abort();
|
|
11645
11652
|
}
|
|
11646
11653
|
async getWriteCheckpoint() {
|
|
11647
11654
|
const clientId = await this.options.adapter.getClientId();
|
|
@@ -11651,7 +11658,17 @@ class AbstractStreamingSyncImplementation extends BaseObserver {
|
|
|
11651
11658
|
this.logger.debug(`Created write checkpoint: ${checkpoint}`);
|
|
11652
11659
|
return checkpoint;
|
|
11653
11660
|
}
|
|
11654
|
-
async
|
|
11661
|
+
async crudUploadLoop(signal) {
|
|
11662
|
+
while (!signal.aborted) {
|
|
11663
|
+
await Promise.all([
|
|
11664
|
+
// Start the initial CRUD upload on connect. Then, keep polling until we're done.
|
|
11665
|
+
this._uploadAllCrud(signal),
|
|
11666
|
+
this.delayRetry(signal, this.options.crudUploadThrottleMs)
|
|
11667
|
+
]);
|
|
11668
|
+
await this.crudUploadNotifier.waitForNotification(signal);
|
|
11669
|
+
}
|
|
11670
|
+
}
|
|
11671
|
+
async _uploadAllCrud(signal) {
|
|
11655
11672
|
return this.obtainLock({
|
|
11656
11673
|
type: LockType.CRUD,
|
|
11657
11674
|
callback: async () => {
|
|
@@ -11659,12 +11676,7 @@ class AbstractStreamingSyncImplementation extends BaseObserver {
|
|
|
11659
11676
|
* Keep track of the first item in the CRUD queue for the last `uploadCrud` iteration.
|
|
11660
11677
|
*/
|
|
11661
11678
|
let checkedCrudItem;
|
|
11662
|
-
|
|
11663
|
-
this.uploadAbortController = controller;
|
|
11664
|
-
this.abortController?.signal.addEventListener('abort', () => {
|
|
11665
|
-
controller.abort();
|
|
11666
|
-
}, { once: true });
|
|
11667
|
-
while (!controller.signal.aborted) {
|
|
11679
|
+
while (!signal.aborted) {
|
|
11668
11680
|
try {
|
|
11669
11681
|
/**
|
|
11670
11682
|
* This is the first item in the FIFO CRUD queue.
|
|
@@ -11694,7 +11706,10 @@ The next upload iteration will be delayed.`);
|
|
|
11694
11706
|
else {
|
|
11695
11707
|
// Uploading is completed
|
|
11696
11708
|
const neededUpdate = await this.options.adapter.updateLocalTarget(() => this.getWriteCheckpoint());
|
|
11697
|
-
if (neededUpdate
|
|
11709
|
+
if (neededUpdate) {
|
|
11710
|
+
this.notifyCompletedUploads?.();
|
|
11711
|
+
}
|
|
11712
|
+
else if (checkedCrudItem != null) {
|
|
11698
11713
|
// Only log this if there was something to upload
|
|
11699
11714
|
this.logger.debug('Upload complete, no write checkpoint needed.');
|
|
11700
11715
|
}
|
|
@@ -11709,7 +11724,7 @@ The next upload iteration will be delayed.`);
|
|
|
11709
11724
|
uploadError: ex
|
|
11710
11725
|
}
|
|
11711
11726
|
});
|
|
11712
|
-
await this.delayRetry(
|
|
11727
|
+
await this.delayRetry(signal);
|
|
11713
11728
|
if (!this.isConnected) {
|
|
11714
11729
|
// Exit the upload loop if the sync stream is no longer connected
|
|
11715
11730
|
break;
|
|
@@ -11724,7 +11739,6 @@ The next upload iteration will be delayed.`);
|
|
|
11724
11739
|
});
|
|
11725
11740
|
}
|
|
11726
11741
|
}
|
|
11727
|
-
this.uploadAbortController = undefined;
|
|
11728
11742
|
}
|
|
11729
11743
|
});
|
|
11730
11744
|
}
|
|
@@ -11734,7 +11748,10 @@ The next upload iteration will be delayed.`);
|
|
|
11734
11748
|
}
|
|
11735
11749
|
const controller = new AbortController();
|
|
11736
11750
|
this.abortController = controller;
|
|
11737
|
-
this.streamingSyncPromise =
|
|
11751
|
+
this.streamingSyncPromise = Promise.all([
|
|
11752
|
+
this.crudUploadLoop(controller.signal).catch((ex) => this.logger.error('Error in crud upload loop', ex)),
|
|
11753
|
+
this.streamingSync(controller.signal, options)
|
|
11754
|
+
]);
|
|
11738
11755
|
// Return a promise that resolves when the connection status is updated to indicate that we're connected.
|
|
11739
11756
|
return new Promise((resolve) => {
|
|
11740
11757
|
const disposer = this.registerListener({
|
|
@@ -11772,14 +11789,7 @@ The next upload iteration will be delayed.`);
|
|
|
11772
11789
|
this.abortController = null;
|
|
11773
11790
|
this.updateSyncStatus({ connected: false, connecting: false });
|
|
11774
11791
|
}
|
|
11775
|
-
/**
|
|
11776
|
-
* @deprecated use [connect instead]
|
|
11777
|
-
*/
|
|
11778
11792
|
async streamingSync(signal, options) {
|
|
11779
|
-
if (!signal) {
|
|
11780
|
-
this.abortController = new AbortController();
|
|
11781
|
-
signal = this.abortController.signal;
|
|
11782
|
-
}
|
|
11783
11793
|
/**
|
|
11784
11794
|
* Listen for CRUD updates and trigger upstream uploads
|
|
11785
11795
|
*/
|
|
@@ -12153,14 +12163,13 @@ The next upload iteration will be delayed.`);
|
|
|
12153
12163
|
// trigger this for all updates
|
|
12154
12164
|
this.iterateListeners((cb) => cb.statusUpdated?.(options));
|
|
12155
12165
|
}
|
|
12156
|
-
async delayRetry(signal) {
|
|
12166
|
+
async delayRetry(signal, delay = this.options.retryDelayMs) {
|
|
12157
12167
|
return new Promise((resolve) => {
|
|
12158
12168
|
if (signal?.aborted) {
|
|
12159
12169
|
// If the signal is already aborted, resolve immediately
|
|
12160
12170
|
resolve();
|
|
12161
12171
|
return;
|
|
12162
12172
|
}
|
|
12163
|
-
const { retryDelayMs } = this.options;
|
|
12164
12173
|
let timeoutId;
|
|
12165
12174
|
const endDelay = () => {
|
|
12166
12175
|
resolve();
|
|
@@ -12171,7 +12180,7 @@ The next upload iteration will be delayed.`);
|
|
|
12171
12180
|
signal?.removeEventListener('abort', endDelay);
|
|
12172
12181
|
};
|
|
12173
12182
|
signal?.addEventListener('abort', endDelay, { once: true });
|
|
12174
|
-
timeoutId = setTimeout(endDelay,
|
|
12183
|
+
timeoutId = setTimeout(endDelay, delay);
|
|
12175
12184
|
});
|
|
12176
12185
|
}
|
|
12177
12186
|
updateSubscriptions(subscriptions) {
|