@powersync/common 1.50.0 → 1.51.0
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 +128 -37
- package/dist/bundle.cjs.map +1 -1
- package/dist/bundle.mjs +128 -38
- package/dist/bundle.mjs.map +1 -1
- package/dist/bundle.node.cjs +128 -37
- package/dist/bundle.node.cjs.map +1 -1
- package/dist/bundle.node.mjs +128 -38
- package/dist/bundle.node.mjs.map +1 -1
- package/dist/index.d.cts +33 -4
- package/lib/utils/mutex.d.ts +32 -3
- package/lib/utils/mutex.js +85 -36
- package/lib/utils/mutex.js.map +1 -1
- package/lib/utils/queue.d.ts +16 -0
- package/lib/utils/queue.js +42 -0
- package/lib/utils/queue.js.map +1 -0
- package/package.json +1 -1
- package/src/utils/mutex.ts +111 -48
- package/src/utils/queue.ts +48 -0
package/dist/bundle.mjs
CHANGED
|
@@ -780,19 +780,69 @@ class SyncingService {
|
|
|
780
780
|
}
|
|
781
781
|
|
|
782
782
|
/**
|
|
783
|
-
*
|
|
783
|
+
* A simple fixed-capacity queue implementation.
|
|
784
|
+
*
|
|
785
|
+
* Unlike a naive queue implemented by `array.push()` and `array.shift()`, this avoids moving array elements around
|
|
786
|
+
* and is `O(1)` for {@link addLast} and {@link removeFirst}.
|
|
787
|
+
*/
|
|
788
|
+
class Queue {
|
|
789
|
+
table;
|
|
790
|
+
// Index of the first element in the table.
|
|
791
|
+
head;
|
|
792
|
+
// Amount of items currently in the queue.
|
|
793
|
+
_length;
|
|
794
|
+
constructor(initialItems) {
|
|
795
|
+
this.table = [...initialItems];
|
|
796
|
+
this.head = 0;
|
|
797
|
+
this._length = this.table.length;
|
|
798
|
+
}
|
|
799
|
+
get isEmpty() {
|
|
800
|
+
return this.length == 0;
|
|
801
|
+
}
|
|
802
|
+
get length() {
|
|
803
|
+
return this._length;
|
|
804
|
+
}
|
|
805
|
+
removeFirst() {
|
|
806
|
+
if (this.isEmpty) {
|
|
807
|
+
throw new Error('Queue is empty');
|
|
808
|
+
}
|
|
809
|
+
const result = this.table[this.head];
|
|
810
|
+
this._length--;
|
|
811
|
+
this.table[this.head] = undefined;
|
|
812
|
+
this.head = (this.head + 1) % this.table.length;
|
|
813
|
+
return result;
|
|
814
|
+
}
|
|
815
|
+
addLast(element) {
|
|
816
|
+
if (this.length == this.table.length) {
|
|
817
|
+
throw new Error('Queue is full');
|
|
818
|
+
}
|
|
819
|
+
this.table[(this.head + this._length) % this.table.length] = element;
|
|
820
|
+
this._length++;
|
|
821
|
+
}
|
|
822
|
+
}
|
|
823
|
+
|
|
824
|
+
/**
|
|
825
|
+
* An asynchronous semaphore implementation with associated items per lease.
|
|
784
826
|
*
|
|
785
827
|
* @internal This class is meant to be used in PowerSync SDKs only, and is not part of the public API.
|
|
786
828
|
*/
|
|
787
|
-
class
|
|
788
|
-
|
|
829
|
+
class Semaphore {
|
|
830
|
+
// Available items that are not currently assigned to a waiter.
|
|
831
|
+
available;
|
|
832
|
+
size;
|
|
789
833
|
// Linked list of waiters. We don't expect the wait list to become particularly large, and this allows removing
|
|
790
834
|
// aborted waiters from the middle of the list efficiently.
|
|
791
835
|
firstWaiter;
|
|
792
836
|
lastWaiter;
|
|
793
|
-
|
|
837
|
+
constructor(elements) {
|
|
838
|
+
this.available = new Queue(elements);
|
|
839
|
+
this.size = this.available.length;
|
|
840
|
+
}
|
|
841
|
+
addWaiter(requestedItems, onAcquire) {
|
|
794
842
|
const node = {
|
|
795
843
|
isActive: true,
|
|
844
|
+
acquiredItems: [],
|
|
845
|
+
remainingItems: requestedItems,
|
|
796
846
|
onAcquire,
|
|
797
847
|
prev: this.lastWaiter
|
|
798
848
|
};
|
|
@@ -818,52 +868,92 @@ class Mutex {
|
|
|
818
868
|
if (waiter == this.lastWaiter)
|
|
819
869
|
this.lastWaiter = prev;
|
|
820
870
|
}
|
|
821
|
-
|
|
871
|
+
requestPermits(amount, abort) {
|
|
872
|
+
if (amount <= 0 || amount > this.size) {
|
|
873
|
+
throw new Error(`Invalid amount of items requested (${amount}), must be between 1 and ${this.size}`);
|
|
874
|
+
}
|
|
822
875
|
return new Promise((resolve, reject) => {
|
|
823
876
|
function rejectAborted() {
|
|
824
|
-
reject(abort?.reason ?? new Error('
|
|
877
|
+
reject(abort?.reason ?? new Error('Semaphore acquire aborted'));
|
|
825
878
|
}
|
|
826
879
|
if (abort?.aborted) {
|
|
827
880
|
return rejectAborted();
|
|
828
881
|
}
|
|
829
|
-
let
|
|
882
|
+
let waiter;
|
|
830
883
|
const markCompleted = () => {
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
884
|
+
const items = waiter.acquiredItems;
|
|
885
|
+
waiter.acquiredItems = []; // Avoid releasing items twice.
|
|
886
|
+
for (const element of items) {
|
|
887
|
+
// Give to next waiter, if possible.
|
|
888
|
+
const nextWaiter = this.firstWaiter;
|
|
889
|
+
if (nextWaiter) {
|
|
890
|
+
nextWaiter.acquiredItems.push(element);
|
|
891
|
+
nextWaiter.remainingItems--;
|
|
892
|
+
if (nextWaiter.remainingItems == 0) {
|
|
893
|
+
nextWaiter.onAcquire();
|
|
894
|
+
}
|
|
895
|
+
}
|
|
896
|
+
else {
|
|
897
|
+
// No pending waiter, return lease into pool.
|
|
898
|
+
this.available.addLast(element);
|
|
899
|
+
}
|
|
839
900
|
}
|
|
840
|
-
|
|
841
|
-
|
|
901
|
+
};
|
|
902
|
+
const onAbort = () => {
|
|
903
|
+
abort?.removeEventListener('abort', onAbort);
|
|
904
|
+
if (waiter.isActive) {
|
|
905
|
+
this.deactivateWaiter(waiter);
|
|
906
|
+
rejectAborted();
|
|
842
907
|
}
|
|
843
908
|
};
|
|
844
|
-
|
|
845
|
-
this.
|
|
846
|
-
|
|
847
|
-
|
|
909
|
+
const resolvePromise = () => {
|
|
910
|
+
this.deactivateWaiter(waiter);
|
|
911
|
+
abort?.removeEventListener('abort', onAbort);
|
|
912
|
+
const items = waiter.acquiredItems;
|
|
913
|
+
resolve({ items, release: markCompleted });
|
|
914
|
+
};
|
|
915
|
+
waiter = this.addWaiter(amount, resolvePromise);
|
|
916
|
+
// If there are items in the pool that haven't been assigned, we can pull them into this waiter. Note that this is
|
|
917
|
+
// only the case if we're the first waiter (otherwise, items would have been assigned to an earlier waiter).
|
|
918
|
+
while (!this.available.isEmpty && waiter.remainingItems > 0) {
|
|
919
|
+
waiter.acquiredItems.push(this.available.removeFirst());
|
|
920
|
+
waiter.remainingItems--;
|
|
848
921
|
}
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
const onAbort = () => {
|
|
852
|
-
abort?.removeEventListener('abort', onAbort);
|
|
853
|
-
if (node.isActive) {
|
|
854
|
-
this.deactivateWaiter(node);
|
|
855
|
-
rejectAborted();
|
|
856
|
-
}
|
|
857
|
-
};
|
|
858
|
-
node = this.addWaiter(() => {
|
|
859
|
-
abort?.removeEventListener('abort', onAbort);
|
|
860
|
-
holdsMutex = true;
|
|
861
|
-
resolve(markCompleted);
|
|
862
|
-
});
|
|
863
|
-
abort?.addEventListener('abort', onAbort);
|
|
922
|
+
if (waiter.remainingItems == 0) {
|
|
923
|
+
return resolvePromise();
|
|
864
924
|
}
|
|
925
|
+
abort?.addEventListener('abort', onAbort);
|
|
865
926
|
});
|
|
866
927
|
}
|
|
928
|
+
/**
|
|
929
|
+
* Requests a single item from the pool.
|
|
930
|
+
*
|
|
931
|
+
* The returned `release` callback must be invoked to return the item into the pool.
|
|
932
|
+
*/
|
|
933
|
+
async requestOne(abort) {
|
|
934
|
+
const { items, release } = await this.requestPermits(1, abort);
|
|
935
|
+
return { release, item: items[0] };
|
|
936
|
+
}
|
|
937
|
+
/**
|
|
938
|
+
* Requests access to all items from the pool.
|
|
939
|
+
*
|
|
940
|
+
* The returned `release` callback must be invoked to return items into the pool.
|
|
941
|
+
*/
|
|
942
|
+
requestAll(abort) {
|
|
943
|
+
return this.requestPermits(this.size, abort);
|
|
944
|
+
}
|
|
945
|
+
}
|
|
946
|
+
/**
|
|
947
|
+
* An asynchronous mutex implementation.
|
|
948
|
+
*
|
|
949
|
+
* @internal This class is meant to be used in PowerSync SDKs only, and is not part of the public API.
|
|
950
|
+
*/
|
|
951
|
+
class Mutex {
|
|
952
|
+
inner = new Semaphore([null]);
|
|
953
|
+
async acquire(abort) {
|
|
954
|
+
const { release } = await this.inner.requestOne(abort);
|
|
955
|
+
return release;
|
|
956
|
+
}
|
|
867
957
|
async runExclusive(fn, abort) {
|
|
868
958
|
const returnMutex = await this.acquire(abort);
|
|
869
959
|
try {
|
|
@@ -10660,7 +10750,7 @@ function requireDist () {
|
|
|
10660
10750
|
|
|
10661
10751
|
var distExports = requireDist();
|
|
10662
10752
|
|
|
10663
|
-
var version = "1.
|
|
10753
|
+
var version = "1.51.0";
|
|
10664
10754
|
var PACKAGE = {
|
|
10665
10755
|
version: version};
|
|
10666
10756
|
|
|
@@ -14594,5 +14684,5 @@ const parseQuery = (query, parameters) => {
|
|
|
14594
14684
|
return { sqlStatement, parameters: parameters };
|
|
14595
14685
|
};
|
|
14596
14686
|
|
|
14597
|
-
export { ATTACHMENT_TABLE, AbortOperation, AbstractPowerSyncDatabase, AbstractPowerSyncDatabaseOpenFactory, AbstractQueryProcessor, AbstractRemote, AbstractStreamingSyncImplementation, ArrayComparator, AttachmentContext, AttachmentQueue, AttachmentService, AttachmentState, AttachmentTable, BaseObserver, Column, ColumnType, ConnectionClosedError, ConnectionManager, ControlledExecutor, CrudBatch, CrudEntry, CrudTransaction, DBAdapterDefaultMixin, DBGetUtilsDefaultMixin, DEFAULT_CRUD_BATCH_LIMIT, DEFAULT_CRUD_UPLOAD_THROTTLE_MS, DEFAULT_INDEX_COLUMN_OPTIONS, DEFAULT_INDEX_OPTIONS, DEFAULT_LOCK_TIMEOUT_MS, DEFAULT_POWERSYNC_CLOSE_OPTIONS, DEFAULT_POWERSYNC_DB_OPTIONS, DEFAULT_PRESSURE_LIMITS, DEFAULT_REMOTE_LOGGER, DEFAULT_REMOTE_OPTIONS, DEFAULT_RETRY_DELAY_MS, DEFAULT_ROW_COMPARATOR, DEFAULT_STREAMING_SYNC_OPTIONS, DEFAULT_STREAM_CONNECTION_OPTIONS, DEFAULT_SYNC_CLIENT_IMPLEMENTATION, DEFAULT_TABLE_OPTIONS, DEFAULT_WATCH_QUERY_OPTIONS, DEFAULT_WATCH_THROTTLE_MS, DataStream, DiffTriggerOperation, DifferentialQueryProcessor, EMPTY_DIFFERENTIAL, EncodingType, FalsyComparator, FetchImplementationProvider, FetchStrategy, GetAllQuery, Index, IndexedColumn, InvalidSQLCharacters, LockType, LogLevel, MAX_AMOUNT_OF_COLUMNS, MAX_OP_ID, MEMORY_TRIGGER_CLAIM_MANAGER, Mutex, OnChangeQueryProcessor, OpType, OpTypeEnum, OplogEntry, PSInternalTable, PowerSyncControlCommand, RowUpdateType, Schema, SqliteBucketStorage, SyncClientImplementation, SyncDataBatch, SyncDataBucket, SyncProgress, SyncStatus, SyncStreamConnectionMethod, SyncingService, Table, TableV2, TriggerManagerImpl, UpdateType, UploadQueueStats, WatchedQueryListenerEvent, attachmentFromSql, column, compilableQueryWatch, createBaseLogger, createLogger, extractTableUpdates, isBatchedUpdateNotification, isContinueCheckpointRequest, isDBAdapter, isPowerSyncDatabaseOptionsWithSettings, isSQLOpenFactory, isSQLOpenOptions, isStreamingKeepalive, isStreamingSyncCheckpoint, isStreamingSyncCheckpointComplete, isStreamingSyncCheckpointDiff, isStreamingSyncCheckpointPartiallyComplete, isStreamingSyncData, isSyncNewCheckpointRequest, parseQuery, runOnSchemaChange, sanitizeSQL, sanitizeUUID, timeoutSignal };
|
|
14687
|
+
export { ATTACHMENT_TABLE, AbortOperation, AbstractPowerSyncDatabase, AbstractPowerSyncDatabaseOpenFactory, AbstractQueryProcessor, AbstractRemote, AbstractStreamingSyncImplementation, ArrayComparator, AttachmentContext, AttachmentQueue, AttachmentService, AttachmentState, AttachmentTable, BaseObserver, Column, ColumnType, ConnectionClosedError, ConnectionManager, ControlledExecutor, CrudBatch, CrudEntry, CrudTransaction, DBAdapterDefaultMixin, DBGetUtilsDefaultMixin, DEFAULT_CRUD_BATCH_LIMIT, DEFAULT_CRUD_UPLOAD_THROTTLE_MS, DEFAULT_INDEX_COLUMN_OPTIONS, DEFAULT_INDEX_OPTIONS, DEFAULT_LOCK_TIMEOUT_MS, DEFAULT_POWERSYNC_CLOSE_OPTIONS, DEFAULT_POWERSYNC_DB_OPTIONS, DEFAULT_PRESSURE_LIMITS, DEFAULT_REMOTE_LOGGER, DEFAULT_REMOTE_OPTIONS, DEFAULT_RETRY_DELAY_MS, DEFAULT_ROW_COMPARATOR, DEFAULT_STREAMING_SYNC_OPTIONS, DEFAULT_STREAM_CONNECTION_OPTIONS, DEFAULT_SYNC_CLIENT_IMPLEMENTATION, DEFAULT_TABLE_OPTIONS, DEFAULT_WATCH_QUERY_OPTIONS, DEFAULT_WATCH_THROTTLE_MS, DataStream, DiffTriggerOperation, DifferentialQueryProcessor, EMPTY_DIFFERENTIAL, EncodingType, FalsyComparator, FetchImplementationProvider, FetchStrategy, GetAllQuery, Index, IndexedColumn, InvalidSQLCharacters, LockType, LogLevel, MAX_AMOUNT_OF_COLUMNS, MAX_OP_ID, MEMORY_TRIGGER_CLAIM_MANAGER, Mutex, OnChangeQueryProcessor, OpType, OpTypeEnum, OplogEntry, PSInternalTable, PowerSyncControlCommand, RowUpdateType, Schema, Semaphore, SqliteBucketStorage, SyncClientImplementation, SyncDataBatch, SyncDataBucket, SyncProgress, SyncStatus, SyncStreamConnectionMethod, SyncingService, Table, TableV2, TriggerManagerImpl, UpdateType, UploadQueueStats, WatchedQueryListenerEvent, attachmentFromSql, column, compilableQueryWatch, createBaseLogger, createLogger, extractTableUpdates, isBatchedUpdateNotification, isContinueCheckpointRequest, isDBAdapter, isPowerSyncDatabaseOptionsWithSettings, isSQLOpenFactory, isSQLOpenOptions, isStreamingKeepalive, isStreamingSyncCheckpoint, isStreamingSyncCheckpointComplete, isStreamingSyncCheckpointDiff, isStreamingSyncCheckpointPartiallyComplete, isStreamingSyncData, isSyncNewCheckpointRequest, parseQuery, runOnSchemaChange, sanitizeSQL, sanitizeUUID, timeoutSignal };
|
|
14598
14688
|
//# sourceMappingURL=bundle.mjs.map
|