@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
|
@@ -1735,6 +1735,7 @@ __webpack_require__.r(__webpack_exports__);
|
|
|
1735
1735
|
/* harmony export */ PowerSyncControlCommand: () => (/* binding */ PowerSyncControlCommand),
|
|
1736
1736
|
/* harmony export */ RowUpdateType: () => (/* binding */ RowUpdateType),
|
|
1737
1737
|
/* harmony export */ Schema: () => (/* binding */ Schema),
|
|
1738
|
+
/* harmony export */ Semaphore: () => (/* binding */ Semaphore),
|
|
1738
1739
|
/* harmony export */ SqliteBucketStorage: () => (/* binding */ SqliteBucketStorage),
|
|
1739
1740
|
/* harmony export */ SyncClientImplementation: () => (/* binding */ SyncClientImplementation),
|
|
1740
1741
|
/* harmony export */ SyncDataBatch: () => (/* binding */ SyncDataBatch),
|
|
@@ -2556,19 +2557,69 @@ class SyncingService {
|
|
|
2556
2557
|
}
|
|
2557
2558
|
|
|
2558
2559
|
/**
|
|
2559
|
-
*
|
|
2560
|
+
* A simple fixed-capacity queue implementation.
|
|
2561
|
+
*
|
|
2562
|
+
* Unlike a naive queue implemented by `array.push()` and `array.shift()`, this avoids moving array elements around
|
|
2563
|
+
* and is `O(1)` for {@link addLast} and {@link removeFirst}.
|
|
2564
|
+
*/
|
|
2565
|
+
class Queue {
|
|
2566
|
+
table;
|
|
2567
|
+
// Index of the first element in the table.
|
|
2568
|
+
head;
|
|
2569
|
+
// Amount of items currently in the queue.
|
|
2570
|
+
_length;
|
|
2571
|
+
constructor(initialItems) {
|
|
2572
|
+
this.table = [...initialItems];
|
|
2573
|
+
this.head = 0;
|
|
2574
|
+
this._length = this.table.length;
|
|
2575
|
+
}
|
|
2576
|
+
get isEmpty() {
|
|
2577
|
+
return this.length == 0;
|
|
2578
|
+
}
|
|
2579
|
+
get length() {
|
|
2580
|
+
return this._length;
|
|
2581
|
+
}
|
|
2582
|
+
removeFirst() {
|
|
2583
|
+
if (this.isEmpty) {
|
|
2584
|
+
throw new Error('Queue is empty');
|
|
2585
|
+
}
|
|
2586
|
+
const result = this.table[this.head];
|
|
2587
|
+
this._length--;
|
|
2588
|
+
this.table[this.head] = undefined;
|
|
2589
|
+
this.head = (this.head + 1) % this.table.length;
|
|
2590
|
+
return result;
|
|
2591
|
+
}
|
|
2592
|
+
addLast(element) {
|
|
2593
|
+
if (this.length == this.table.length) {
|
|
2594
|
+
throw new Error('Queue is full');
|
|
2595
|
+
}
|
|
2596
|
+
this.table[(this.head + this._length) % this.table.length] = element;
|
|
2597
|
+
this._length++;
|
|
2598
|
+
}
|
|
2599
|
+
}
|
|
2600
|
+
|
|
2601
|
+
/**
|
|
2602
|
+
* An asynchronous semaphore implementation with associated items per lease.
|
|
2560
2603
|
*
|
|
2561
2604
|
* @internal This class is meant to be used in PowerSync SDKs only, and is not part of the public API.
|
|
2562
2605
|
*/
|
|
2563
|
-
class
|
|
2564
|
-
|
|
2606
|
+
class Semaphore {
|
|
2607
|
+
// Available items that are not currently assigned to a waiter.
|
|
2608
|
+
available;
|
|
2609
|
+
size;
|
|
2565
2610
|
// Linked list of waiters. We don't expect the wait list to become particularly large, and this allows removing
|
|
2566
2611
|
// aborted waiters from the middle of the list efficiently.
|
|
2567
2612
|
firstWaiter;
|
|
2568
2613
|
lastWaiter;
|
|
2569
|
-
|
|
2614
|
+
constructor(elements) {
|
|
2615
|
+
this.available = new Queue(elements);
|
|
2616
|
+
this.size = this.available.length;
|
|
2617
|
+
}
|
|
2618
|
+
addWaiter(requestedItems, onAcquire) {
|
|
2570
2619
|
const node = {
|
|
2571
2620
|
isActive: true,
|
|
2621
|
+
acquiredItems: [],
|
|
2622
|
+
remainingItems: requestedItems,
|
|
2572
2623
|
onAcquire,
|
|
2573
2624
|
prev: this.lastWaiter
|
|
2574
2625
|
};
|
|
@@ -2594,52 +2645,92 @@ class Mutex {
|
|
|
2594
2645
|
if (waiter == this.lastWaiter)
|
|
2595
2646
|
this.lastWaiter = prev;
|
|
2596
2647
|
}
|
|
2597
|
-
|
|
2648
|
+
requestPermits(amount, abort) {
|
|
2649
|
+
if (amount <= 0 || amount > this.size) {
|
|
2650
|
+
throw new Error(`Invalid amount of items requested (${amount}), must be between 1 and ${this.size}`);
|
|
2651
|
+
}
|
|
2598
2652
|
return new Promise((resolve, reject) => {
|
|
2599
2653
|
function rejectAborted() {
|
|
2600
|
-
reject(abort?.reason ?? new Error('
|
|
2654
|
+
reject(abort?.reason ?? new Error('Semaphore acquire aborted'));
|
|
2601
2655
|
}
|
|
2602
2656
|
if (abort?.aborted) {
|
|
2603
2657
|
return rejectAborted();
|
|
2604
2658
|
}
|
|
2605
|
-
let
|
|
2659
|
+
let waiter;
|
|
2606
2660
|
const markCompleted = () => {
|
|
2607
|
-
|
|
2608
|
-
|
|
2609
|
-
|
|
2610
|
-
|
|
2611
|
-
|
|
2612
|
-
|
|
2613
|
-
|
|
2614
|
-
|
|
2661
|
+
const items = waiter.acquiredItems;
|
|
2662
|
+
waiter.acquiredItems = []; // Avoid releasing items twice.
|
|
2663
|
+
for (const element of items) {
|
|
2664
|
+
// Give to next waiter, if possible.
|
|
2665
|
+
const nextWaiter = this.firstWaiter;
|
|
2666
|
+
if (nextWaiter) {
|
|
2667
|
+
nextWaiter.acquiredItems.push(element);
|
|
2668
|
+
nextWaiter.remainingItems--;
|
|
2669
|
+
if (nextWaiter.remainingItems == 0) {
|
|
2670
|
+
nextWaiter.onAcquire();
|
|
2671
|
+
}
|
|
2672
|
+
}
|
|
2673
|
+
else {
|
|
2674
|
+
// No pending waiter, return lease into pool.
|
|
2675
|
+
this.available.addLast(element);
|
|
2676
|
+
}
|
|
2615
2677
|
}
|
|
2616
|
-
|
|
2617
|
-
|
|
2678
|
+
};
|
|
2679
|
+
const onAbort = () => {
|
|
2680
|
+
abort?.removeEventListener('abort', onAbort);
|
|
2681
|
+
if (waiter.isActive) {
|
|
2682
|
+
this.deactivateWaiter(waiter);
|
|
2683
|
+
rejectAborted();
|
|
2618
2684
|
}
|
|
2619
2685
|
};
|
|
2620
|
-
|
|
2621
|
-
this.
|
|
2622
|
-
|
|
2623
|
-
|
|
2686
|
+
const resolvePromise = () => {
|
|
2687
|
+
this.deactivateWaiter(waiter);
|
|
2688
|
+
abort?.removeEventListener('abort', onAbort);
|
|
2689
|
+
const items = waiter.acquiredItems;
|
|
2690
|
+
resolve({ items, release: markCompleted });
|
|
2691
|
+
};
|
|
2692
|
+
waiter = this.addWaiter(amount, resolvePromise);
|
|
2693
|
+
// If there are items in the pool that haven't been assigned, we can pull them into this waiter. Note that this is
|
|
2694
|
+
// only the case if we're the first waiter (otherwise, items would have been assigned to an earlier waiter).
|
|
2695
|
+
while (!this.available.isEmpty && waiter.remainingItems > 0) {
|
|
2696
|
+
waiter.acquiredItems.push(this.available.removeFirst());
|
|
2697
|
+
waiter.remainingItems--;
|
|
2624
2698
|
}
|
|
2625
|
-
|
|
2626
|
-
|
|
2627
|
-
const onAbort = () => {
|
|
2628
|
-
abort?.removeEventListener('abort', onAbort);
|
|
2629
|
-
if (node.isActive) {
|
|
2630
|
-
this.deactivateWaiter(node);
|
|
2631
|
-
rejectAborted();
|
|
2632
|
-
}
|
|
2633
|
-
};
|
|
2634
|
-
node = this.addWaiter(() => {
|
|
2635
|
-
abort?.removeEventListener('abort', onAbort);
|
|
2636
|
-
holdsMutex = true;
|
|
2637
|
-
resolve(markCompleted);
|
|
2638
|
-
});
|
|
2639
|
-
abort?.addEventListener('abort', onAbort);
|
|
2699
|
+
if (waiter.remainingItems == 0) {
|
|
2700
|
+
return resolvePromise();
|
|
2640
2701
|
}
|
|
2702
|
+
abort?.addEventListener('abort', onAbort);
|
|
2641
2703
|
});
|
|
2642
2704
|
}
|
|
2705
|
+
/**
|
|
2706
|
+
* Requests a single item from the pool.
|
|
2707
|
+
*
|
|
2708
|
+
* The returned `release` callback must be invoked to return the item into the pool.
|
|
2709
|
+
*/
|
|
2710
|
+
async requestOne(abort) {
|
|
2711
|
+
const { items, release } = await this.requestPermits(1, abort);
|
|
2712
|
+
return { release, item: items[0] };
|
|
2713
|
+
}
|
|
2714
|
+
/**
|
|
2715
|
+
* Requests access to all items from the pool.
|
|
2716
|
+
*
|
|
2717
|
+
* The returned `release` callback must be invoked to return items into the pool.
|
|
2718
|
+
*/
|
|
2719
|
+
requestAll(abort) {
|
|
2720
|
+
return this.requestPermits(this.size, abort);
|
|
2721
|
+
}
|
|
2722
|
+
}
|
|
2723
|
+
/**
|
|
2724
|
+
* An asynchronous mutex implementation.
|
|
2725
|
+
*
|
|
2726
|
+
* @internal This class is meant to be used in PowerSync SDKs only, and is not part of the public API.
|
|
2727
|
+
*/
|
|
2728
|
+
class Mutex {
|
|
2729
|
+
inner = new Semaphore([null]);
|
|
2730
|
+
async acquire(abort) {
|
|
2731
|
+
const { release } = await this.inner.requestOne(abort);
|
|
2732
|
+
return release;
|
|
2733
|
+
}
|
|
2643
2734
|
async runExclusive(fn, abort) {
|
|
2644
2735
|
const returnMutex = await this.acquire(abort);
|
|
2645
2736
|
try {
|
|
@@ -12436,7 +12527,7 @@ function requireDist () {
|
|
|
12436
12527
|
|
|
12437
12528
|
var distExports = requireDist();
|
|
12438
12529
|
|
|
12439
|
-
var version = "1.
|
|
12530
|
+
var version = "1.51.0";
|
|
12440
12531
|
var PACKAGE = {
|
|
12441
12532
|
version: version};
|
|
12442
12533
|
|