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