@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.node.mjs
CHANGED
|
@@ -783,19 +783,69 @@ class SyncingService {
|
|
|
783
783
|
}
|
|
784
784
|
|
|
785
785
|
/**
|
|
786
|
-
*
|
|
786
|
+
* A simple fixed-capacity queue implementation.
|
|
787
|
+
*
|
|
788
|
+
* Unlike a naive queue implemented by `array.push()` and `array.shift()`, this avoids moving array elements around
|
|
789
|
+
* and is `O(1)` for {@link addLast} and {@link removeFirst}.
|
|
790
|
+
*/
|
|
791
|
+
class Queue {
|
|
792
|
+
table;
|
|
793
|
+
// Index of the first element in the table.
|
|
794
|
+
head;
|
|
795
|
+
// Amount of items currently in the queue.
|
|
796
|
+
_length;
|
|
797
|
+
constructor(initialItems) {
|
|
798
|
+
this.table = [...initialItems];
|
|
799
|
+
this.head = 0;
|
|
800
|
+
this._length = this.table.length;
|
|
801
|
+
}
|
|
802
|
+
get isEmpty() {
|
|
803
|
+
return this.length == 0;
|
|
804
|
+
}
|
|
805
|
+
get length() {
|
|
806
|
+
return this._length;
|
|
807
|
+
}
|
|
808
|
+
removeFirst() {
|
|
809
|
+
if (this.isEmpty) {
|
|
810
|
+
throw new Error('Queue is empty');
|
|
811
|
+
}
|
|
812
|
+
const result = this.table[this.head];
|
|
813
|
+
this._length--;
|
|
814
|
+
this.table[this.head] = undefined;
|
|
815
|
+
this.head = (this.head + 1) % this.table.length;
|
|
816
|
+
return result;
|
|
817
|
+
}
|
|
818
|
+
addLast(element) {
|
|
819
|
+
if (this.length == this.table.length) {
|
|
820
|
+
throw new Error('Queue is full');
|
|
821
|
+
}
|
|
822
|
+
this.table[(this.head + this._length) % this.table.length] = element;
|
|
823
|
+
this._length++;
|
|
824
|
+
}
|
|
825
|
+
}
|
|
826
|
+
|
|
827
|
+
/**
|
|
828
|
+
* An asynchronous semaphore implementation with associated items per lease.
|
|
787
829
|
*
|
|
788
830
|
* @internal This class is meant to be used in PowerSync SDKs only, and is not part of the public API.
|
|
789
831
|
*/
|
|
790
|
-
class
|
|
791
|
-
|
|
832
|
+
class Semaphore {
|
|
833
|
+
// Available items that are not currently assigned to a waiter.
|
|
834
|
+
available;
|
|
835
|
+
size;
|
|
792
836
|
// Linked list of waiters. We don't expect the wait list to become particularly large, and this allows removing
|
|
793
837
|
// aborted waiters from the middle of the list efficiently.
|
|
794
838
|
firstWaiter;
|
|
795
839
|
lastWaiter;
|
|
796
|
-
|
|
840
|
+
constructor(elements) {
|
|
841
|
+
this.available = new Queue(elements);
|
|
842
|
+
this.size = this.available.length;
|
|
843
|
+
}
|
|
844
|
+
addWaiter(requestedItems, onAcquire) {
|
|
797
845
|
const node = {
|
|
798
846
|
isActive: true,
|
|
847
|
+
acquiredItems: [],
|
|
848
|
+
remainingItems: requestedItems,
|
|
799
849
|
onAcquire,
|
|
800
850
|
prev: this.lastWaiter
|
|
801
851
|
};
|
|
@@ -821,52 +871,92 @@ class Mutex {
|
|
|
821
871
|
if (waiter == this.lastWaiter)
|
|
822
872
|
this.lastWaiter = prev;
|
|
823
873
|
}
|
|
824
|
-
|
|
874
|
+
requestPermits(amount, abort) {
|
|
875
|
+
if (amount <= 0 || amount > this.size) {
|
|
876
|
+
throw new Error(`Invalid amount of items requested (${amount}), must be between 1 and ${this.size}`);
|
|
877
|
+
}
|
|
825
878
|
return new Promise((resolve, reject) => {
|
|
826
879
|
function rejectAborted() {
|
|
827
|
-
reject(abort?.reason ?? new Error('
|
|
880
|
+
reject(abort?.reason ?? new Error('Semaphore acquire aborted'));
|
|
828
881
|
}
|
|
829
882
|
if (abort?.aborted) {
|
|
830
883
|
return rejectAborted();
|
|
831
884
|
}
|
|
832
|
-
let
|
|
885
|
+
let waiter;
|
|
833
886
|
const markCompleted = () => {
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
887
|
+
const items = waiter.acquiredItems;
|
|
888
|
+
waiter.acquiredItems = []; // Avoid releasing items twice.
|
|
889
|
+
for (const element of items) {
|
|
890
|
+
// Give to next waiter, if possible.
|
|
891
|
+
const nextWaiter = this.firstWaiter;
|
|
892
|
+
if (nextWaiter) {
|
|
893
|
+
nextWaiter.acquiredItems.push(element);
|
|
894
|
+
nextWaiter.remainingItems--;
|
|
895
|
+
if (nextWaiter.remainingItems == 0) {
|
|
896
|
+
nextWaiter.onAcquire();
|
|
897
|
+
}
|
|
898
|
+
}
|
|
899
|
+
else {
|
|
900
|
+
// No pending waiter, return lease into pool.
|
|
901
|
+
this.available.addLast(element);
|
|
902
|
+
}
|
|
842
903
|
}
|
|
843
|
-
|
|
844
|
-
|
|
904
|
+
};
|
|
905
|
+
const onAbort = () => {
|
|
906
|
+
abort?.removeEventListener('abort', onAbort);
|
|
907
|
+
if (waiter.isActive) {
|
|
908
|
+
this.deactivateWaiter(waiter);
|
|
909
|
+
rejectAborted();
|
|
845
910
|
}
|
|
846
911
|
};
|
|
847
|
-
|
|
848
|
-
this.
|
|
849
|
-
|
|
850
|
-
|
|
912
|
+
const resolvePromise = () => {
|
|
913
|
+
this.deactivateWaiter(waiter);
|
|
914
|
+
abort?.removeEventListener('abort', onAbort);
|
|
915
|
+
const items = waiter.acquiredItems;
|
|
916
|
+
resolve({ items, release: markCompleted });
|
|
917
|
+
};
|
|
918
|
+
waiter = this.addWaiter(amount, resolvePromise);
|
|
919
|
+
// If there are items in the pool that haven't been assigned, we can pull them into this waiter. Note that this is
|
|
920
|
+
// only the case if we're the first waiter (otherwise, items would have been assigned to an earlier waiter).
|
|
921
|
+
while (!this.available.isEmpty && waiter.remainingItems > 0) {
|
|
922
|
+
waiter.acquiredItems.push(this.available.removeFirst());
|
|
923
|
+
waiter.remainingItems--;
|
|
851
924
|
}
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
const onAbort = () => {
|
|
855
|
-
abort?.removeEventListener('abort', onAbort);
|
|
856
|
-
if (node.isActive) {
|
|
857
|
-
this.deactivateWaiter(node);
|
|
858
|
-
rejectAborted();
|
|
859
|
-
}
|
|
860
|
-
};
|
|
861
|
-
node = this.addWaiter(() => {
|
|
862
|
-
abort?.removeEventListener('abort', onAbort);
|
|
863
|
-
holdsMutex = true;
|
|
864
|
-
resolve(markCompleted);
|
|
865
|
-
});
|
|
866
|
-
abort?.addEventListener('abort', onAbort);
|
|
925
|
+
if (waiter.remainingItems == 0) {
|
|
926
|
+
return resolvePromise();
|
|
867
927
|
}
|
|
928
|
+
abort?.addEventListener('abort', onAbort);
|
|
868
929
|
});
|
|
869
930
|
}
|
|
931
|
+
/**
|
|
932
|
+
* Requests a single item from the pool.
|
|
933
|
+
*
|
|
934
|
+
* The returned `release` callback must be invoked to return the item into the pool.
|
|
935
|
+
*/
|
|
936
|
+
async requestOne(abort) {
|
|
937
|
+
const { items, release } = await this.requestPermits(1, abort);
|
|
938
|
+
return { release, item: items[0] };
|
|
939
|
+
}
|
|
940
|
+
/**
|
|
941
|
+
* Requests access to all items from the pool.
|
|
942
|
+
*
|
|
943
|
+
* The returned `release` callback must be invoked to return items into the pool.
|
|
944
|
+
*/
|
|
945
|
+
requestAll(abort) {
|
|
946
|
+
return this.requestPermits(this.size, abort);
|
|
947
|
+
}
|
|
948
|
+
}
|
|
949
|
+
/**
|
|
950
|
+
* An asynchronous mutex implementation.
|
|
951
|
+
*
|
|
952
|
+
* @internal This class is meant to be used in PowerSync SDKs only, and is not part of the public API.
|
|
953
|
+
*/
|
|
954
|
+
class Mutex {
|
|
955
|
+
inner = new Semaphore([null]);
|
|
956
|
+
async acquire(abort) {
|
|
957
|
+
const { release } = await this.inner.requestOne(abort);
|
|
958
|
+
return release;
|
|
959
|
+
}
|
|
870
960
|
async runExclusive(fn, abort) {
|
|
871
961
|
const returnMutex = await this.acquire(abort);
|
|
872
962
|
try {
|
|
@@ -8139,7 +8229,7 @@ function requireDist () {
|
|
|
8139
8229
|
|
|
8140
8230
|
var distExports = requireDist();
|
|
8141
8231
|
|
|
8142
|
-
var version = "1.
|
|
8232
|
+
var version = "1.51.0";
|
|
8143
8233
|
var PACKAGE = {
|
|
8144
8234
|
version: version};
|
|
8145
8235
|
|
|
@@ -12073,5 +12163,5 @@ const parseQuery = (query, parameters) => {
|
|
|
12073
12163
|
return { sqlStatement, parameters: parameters };
|
|
12074
12164
|
};
|
|
12075
12165
|
|
|
12076
|
-
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 };
|
|
12166
|
+
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 };
|
|
12077
12167
|
//# sourceMappingURL=bundle.node.mjs.map
|