@powersync/web 1.37.0 → 1.37.1
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 +128 -37
- package/dist/worker/SharedSyncImplementation.umd.js.map +1 -1
- package/dist/worker/WASQLiteDB.umd.js +128 -37
- 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
|
@@ -2871,6 +2871,7 @@ __webpack_require__.r(__webpack_exports__);
|
|
|
2871
2871
|
/* harmony export */ PowerSyncControlCommand: () => (/* binding */ PowerSyncControlCommand),
|
|
2872
2872
|
/* harmony export */ RowUpdateType: () => (/* binding */ RowUpdateType),
|
|
2873
2873
|
/* harmony export */ Schema: () => (/* binding */ Schema),
|
|
2874
|
+
/* harmony export */ Semaphore: () => (/* binding */ Semaphore),
|
|
2874
2875
|
/* harmony export */ SqliteBucketStorage: () => (/* binding */ SqliteBucketStorage),
|
|
2875
2876
|
/* harmony export */ SyncClientImplementation: () => (/* binding */ SyncClientImplementation),
|
|
2876
2877
|
/* harmony export */ SyncDataBatch: () => (/* binding */ SyncDataBatch),
|
|
@@ -3692,19 +3693,69 @@ class SyncingService {
|
|
|
3692
3693
|
}
|
|
3693
3694
|
|
|
3694
3695
|
/**
|
|
3695
|
-
*
|
|
3696
|
+
* A simple fixed-capacity queue implementation.
|
|
3697
|
+
*
|
|
3698
|
+
* Unlike a naive queue implemented by `array.push()` and `array.shift()`, this avoids moving array elements around
|
|
3699
|
+
* and is `O(1)` for {@link addLast} and {@link removeFirst}.
|
|
3700
|
+
*/
|
|
3701
|
+
class Queue {
|
|
3702
|
+
table;
|
|
3703
|
+
// Index of the first element in the table.
|
|
3704
|
+
head;
|
|
3705
|
+
// Amount of items currently in the queue.
|
|
3706
|
+
_length;
|
|
3707
|
+
constructor(initialItems) {
|
|
3708
|
+
this.table = [...initialItems];
|
|
3709
|
+
this.head = 0;
|
|
3710
|
+
this._length = this.table.length;
|
|
3711
|
+
}
|
|
3712
|
+
get isEmpty() {
|
|
3713
|
+
return this.length == 0;
|
|
3714
|
+
}
|
|
3715
|
+
get length() {
|
|
3716
|
+
return this._length;
|
|
3717
|
+
}
|
|
3718
|
+
removeFirst() {
|
|
3719
|
+
if (this.isEmpty) {
|
|
3720
|
+
throw new Error('Queue is empty');
|
|
3721
|
+
}
|
|
3722
|
+
const result = this.table[this.head];
|
|
3723
|
+
this._length--;
|
|
3724
|
+
this.table[this.head] = undefined;
|
|
3725
|
+
this.head = (this.head + 1) % this.table.length;
|
|
3726
|
+
return result;
|
|
3727
|
+
}
|
|
3728
|
+
addLast(element) {
|
|
3729
|
+
if (this.length == this.table.length) {
|
|
3730
|
+
throw new Error('Queue is full');
|
|
3731
|
+
}
|
|
3732
|
+
this.table[(this.head + this._length) % this.table.length] = element;
|
|
3733
|
+
this._length++;
|
|
3734
|
+
}
|
|
3735
|
+
}
|
|
3736
|
+
|
|
3737
|
+
/**
|
|
3738
|
+
* An asynchronous semaphore implementation with associated items per lease.
|
|
3696
3739
|
*
|
|
3697
3740
|
* @internal This class is meant to be used in PowerSync SDKs only, and is not part of the public API.
|
|
3698
3741
|
*/
|
|
3699
|
-
class
|
|
3700
|
-
|
|
3742
|
+
class Semaphore {
|
|
3743
|
+
// Available items that are not currently assigned to a waiter.
|
|
3744
|
+
available;
|
|
3745
|
+
size;
|
|
3701
3746
|
// Linked list of waiters. We don't expect the wait list to become particularly large, and this allows removing
|
|
3702
3747
|
// aborted waiters from the middle of the list efficiently.
|
|
3703
3748
|
firstWaiter;
|
|
3704
3749
|
lastWaiter;
|
|
3705
|
-
|
|
3750
|
+
constructor(elements) {
|
|
3751
|
+
this.available = new Queue(elements);
|
|
3752
|
+
this.size = this.available.length;
|
|
3753
|
+
}
|
|
3754
|
+
addWaiter(requestedItems, onAcquire) {
|
|
3706
3755
|
const node = {
|
|
3707
3756
|
isActive: true,
|
|
3757
|
+
acquiredItems: [],
|
|
3758
|
+
remainingItems: requestedItems,
|
|
3708
3759
|
onAcquire,
|
|
3709
3760
|
prev: this.lastWaiter
|
|
3710
3761
|
};
|
|
@@ -3730,52 +3781,92 @@ class Mutex {
|
|
|
3730
3781
|
if (waiter == this.lastWaiter)
|
|
3731
3782
|
this.lastWaiter = prev;
|
|
3732
3783
|
}
|
|
3733
|
-
|
|
3784
|
+
requestPermits(amount, abort) {
|
|
3785
|
+
if (amount <= 0 || amount > this.size) {
|
|
3786
|
+
throw new Error(`Invalid amount of items requested (${amount}), must be between 1 and ${this.size}`);
|
|
3787
|
+
}
|
|
3734
3788
|
return new Promise((resolve, reject) => {
|
|
3735
3789
|
function rejectAborted() {
|
|
3736
|
-
reject(abort?.reason ?? new Error('
|
|
3790
|
+
reject(abort?.reason ?? new Error('Semaphore acquire aborted'));
|
|
3737
3791
|
}
|
|
3738
3792
|
if (abort?.aborted) {
|
|
3739
3793
|
return rejectAborted();
|
|
3740
3794
|
}
|
|
3741
|
-
let
|
|
3795
|
+
let waiter;
|
|
3742
3796
|
const markCompleted = () => {
|
|
3743
|
-
|
|
3744
|
-
|
|
3745
|
-
|
|
3746
|
-
|
|
3747
|
-
|
|
3748
|
-
|
|
3749
|
-
|
|
3750
|
-
|
|
3797
|
+
const items = waiter.acquiredItems;
|
|
3798
|
+
waiter.acquiredItems = []; // Avoid releasing items twice.
|
|
3799
|
+
for (const element of items) {
|
|
3800
|
+
// Give to next waiter, if possible.
|
|
3801
|
+
const nextWaiter = this.firstWaiter;
|
|
3802
|
+
if (nextWaiter) {
|
|
3803
|
+
nextWaiter.acquiredItems.push(element);
|
|
3804
|
+
nextWaiter.remainingItems--;
|
|
3805
|
+
if (nextWaiter.remainingItems == 0) {
|
|
3806
|
+
nextWaiter.onAcquire();
|
|
3807
|
+
}
|
|
3808
|
+
}
|
|
3809
|
+
else {
|
|
3810
|
+
// No pending waiter, return lease into pool.
|
|
3811
|
+
this.available.addLast(element);
|
|
3812
|
+
}
|
|
3751
3813
|
}
|
|
3752
|
-
|
|
3753
|
-
|
|
3814
|
+
};
|
|
3815
|
+
const onAbort = () => {
|
|
3816
|
+
abort?.removeEventListener('abort', onAbort);
|
|
3817
|
+
if (waiter.isActive) {
|
|
3818
|
+
this.deactivateWaiter(waiter);
|
|
3819
|
+
rejectAborted();
|
|
3754
3820
|
}
|
|
3755
3821
|
};
|
|
3756
|
-
|
|
3757
|
-
this.
|
|
3758
|
-
|
|
3759
|
-
|
|
3822
|
+
const resolvePromise = () => {
|
|
3823
|
+
this.deactivateWaiter(waiter);
|
|
3824
|
+
abort?.removeEventListener('abort', onAbort);
|
|
3825
|
+
const items = waiter.acquiredItems;
|
|
3826
|
+
resolve({ items, release: markCompleted });
|
|
3827
|
+
};
|
|
3828
|
+
waiter = this.addWaiter(amount, resolvePromise);
|
|
3829
|
+
// If there are items in the pool that haven't been assigned, we can pull them into this waiter. Note that this is
|
|
3830
|
+
// only the case if we're the first waiter (otherwise, items would have been assigned to an earlier waiter).
|
|
3831
|
+
while (!this.available.isEmpty && waiter.remainingItems > 0) {
|
|
3832
|
+
waiter.acquiredItems.push(this.available.removeFirst());
|
|
3833
|
+
waiter.remainingItems--;
|
|
3760
3834
|
}
|
|
3761
|
-
|
|
3762
|
-
|
|
3763
|
-
const onAbort = () => {
|
|
3764
|
-
abort?.removeEventListener('abort', onAbort);
|
|
3765
|
-
if (node.isActive) {
|
|
3766
|
-
this.deactivateWaiter(node);
|
|
3767
|
-
rejectAborted();
|
|
3768
|
-
}
|
|
3769
|
-
};
|
|
3770
|
-
node = this.addWaiter(() => {
|
|
3771
|
-
abort?.removeEventListener('abort', onAbort);
|
|
3772
|
-
holdsMutex = true;
|
|
3773
|
-
resolve(markCompleted);
|
|
3774
|
-
});
|
|
3775
|
-
abort?.addEventListener('abort', onAbort);
|
|
3835
|
+
if (waiter.remainingItems == 0) {
|
|
3836
|
+
return resolvePromise();
|
|
3776
3837
|
}
|
|
3838
|
+
abort?.addEventListener('abort', onAbort);
|
|
3777
3839
|
});
|
|
3778
3840
|
}
|
|
3841
|
+
/**
|
|
3842
|
+
* Requests a single item from the pool.
|
|
3843
|
+
*
|
|
3844
|
+
* The returned `release` callback must be invoked to return the item into the pool.
|
|
3845
|
+
*/
|
|
3846
|
+
async requestOne(abort) {
|
|
3847
|
+
const { items, release } = await this.requestPermits(1, abort);
|
|
3848
|
+
return { release, item: items[0] };
|
|
3849
|
+
}
|
|
3850
|
+
/**
|
|
3851
|
+
* Requests access to all items from the pool.
|
|
3852
|
+
*
|
|
3853
|
+
* The returned `release` callback must be invoked to return items into the pool.
|
|
3854
|
+
*/
|
|
3855
|
+
requestAll(abort) {
|
|
3856
|
+
return this.requestPermits(this.size, abort);
|
|
3857
|
+
}
|
|
3858
|
+
}
|
|
3859
|
+
/**
|
|
3860
|
+
* An asynchronous mutex implementation.
|
|
3861
|
+
*
|
|
3862
|
+
* @internal This class is meant to be used in PowerSync SDKs only, and is not part of the public API.
|
|
3863
|
+
*/
|
|
3864
|
+
class Mutex {
|
|
3865
|
+
inner = new Semaphore([null]);
|
|
3866
|
+
async acquire(abort) {
|
|
3867
|
+
const { release } = await this.inner.requestOne(abort);
|
|
3868
|
+
return release;
|
|
3869
|
+
}
|
|
3779
3870
|
async runExclusive(fn, abort) {
|
|
3780
3871
|
const returnMutex = await this.acquire(abort);
|
|
3781
3872
|
try {
|
|
@@ -13572,7 +13663,7 @@ function requireDist () {
|
|
|
13572
13663
|
|
|
13573
13664
|
var distExports = requireDist();
|
|
13574
13665
|
|
|
13575
|
-
var version = "1.
|
|
13666
|
+
var version = "1.51.0";
|
|
13576
13667
|
var PACKAGE = {
|
|
13577
13668
|
version: version};
|
|
13578
13669
|
|