@powersync/web 0.0.0-dev-20251127205344 → 0.0.0-dev-20251201150812
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/1807036ae51c10ee4d23.wasm +0 -0
- package/dist/{10072fe45f0a8fab0a0e.wasm → 307d8ce2280e3bae09d5.wasm} +0 -0
- package/dist/{6e435e51534839845554.wasm → cd8b9e8f4c87bf81c169.wasm} +0 -0
- package/dist/e797080f5ed0b5324166.wasm +0 -0
- package/dist/index.umd.js +336 -177
- package/dist/index.umd.js.map +1 -1
- package/dist/worker/SharedSyncImplementation.umd.js +310 -143
- package/dist/worker/SharedSyncImplementation.umd.js.map +1 -1
- package/dist/worker/WASQLiteDB.umd.js +19 -5
- package/dist/worker/WASQLiteDB.umd.js.map +1 -1
- package/dist/worker/node_modules_journeyapps_wa-sqlite_dist_mc-wa-sqlite-async_mjs.umd.js +2 -2
- package/dist/worker/node_modules_journeyapps_wa-sqlite_dist_mc-wa-sqlite-async_mjs.umd.js.map +1 -1
- package/dist/worker/node_modules_journeyapps_wa-sqlite_dist_mc-wa-sqlite_mjs.umd.js +2 -2
- package/dist/worker/node_modules_journeyapps_wa-sqlite_dist_mc-wa-sqlite_mjs.umd.js.map +1 -1
- package/dist/worker/node_modules_journeyapps_wa-sqlite_dist_wa-sqlite-async_mjs.umd.js +2 -2
- package/dist/worker/node_modules_journeyapps_wa-sqlite_dist_wa-sqlite-async_mjs.umd.js.map +1 -1
- package/dist/worker/node_modules_journeyapps_wa-sqlite_dist_wa-sqlite_mjs.umd.js +2 -2
- package/dist/worker/node_modules_journeyapps_wa-sqlite_dist_wa-sqlite_mjs.umd.js.map +1 -1
- package/dist/worker/node_modules_journeyapps_wa-sqlite_src_examples_IDBBatchAtomicVFS_js.umd.js +20 -23
- package/dist/worker/node_modules_journeyapps_wa-sqlite_src_examples_IDBBatchAtomicVFS_js.umd.js.map +1 -1
- package/lib/src/db/PowerSyncDatabase.d.ts +1 -1
- package/lib/src/db/PowerSyncDatabase.js +4 -4
- package/lib/src/db/adapters/AsyncDatabaseConnection.d.ts +8 -0
- package/lib/src/db/adapters/AsyncDatabaseConnection.js +11 -1
- package/lib/src/db/adapters/LockedAsyncDatabaseAdapter.d.ts +14 -0
- package/lib/src/db/adapters/LockedAsyncDatabaseAdapter.js +61 -8
- package/lib/src/db/adapters/WorkerWrappedAsyncDatabaseConnection.d.ts +5 -1
- package/lib/src/db/adapters/WorkerWrappedAsyncDatabaseConnection.js +15 -7
- package/lib/src/db/sync/SharedWebStreamingSyncImplementation.d.ts +1 -4
- package/lib/src/db/sync/SharedWebStreamingSyncImplementation.js +45 -31
- package/lib/src/worker/sync/MockSyncService.d.ts +2 -0
- package/lib/src/worker/sync/MockSyncService.js +3 -0
- package/lib/src/worker/sync/MockSyncServiceTypes.d.ts +101 -0
- package/lib/src/worker/sync/MockSyncServiceTypes.js +1 -0
- package/lib/src/worker/sync/MockSyncServiceWorker.d.ts +56 -0
- package/lib/src/worker/sync/MockSyncServiceWorker.js +369 -0
- package/lib/src/worker/sync/SharedSyncImplementation.d.ts +18 -8
- package/lib/src/worker/sync/SharedSyncImplementation.js +174 -108
- package/lib/src/worker/sync/SharedSyncImplementation.worker.js +1 -1
- package/lib/src/worker/sync/WorkerClient.d.ts +4 -5
- package/lib/src/worker/sync/WorkerClient.js +5 -7
- package/lib/tsconfig.tsbuildinfo +1 -1
- package/package.json +3 -3
- package/src/db/PowerSyncDatabase.ts +13 -15
- package/src/db/adapters/AsyncDatabaseConnection.ts +12 -0
- package/src/db/adapters/LockedAsyncDatabaseAdapter.ts +71 -9
- package/src/db/adapters/WorkerWrappedAsyncDatabaseConnection.ts +19 -6
- package/src/db/sync/SharedWebStreamingSyncImplementation.ts +56 -40
- package/src/worker/sync/MockSyncService.ts +3 -0
- package/src/worker/sync/MockSyncServiceTypes.ts +71 -0
- package/src/worker/sync/MockSyncServiceWorker.ts +406 -0
- package/src/worker/sync/SharedSyncImplementation.ts +201 -120
- package/src/worker/sync/SharedSyncImplementation.worker.ts +1 -1
- package/src/worker/sync/WorkerClient.ts +6 -11
- package/dist/a730f7ca717b02234beb.wasm +0 -0
- package/dist/aa2f408d64445fed090e.wasm +0 -0
|
@@ -3228,12 +3228,26 @@ class SyncStatus {
|
|
|
3228
3228
|
return {
|
|
3229
3229
|
connected: this.connected,
|
|
3230
3230
|
connecting: this.connecting,
|
|
3231
|
-
dataFlow:
|
|
3231
|
+
dataFlow: {
|
|
3232
|
+
...this.dataFlowStatus,
|
|
3233
|
+
uploadError: this.serializeError(this.dataFlowStatus.uploadError),
|
|
3234
|
+
downloadError: this.serializeError(this.dataFlowStatus.downloadError)
|
|
3235
|
+
},
|
|
3232
3236
|
lastSyncedAt: this.lastSyncedAt,
|
|
3233
3237
|
hasSynced: this.hasSynced,
|
|
3234
3238
|
priorityStatusEntries: this.priorityStatusEntries
|
|
3235
3239
|
};
|
|
3236
3240
|
}
|
|
3241
|
+
serializeError(error) {
|
|
3242
|
+
if (typeof error == 'undefined') {
|
|
3243
|
+
return undefined;
|
|
3244
|
+
}
|
|
3245
|
+
return {
|
|
3246
|
+
name: error.name,
|
|
3247
|
+
message: error.message,
|
|
3248
|
+
stack: error.stack
|
|
3249
|
+
};
|
|
3250
|
+
}
|
|
3237
3251
|
static comparePriorities(a, b) {
|
|
3238
3252
|
return b.priority - a.priority; // Reverse because higher priorities have lower numbers
|
|
3239
3253
|
}
|
|
@@ -14659,7 +14673,7 @@ The next upload iteration will be delayed.`);
|
|
|
14659
14673
|
uploadError: ex
|
|
14660
14674
|
}
|
|
14661
14675
|
});
|
|
14662
|
-
await this.delayRetry(controller.signal);
|
|
14676
|
+
await this.delayRetry(controller.signal, this.options.crudUploadThrottleMs);
|
|
14663
14677
|
if (!this.isConnected) {
|
|
14664
14678
|
// Exit the upload loop if the sync stream is no longer connected
|
|
14665
14679
|
break;
|
|
@@ -15370,14 +15384,14 @@ The next upload iteration will be delayed.`);
|
|
|
15370
15384
|
// trigger this for all updates
|
|
15371
15385
|
this.iterateListeners((cb) => cb.statusUpdated?.(options));
|
|
15372
15386
|
}
|
|
15373
|
-
async delayRetry(signal) {
|
|
15387
|
+
async delayRetry(signal, delayMs) {
|
|
15374
15388
|
return new Promise((resolve) => {
|
|
15375
15389
|
if (signal?.aborted) {
|
|
15376
15390
|
// If the signal is already aborted, resolve immediately
|
|
15377
15391
|
resolve();
|
|
15378
15392
|
return;
|
|
15379
15393
|
}
|
|
15380
|
-
const
|
|
15394
|
+
const delay = delayMs ?? this.options.retryDelayMs;
|
|
15381
15395
|
let timeoutId;
|
|
15382
15396
|
const endDelay = () => {
|
|
15383
15397
|
resolve();
|
|
@@ -15388,7 +15402,7 @@ The next upload iteration will be delayed.`);
|
|
|
15388
15402
|
signal?.removeEventListener('abort', endDelay);
|
|
15389
15403
|
};
|
|
15390
15404
|
signal?.addEventListener('abort', endDelay, { once: true });
|
|
15391
|
-
timeoutId = setTimeout(endDelay,
|
|
15405
|
+
timeoutId = setTimeout(endDelay, delay);
|
|
15392
15406
|
});
|
|
15393
15407
|
}
|
|
15394
15408
|
updateSubscriptions(subscriptions) {
|
|
@@ -17600,6 +17614,31 @@ const parseQuery = (query, parameters) => {
|
|
|
17600
17614
|
//# sourceMappingURL=bundle.mjs.map
|
|
17601
17615
|
|
|
17602
17616
|
|
|
17617
|
+
/***/ }),
|
|
17618
|
+
|
|
17619
|
+
/***/ "./lib/src/db/adapters/AsyncDatabaseConnection.js":
|
|
17620
|
+
/*!********************************************************!*\
|
|
17621
|
+
!*** ./lib/src/db/adapters/AsyncDatabaseConnection.js ***!
|
|
17622
|
+
\********************************************************/
|
|
17623
|
+
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
|
17624
|
+
|
|
17625
|
+
__webpack_require__.r(__webpack_exports__);
|
|
17626
|
+
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
|
17627
|
+
/* harmony export */ ConnectionClosedError: () => (/* binding */ ConnectionClosedError)
|
|
17628
|
+
/* harmony export */ });
|
|
17629
|
+
/**
|
|
17630
|
+
* Thrown when an underlying database connection is closed.
|
|
17631
|
+
* This is particularly relevant when worker connections are marked as closed while
|
|
17632
|
+
* operations are still in progress.
|
|
17633
|
+
*/
|
|
17634
|
+
class ConnectionClosedError extends Error {
|
|
17635
|
+
constructor(message) {
|
|
17636
|
+
super(message);
|
|
17637
|
+
this.name = 'ConnectionClosedError';
|
|
17638
|
+
}
|
|
17639
|
+
}
|
|
17640
|
+
|
|
17641
|
+
|
|
17603
17642
|
/***/ }),
|
|
17604
17643
|
|
|
17605
17644
|
/***/ "./lib/src/db/adapters/LockedAsyncDatabaseAdapter.js":
|
|
@@ -17614,8 +17653,10 @@ __webpack_require__.r(__webpack_exports__);
|
|
|
17614
17653
|
/* harmony export */ });
|
|
17615
17654
|
/* harmony import */ var _powersync_common__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @powersync/common */ "../common/dist/bundle.mjs");
|
|
17616
17655
|
/* harmony import */ var _shared_navigator__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../..//shared/navigator */ "./lib/src/shared/navigator.js");
|
|
17617
|
-
/* harmony import */ var
|
|
17618
|
-
/* harmony import */ var
|
|
17656
|
+
/* harmony import */ var _AsyncDatabaseConnection__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./AsyncDatabaseConnection */ "./lib/src/db/adapters/AsyncDatabaseConnection.js");
|
|
17657
|
+
/* harmony import */ var _WorkerWrappedAsyncDatabaseConnection__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./WorkerWrappedAsyncDatabaseConnection */ "./lib/src/db/adapters/WorkerWrappedAsyncDatabaseConnection.js");
|
|
17658
|
+
/* harmony import */ var _wa_sqlite_WASQLiteConnection__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./wa-sqlite/WASQLiteConnection */ "./lib/src/db/adapters/wa-sqlite/WASQLiteConnection.js");
|
|
17659
|
+
|
|
17619
17660
|
|
|
17620
17661
|
|
|
17621
17662
|
|
|
@@ -17637,6 +17678,7 @@ class LockedAsyncDatabaseAdapter extends _powersync_common__WEBPACK_IMPORTED_MOD
|
|
|
17637
17678
|
_config = null;
|
|
17638
17679
|
pendingAbortControllers;
|
|
17639
17680
|
requiresHolds;
|
|
17681
|
+
databaseOpenPromise = null;
|
|
17640
17682
|
closing;
|
|
17641
17683
|
closed;
|
|
17642
17684
|
constructor(options) {
|
|
@@ -17686,16 +17728,45 @@ class LockedAsyncDatabaseAdapter extends _powersync_common__WEBPACK_IMPORTED_MOD
|
|
|
17686
17728
|
async init() {
|
|
17687
17729
|
return this.initPromise;
|
|
17688
17730
|
}
|
|
17689
|
-
async
|
|
17731
|
+
async openInternalDB() {
|
|
17732
|
+
// Dispose any previous table change listener.
|
|
17733
|
+
this._disposeTableChangeListener?.();
|
|
17734
|
+
this._disposeTableChangeListener = null;
|
|
17735
|
+
const isReOpen = !!this._db;
|
|
17690
17736
|
this._db = await this.options.openConnection();
|
|
17691
17737
|
await this._db.init();
|
|
17692
17738
|
this._config = await this._db.getConfig();
|
|
17693
17739
|
await this.registerOnChangeListener(this._db);
|
|
17694
|
-
|
|
17740
|
+
if (isReOpen) {
|
|
17741
|
+
this.iterateListeners((cb) => cb.databaseReOpened?.());
|
|
17742
|
+
}
|
|
17695
17743
|
/**
|
|
17696
17744
|
* This is only required for the long-lived shared IndexedDB connections.
|
|
17697
17745
|
*/
|
|
17698
|
-
this.requiresHolds = this._config.vfs ==
|
|
17746
|
+
this.requiresHolds = this._config.vfs == _wa_sqlite_WASQLiteConnection__WEBPACK_IMPORTED_MODULE_4__.WASQLiteVFS.IDBBatchAtomicVFS;
|
|
17747
|
+
}
|
|
17748
|
+
_reOpen() {
|
|
17749
|
+
this.databaseOpenPromise = this.openInternalDB().finally(() => {
|
|
17750
|
+
this.databaseOpenPromise = null;
|
|
17751
|
+
});
|
|
17752
|
+
return this.databaseOpenPromise;
|
|
17753
|
+
}
|
|
17754
|
+
/**
|
|
17755
|
+
* Re-opens the underlying database.
|
|
17756
|
+
* Returns a pending operation if one is already in progress.
|
|
17757
|
+
*/
|
|
17758
|
+
async reOpenInternalDB() {
|
|
17759
|
+
if (!this.options.reOpenOnConnectionClosed) {
|
|
17760
|
+
throw new Error(`Cannot re-open underlying database, reOpenOnConnectionClosed is not enabled`);
|
|
17761
|
+
}
|
|
17762
|
+
if (this.databaseOpenPromise) {
|
|
17763
|
+
return this.databaseOpenPromise;
|
|
17764
|
+
}
|
|
17765
|
+
return this._reOpen();
|
|
17766
|
+
}
|
|
17767
|
+
async _init() {
|
|
17768
|
+
await this.openInternalDB();
|
|
17769
|
+
this.iterateListeners((cb) => cb.initialized?.());
|
|
17699
17770
|
}
|
|
17700
17771
|
getConfiguration() {
|
|
17701
17772
|
if (!this._config) {
|
|
@@ -17708,7 +17779,7 @@ class LockedAsyncDatabaseAdapter extends _powersync_common__WEBPACK_IMPORTED_MOD
|
|
|
17708
17779
|
await this.initPromise;
|
|
17709
17780
|
}
|
|
17710
17781
|
async shareConnection() {
|
|
17711
|
-
if (false == this._db instanceof
|
|
17782
|
+
if (false == this._db instanceof _WorkerWrappedAsyncDatabaseConnection__WEBPACK_IMPORTED_MODULE_3__.WorkerWrappedAsyncDatabaseConnection) {
|
|
17712
17783
|
throw new Error(`Only worker connections can be shared`);
|
|
17713
17784
|
}
|
|
17714
17785
|
return this._db.shareConnection();
|
|
@@ -17762,13 +17833,13 @@ class LockedAsyncDatabaseAdapter extends _powersync_common__WEBPACK_IMPORTED_MOD
|
|
|
17762
17833
|
async readLock(fn, options) {
|
|
17763
17834
|
await this.waitForInitialized();
|
|
17764
17835
|
return this.acquireLock(async () => fn(this.generateDBHelpers({ execute: this._execute, executeRaw: this._executeRaw })), {
|
|
17765
|
-
timeoutMs: options?.timeoutMs
|
|
17836
|
+
timeoutMs: options?.timeoutMs ?? this.options.defaultLockTimeoutMs
|
|
17766
17837
|
});
|
|
17767
17838
|
}
|
|
17768
17839
|
async writeLock(fn, options) {
|
|
17769
17840
|
await this.waitForInitialized();
|
|
17770
17841
|
return this.acquireLock(async () => fn(this.generateDBHelpers({ execute: this._execute, executeRaw: this._executeRaw })), {
|
|
17771
|
-
timeoutMs: options?.timeoutMs
|
|
17842
|
+
timeoutMs: options?.timeoutMs ?? this.options.defaultLockTimeoutMs
|
|
17772
17843
|
});
|
|
17773
17844
|
}
|
|
17774
17845
|
async acquireLock(callback, options) {
|
|
@@ -17779,7 +17850,7 @@ class LockedAsyncDatabaseAdapter extends _powersync_common__WEBPACK_IMPORTED_MOD
|
|
|
17779
17850
|
const abortController = new AbortController();
|
|
17780
17851
|
this.pendingAbortControllers.add(abortController);
|
|
17781
17852
|
const { timeoutMs } = options ?? {};
|
|
17782
|
-
const
|
|
17853
|
+
const timeoutId = timeoutMs
|
|
17783
17854
|
? setTimeout(() => {
|
|
17784
17855
|
abortController.abort(`Timeout after ${timeoutMs}ms`);
|
|
17785
17856
|
this.pendingAbortControllers.delete(abortController);
|
|
@@ -17787,13 +17858,35 @@ class LockedAsyncDatabaseAdapter extends _powersync_common__WEBPACK_IMPORTED_MOD
|
|
|
17787
17858
|
: null;
|
|
17788
17859
|
return (0,_shared_navigator__WEBPACK_IMPORTED_MODULE_1__.getNavigatorLocks)().request(`db-lock-${this._dbIdentifier}`, { signal: abortController.signal }, async () => {
|
|
17789
17860
|
this.pendingAbortControllers.delete(abortController);
|
|
17790
|
-
if (
|
|
17791
|
-
clearTimeout(
|
|
17861
|
+
if (timeoutId) {
|
|
17862
|
+
clearTimeout(timeoutId);
|
|
17792
17863
|
}
|
|
17793
|
-
|
|
17864
|
+
let holdId = null;
|
|
17794
17865
|
try {
|
|
17866
|
+
// The database is being opened in the background. Wait for it here.
|
|
17867
|
+
if (this.databaseOpenPromise) {
|
|
17868
|
+
try {
|
|
17869
|
+
await this.databaseOpenPromise;
|
|
17870
|
+
}
|
|
17871
|
+
catch (ex) {
|
|
17872
|
+
// This will cause a retry of opening the database.
|
|
17873
|
+
const wrappedError = new _AsyncDatabaseConnection__WEBPACK_IMPORTED_MODULE_2__.ConnectionClosedError('Could not open database');
|
|
17874
|
+
wrappedError.cause = ex;
|
|
17875
|
+
throw wrappedError;
|
|
17876
|
+
}
|
|
17877
|
+
}
|
|
17878
|
+
holdId = this.requiresHolds ? await this.baseDB.markHold() : null;
|
|
17795
17879
|
return await callback();
|
|
17796
17880
|
}
|
|
17881
|
+
catch (ex) {
|
|
17882
|
+
if (ex instanceof _AsyncDatabaseConnection__WEBPACK_IMPORTED_MODULE_2__.ConnectionClosedError) {
|
|
17883
|
+
if (this.options.reOpenOnConnectionClosed && !this.databaseOpenPromise && !this.closing) {
|
|
17884
|
+
// Immediately re-open the database. We need to miss as little table updates as possible.
|
|
17885
|
+
this.reOpenInternalDB();
|
|
17886
|
+
}
|
|
17887
|
+
}
|
|
17888
|
+
throw ex;
|
|
17889
|
+
}
|
|
17797
17890
|
finally {
|
|
17798
17891
|
if (holdId) {
|
|
17799
17892
|
await this.baseDB.releaseHold(holdId);
|
|
@@ -17926,17 +18019,22 @@ __webpack_require__.r(__webpack_exports__);
|
|
|
17926
18019
|
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
|
17927
18020
|
/* harmony export */ WorkerWrappedAsyncDatabaseConnection: () => (/* binding */ WorkerWrappedAsyncDatabaseConnection)
|
|
17928
18021
|
/* harmony export */ });
|
|
17929
|
-
/* harmony import */ var
|
|
18022
|
+
/* harmony import */ var _powersync_common__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @powersync/common */ "../common/dist/bundle.mjs");
|
|
18023
|
+
/* harmony import */ var comlink__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! comlink */ "../../node_modules/comlink/dist/esm/comlink.mjs");
|
|
18024
|
+
/* harmony import */ var _AsyncDatabaseConnection__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./AsyncDatabaseConnection */ "./lib/src/db/adapters/AsyncDatabaseConnection.js");
|
|
18025
|
+
|
|
18026
|
+
|
|
17930
18027
|
|
|
17931
18028
|
/**
|
|
17932
18029
|
* Wraps a provided instance of {@link AsyncDatabaseConnection}, providing necessary proxy
|
|
17933
18030
|
* functions for worker listeners.
|
|
17934
18031
|
*/
|
|
17935
|
-
class WorkerWrappedAsyncDatabaseConnection {
|
|
18032
|
+
class WorkerWrappedAsyncDatabaseConnection extends _powersync_common__WEBPACK_IMPORTED_MODULE_0__.BaseObserver {
|
|
17936
18033
|
options;
|
|
17937
18034
|
lockAbortController = new AbortController();
|
|
17938
18035
|
notifyRemoteClosed;
|
|
17939
18036
|
constructor(options) {
|
|
18037
|
+
super();
|
|
17940
18038
|
this.options = options;
|
|
17941
18039
|
if (options.remoteCanCloseUnexpectedly) {
|
|
17942
18040
|
this.notifyRemoteClosed = new AbortController();
|
|
@@ -17969,17 +18067,20 @@ class WorkerWrappedAsyncDatabaseConnection {
|
|
|
17969
18067
|
isAutoCommit() {
|
|
17970
18068
|
return this.withRemote(() => this.baseConnection.isAutoCommit());
|
|
17971
18069
|
}
|
|
17972
|
-
withRemote(workerPromise) {
|
|
18070
|
+
withRemote(workerPromise, fireActionOnAbort = false) {
|
|
17973
18071
|
const controller = this.notifyRemoteClosed;
|
|
17974
18072
|
if (controller) {
|
|
17975
18073
|
return new Promise((resolve, reject) => {
|
|
17976
18074
|
if (controller.signal.aborted) {
|
|
17977
|
-
reject(new
|
|
17978
|
-
|
|
17979
|
-
|
|
18075
|
+
reject(new _AsyncDatabaseConnection__WEBPACK_IMPORTED_MODULE_1__.ConnectionClosedError('Called operation on closed remote'));
|
|
18076
|
+
if (!fireActionOnAbort) {
|
|
18077
|
+
// Don't run the operation if we're going to reject
|
|
18078
|
+
// We might want to fire-and-forget the operation in some cases (like a close operation)
|
|
18079
|
+
return;
|
|
18080
|
+
}
|
|
17980
18081
|
}
|
|
17981
18082
|
function handleAbort() {
|
|
17982
|
-
reject(new
|
|
18083
|
+
reject(new _AsyncDatabaseConnection__WEBPACK_IMPORTED_MODULE_1__.ConnectionClosedError('Remote peer closed with request in flight'));
|
|
17983
18084
|
}
|
|
17984
18085
|
function completePromise(action) {
|
|
17985
18086
|
controller.signal.removeEventListener('abort', handleAbort);
|
|
@@ -18033,7 +18134,7 @@ class WorkerWrappedAsyncDatabaseConnection {
|
|
|
18033
18134
|
reject(ex);
|
|
18034
18135
|
}
|
|
18035
18136
|
}));
|
|
18036
|
-
const newPort = await remote[
|
|
18137
|
+
const newPort = await remote[comlink__WEBPACK_IMPORTED_MODULE_2__.createEndpoint]();
|
|
18037
18138
|
return { port: newPort, identifier };
|
|
18038
18139
|
}
|
|
18039
18140
|
/**
|
|
@@ -18041,17 +18142,19 @@ class WorkerWrappedAsyncDatabaseConnection {
|
|
|
18041
18142
|
* This can be extended by custom implementations in order to handle proxy events.
|
|
18042
18143
|
*/
|
|
18043
18144
|
async registerOnTableChange(callback) {
|
|
18044
|
-
return this.baseConnection.registerOnTableChange(
|
|
18145
|
+
return this.baseConnection.registerOnTableChange(comlink__WEBPACK_IMPORTED_MODULE_2__.proxy(callback));
|
|
18045
18146
|
}
|
|
18046
18147
|
async close() {
|
|
18047
18148
|
// Abort any pending lock requests.
|
|
18048
18149
|
this.lockAbortController.abort();
|
|
18049
18150
|
try {
|
|
18050
|
-
|
|
18151
|
+
// fire and forget the close operation
|
|
18152
|
+
await this.withRemote(() => this.baseConnection.close(), true);
|
|
18051
18153
|
}
|
|
18052
18154
|
finally {
|
|
18053
|
-
this.options.remote[
|
|
18155
|
+
this.options.remote[comlink__WEBPACK_IMPORTED_MODULE_2__.releaseProxy]();
|
|
18054
18156
|
this.options.onClose?.();
|
|
18157
|
+
this.iterateListeners((l) => l.closing?.());
|
|
18055
18158
|
}
|
|
18056
18159
|
}
|
|
18057
18160
|
execute(sql, params) {
|
|
@@ -18877,7 +18980,6 @@ class SharedSyncImplementation extends _powersync_common__WEBPACK_IMPORTED_MODUL
|
|
|
18877
18980
|
statusListener;
|
|
18878
18981
|
fetchCredentialsController;
|
|
18879
18982
|
uploadDataController;
|
|
18880
|
-
dbAdapter;
|
|
18881
18983
|
syncParams;
|
|
18882
18984
|
logger;
|
|
18883
18985
|
lastConnectOptions;
|
|
@@ -18886,10 +18988,10 @@ class SharedSyncImplementation extends _powersync_common__WEBPACK_IMPORTED_MODUL
|
|
|
18886
18988
|
connectionManager;
|
|
18887
18989
|
syncStatus;
|
|
18888
18990
|
broadCastLogger;
|
|
18991
|
+
distributedDB;
|
|
18889
18992
|
constructor() {
|
|
18890
18993
|
super();
|
|
18891
18994
|
this.ports = [];
|
|
18892
|
-
this.dbAdapter = null;
|
|
18893
18995
|
this.syncParams = null;
|
|
18894
18996
|
this.logger = (0,_powersync_common__WEBPACK_IMPORTED_MODULE_0__.createLogger)('shared-sync');
|
|
18895
18997
|
this.lastConnectOptions = undefined;
|
|
@@ -18902,26 +19004,23 @@ class SharedSyncImplementation extends _powersync_common__WEBPACK_IMPORTED_MODUL
|
|
|
18902
19004
|
}
|
|
18903
19005
|
});
|
|
18904
19006
|
});
|
|
19007
|
+
// Should be configured once we get params
|
|
19008
|
+
this.distributedDB = null;
|
|
18905
19009
|
this.syncStatus = new _powersync_common__WEBPACK_IMPORTED_MODULE_0__.SyncStatus({});
|
|
18906
19010
|
this.broadCastLogger = new _BroadcastLogger__WEBPACK_IMPORTED_MODULE_6__.BroadcastLogger(this.ports);
|
|
18907
19011
|
this.connectionManager = new _powersync_common__WEBPACK_IMPORTED_MODULE_0__.ConnectionManager({
|
|
18908
19012
|
createSyncImplementation: async () => {
|
|
18909
|
-
|
|
18910
|
-
|
|
18911
|
-
|
|
18912
|
-
|
|
19013
|
+
await this.waitForReady();
|
|
19014
|
+
const sync = this.generateStreamingImplementation();
|
|
19015
|
+
const onDispose = sync.registerListener({
|
|
19016
|
+
statusChanged: (status) => {
|
|
19017
|
+
this.updateAllStatuses(status.toJSON());
|
|
18913
19018
|
}
|
|
18914
|
-
const sync = this.generateStreamingImplementation();
|
|
18915
|
-
const onDispose = sync.registerListener({
|
|
18916
|
-
statusChanged: (status) => {
|
|
18917
|
-
this.updateAllStatuses(status.toJSON());
|
|
18918
|
-
}
|
|
18919
|
-
});
|
|
18920
|
-
return {
|
|
18921
|
-
sync,
|
|
18922
|
-
onDispose
|
|
18923
|
-
};
|
|
18924
19019
|
});
|
|
19020
|
+
return {
|
|
19021
|
+
sync,
|
|
19022
|
+
onDispose
|
|
19023
|
+
};
|
|
18925
19024
|
},
|
|
18926
19025
|
logger: this.logger
|
|
18927
19026
|
});
|
|
@@ -18932,6 +19031,29 @@ class SharedSyncImplementation extends _powersync_common__WEBPACK_IMPORTED_MODUL
|
|
|
18932
19031
|
get isConnected() {
|
|
18933
19032
|
return this.connectionManager.syncStreamImplementation?.isConnected ?? false;
|
|
18934
19033
|
}
|
|
19034
|
+
/**
|
|
19035
|
+
* Gets the last client port which we know is safe from unexpected closes.
|
|
19036
|
+
*/
|
|
19037
|
+
async getLastWrappedPort() {
|
|
19038
|
+
// Find the last port which is not closing
|
|
19039
|
+
return await this.portMutex.runExclusive(() => {
|
|
19040
|
+
for (let i = this.ports.length - 1; i >= 0; i--) {
|
|
19041
|
+
if (!this.ports[i].isClosing) {
|
|
19042
|
+
return this.ports[i];
|
|
19043
|
+
}
|
|
19044
|
+
}
|
|
19045
|
+
return;
|
|
19046
|
+
});
|
|
19047
|
+
}
|
|
19048
|
+
/**
|
|
19049
|
+
* In some very rare cases a specific tab might not respond to requests.
|
|
19050
|
+
* This returns a random port which is not closing.
|
|
19051
|
+
*/
|
|
19052
|
+
async getRandomWrappedPort() {
|
|
19053
|
+
return await this.portMutex.runExclusive(() => {
|
|
19054
|
+
return this.ports[Math.floor(Math.random() * this.ports.length)];
|
|
19055
|
+
});
|
|
19056
|
+
}
|
|
18935
19057
|
async waitForStatus(status) {
|
|
18936
19058
|
return this.withSyncImplementation(async (sync) => {
|
|
18937
19059
|
return sync.waitForStatus(status);
|
|
@@ -18972,28 +19094,45 @@ class SharedSyncImplementation extends _powersync_common__WEBPACK_IMPORTED_MODUL
|
|
|
18972
19094
|
async setParams(params) {
|
|
18973
19095
|
await this.portMutex.runExclusive(async () => {
|
|
18974
19096
|
this.collectActiveSubscriptions();
|
|
18975
|
-
|
|
18976
|
-
|
|
18977
|
-
|
|
18978
|
-
|
|
18979
|
-
|
|
18980
|
-
|
|
18981
|
-
|
|
18982
|
-
|
|
18983
|
-
|
|
18984
|
-
|
|
18985
|
-
|
|
18986
|
-
|
|
18987
|
-
|
|
18988
|
-
|
|
18989
|
-
|
|
18990
|
-
|
|
18991
|
-
|
|
18992
|
-
|
|
18993
|
-
|
|
19097
|
+
});
|
|
19098
|
+
if (this.syncParams) {
|
|
19099
|
+
// Cannot modify already existing sync implementation params
|
|
19100
|
+
return;
|
|
19101
|
+
}
|
|
19102
|
+
// First time setting params
|
|
19103
|
+
this.syncParams = params;
|
|
19104
|
+
if (params.streamOptions?.flags?.broadcastLogs) {
|
|
19105
|
+
this.logger = this.broadCastLogger;
|
|
19106
|
+
}
|
|
19107
|
+
const lockedAdapter = new _db_adapters_LockedAsyncDatabaseAdapter__WEBPACK_IMPORTED_MODULE_4__.LockedAsyncDatabaseAdapter({
|
|
19108
|
+
name: params.dbParams.dbFilename,
|
|
19109
|
+
openConnection: async () => {
|
|
19110
|
+
// Gets a connection from the clients when a new connection is requested.
|
|
19111
|
+
const db = await this.openInternalDB();
|
|
19112
|
+
db.registerListener({
|
|
19113
|
+
closing: () => {
|
|
19114
|
+
lockedAdapter.reOpenInternalDB();
|
|
19115
|
+
}
|
|
19116
|
+
});
|
|
19117
|
+
return db;
|
|
19118
|
+
},
|
|
19119
|
+
logger: this.logger,
|
|
19120
|
+
reOpenOnConnectionClosed: true
|
|
19121
|
+
});
|
|
19122
|
+
this.distributedDB = lockedAdapter;
|
|
19123
|
+
await lockedAdapter.init();
|
|
19124
|
+
lockedAdapter.registerListener({
|
|
19125
|
+
databaseReOpened: () => {
|
|
19126
|
+
// We may have missed some table updates while the database was closed.
|
|
19127
|
+
// We can poke the crud in case we missed any updates.
|
|
19128
|
+
this.connectionManager.syncStreamImplementation?.triggerCrudUpload();
|
|
18994
19129
|
}
|
|
18995
|
-
this.iterateListeners((l) => l.initialized?.());
|
|
18996
19130
|
});
|
|
19131
|
+
self.onerror = (event) => {
|
|
19132
|
+
// Share any uncaught events on the broadcast logger
|
|
19133
|
+
this.logger.error('Uncaught exception in PowerSync shared sync worker', event);
|
|
19134
|
+
};
|
|
19135
|
+
this.iterateListeners((l) => l.initialized?.());
|
|
18997
19136
|
}
|
|
18998
19137
|
async dispose() {
|
|
18999
19138
|
await this.waitForReady();
|
|
@@ -19022,7 +19161,8 @@ class SharedSyncImplementation extends _powersync_common__WEBPACK_IMPORTED_MODUL
|
|
|
19022
19161
|
port,
|
|
19023
19162
|
clientProvider: comlink__WEBPACK_IMPORTED_MODULE_7__.wrap(port),
|
|
19024
19163
|
currentSubscriptions: [],
|
|
19025
|
-
closeListeners: []
|
|
19164
|
+
closeListeners: [],
|
|
19165
|
+
isClosing: false
|
|
19026
19166
|
};
|
|
19027
19167
|
this.ports.push(portProvider);
|
|
19028
19168
|
// Give the newly connected client the latest status
|
|
@@ -19038,14 +19178,16 @@ class SharedSyncImplementation extends _powersync_common__WEBPACK_IMPORTED_MODUL
|
|
|
19038
19178
|
* clients.
|
|
19039
19179
|
*/
|
|
19040
19180
|
async removePort(port) {
|
|
19181
|
+
// Ports might be removed faster than we can process them.
|
|
19182
|
+
port.isClosing = true;
|
|
19041
19183
|
// Remove the port within a mutex context.
|
|
19042
19184
|
// Warns if the port is not found. This should not happen in practice.
|
|
19043
19185
|
// We return early if the port is not found.
|
|
19044
|
-
|
|
19186
|
+
return await this.portMutex.runExclusive(async () => {
|
|
19045
19187
|
const index = this.ports.findIndex((p) => p == port);
|
|
19046
19188
|
if (index < 0) {
|
|
19047
19189
|
this.logger.warn(`Could not remove port ${port} since it is not present in active ports.`);
|
|
19048
|
-
return {};
|
|
19190
|
+
return () => { };
|
|
19049
19191
|
}
|
|
19050
19192
|
const trackedPort = this.ports[index];
|
|
19051
19193
|
// Remove from the list of active ports
|
|
@@ -19059,40 +19201,13 @@ class SharedSyncImplementation extends _powersync_common__WEBPACK_IMPORTED_MODUL
|
|
|
19059
19201
|
abortController.controller.abort(new _powersync_common__WEBPACK_IMPORTED_MODULE_0__.AbortOperation('Closing pending requests after client port is removed'));
|
|
19060
19202
|
}
|
|
19061
19203
|
});
|
|
19062
|
-
|
|
19063
|
-
|
|
19064
|
-
|
|
19065
|
-
* We can disconnect in the portMutex lock. This ensures the disconnect is not affected by potential other
|
|
19066
|
-
* connect operations coming from other tabs.
|
|
19067
|
-
*/
|
|
19068
|
-
if (this.dbAdapter && this.dbAdapter == trackedPort.db) {
|
|
19069
|
-
this.logger.debug(`Disconnecting due to closed database: should reconnect: ${shouldReconnect}`);
|
|
19070
|
-
this.dbAdapter = null;
|
|
19071
|
-
// Unconditionally close the connection because the database it's writing to has just been closed.
|
|
19072
|
-
// The connection has been closed previously, this might throw. We should be able to ignore it.
|
|
19073
|
-
await this.connectionManager
|
|
19074
|
-
.disconnect()
|
|
19075
|
-
.catch((ex) => this.logger.warn('Error while disconnecting. Will attempt to reconnect.', ex));
|
|
19204
|
+
// Close the worker wrapped database connection, we can't accurately rely on this connection
|
|
19205
|
+
for (const closeListener of trackedPort.closeListeners) {
|
|
19206
|
+
await closeListener();
|
|
19076
19207
|
}
|
|
19077
|
-
|
|
19078
|
-
|
|
19079
|
-
trackedPort
|
|
19080
|
-
};
|
|
19208
|
+
this.collectActiveSubscriptions();
|
|
19209
|
+
return () => trackedPort.clientProvider[comlink__WEBPACK_IMPORTED_MODULE_7__.releaseProxy]();
|
|
19081
19210
|
});
|
|
19082
|
-
if (!trackedPort) {
|
|
19083
|
-
// We could not find the port to remove
|
|
19084
|
-
return () => { };
|
|
19085
|
-
}
|
|
19086
|
-
for (const closeListener of trackedPort.closeListeners) {
|
|
19087
|
-
await closeListener();
|
|
19088
|
-
}
|
|
19089
|
-
if (shouldReconnect) {
|
|
19090
|
-
await this.connectionManager.connect(CONNECTOR_PLACEHOLDER, this.lastConnectOptions ?? {});
|
|
19091
|
-
}
|
|
19092
|
-
// Re-index subscriptions, the subscriptions of the removed port would no longer be considered.
|
|
19093
|
-
this.collectActiveSubscriptions();
|
|
19094
|
-
// Release proxy
|
|
19095
|
-
return () => trackedPort.clientProvider[comlink__WEBPACK_IMPORTED_MODULE_7__.releaseProxy]();
|
|
19096
19211
|
}
|
|
19097
19212
|
triggerCrudUpload() {
|
|
19098
19213
|
this.withSyncImplementation(async (sync) => {
|
|
@@ -19129,10 +19244,13 @@ class SharedSyncImplementation extends _powersync_common__WEBPACK_IMPORTED_MODUL
|
|
|
19129
19244
|
const syncParams = this.syncParams;
|
|
19130
19245
|
// Create a new StreamingSyncImplementation for each connect call. This is usually done is all SDKs.
|
|
19131
19246
|
return new _db_sync_WebStreamingSyncImplementation__WEBPACK_IMPORTED_MODULE_3__.WebStreamingSyncImplementation({
|
|
19132
|
-
adapter: new _powersync_common__WEBPACK_IMPORTED_MODULE_0__.SqliteBucketStorage(this.
|
|
19247
|
+
adapter: new _powersync_common__WEBPACK_IMPORTED_MODULE_0__.SqliteBucketStorage(this.distributedDB, this.logger),
|
|
19133
19248
|
remote: new _db_sync_WebRemote__WEBPACK_IMPORTED_MODULE_2__.WebRemote({
|
|
19134
19249
|
invalidateCredentials: async () => {
|
|
19135
|
-
const lastPort = this.
|
|
19250
|
+
const lastPort = await this.getLastWrappedPort();
|
|
19251
|
+
if (!lastPort) {
|
|
19252
|
+
throw new Error('No client port found to invalidate credentials');
|
|
19253
|
+
}
|
|
19136
19254
|
try {
|
|
19137
19255
|
this.logger.log('calling the last port client provider to invalidate credentials');
|
|
19138
19256
|
lastPort.clientProvider.invalidateCredentials();
|
|
@@ -19142,7 +19260,10 @@ class SharedSyncImplementation extends _powersync_common__WEBPACK_IMPORTED_MODUL
|
|
|
19142
19260
|
}
|
|
19143
19261
|
},
|
|
19144
19262
|
fetchCredentials: async () => {
|
|
19145
|
-
const lastPort = this.
|
|
19263
|
+
const lastPort = await this.getLastWrappedPort();
|
|
19264
|
+
if (!lastPort) {
|
|
19265
|
+
throw new Error('No client port found to fetch credentials');
|
|
19266
|
+
}
|
|
19146
19267
|
return new Promise(async (resolve, reject) => {
|
|
19147
19268
|
const abortController = new AbortController();
|
|
19148
19269
|
this.fetchCredentialsController = {
|
|
@@ -19164,7 +19285,10 @@ class SharedSyncImplementation extends _powersync_common__WEBPACK_IMPORTED_MODUL
|
|
|
19164
19285
|
}
|
|
19165
19286
|
}, this.logger),
|
|
19166
19287
|
uploadCrud: async () => {
|
|
19167
|
-
const lastPort = this.
|
|
19288
|
+
const lastPort = await this.getLastWrappedPort();
|
|
19289
|
+
if (!lastPort) {
|
|
19290
|
+
throw new Error('No client port found to upload crud');
|
|
19291
|
+
}
|
|
19168
19292
|
return new Promise(async (resolve, reject) => {
|
|
19169
19293
|
const abortController = new AbortController();
|
|
19170
19294
|
this.uploadDataController = {
|
|
@@ -19190,19 +19314,52 @@ class SharedSyncImplementation extends _powersync_common__WEBPACK_IMPORTED_MODUL
|
|
|
19190
19314
|
logger: this.logger
|
|
19191
19315
|
});
|
|
19192
19316
|
}
|
|
19317
|
+
/**
|
|
19318
|
+
* Opens a worker wrapped database connection. Using the last connected client port.
|
|
19319
|
+
*/
|
|
19193
19320
|
async openInternalDB() {
|
|
19194
|
-
|
|
19195
|
-
|
|
19196
|
-
|
|
19197
|
-
|
|
19198
|
-
|
|
19199
|
-
|
|
19200
|
-
|
|
19201
|
-
|
|
19202
|
-
|
|
19203
|
-
|
|
19204
|
-
|
|
19205
|
-
|
|
19321
|
+
while (true) {
|
|
19322
|
+
try {
|
|
19323
|
+
const client = await this.getRandomWrappedPort();
|
|
19324
|
+
if (!client) {
|
|
19325
|
+
// Should not really happen in practice
|
|
19326
|
+
throw new Error(`Could not open DB connection since no client is connected.`);
|
|
19327
|
+
}
|
|
19328
|
+
// Fail-safe timeout for opening a database connection.
|
|
19329
|
+
const timeout = setTimeout(() => {
|
|
19330
|
+
abortController.abort();
|
|
19331
|
+
}, 10_000);
|
|
19332
|
+
/**
|
|
19333
|
+
* Handle cases where the client might close while opening a connection.
|
|
19334
|
+
*/
|
|
19335
|
+
const abortController = new AbortController();
|
|
19336
|
+
const closeListener = () => {
|
|
19337
|
+
abortController.abort();
|
|
19338
|
+
};
|
|
19339
|
+
const removeCloseListener = () => {
|
|
19340
|
+
const index = client.closeListeners.indexOf(closeListener);
|
|
19341
|
+
if (index >= 0) {
|
|
19342
|
+
client.closeListeners.splice(index, 1);
|
|
19343
|
+
}
|
|
19344
|
+
};
|
|
19345
|
+
client.closeListeners.push(closeListener);
|
|
19346
|
+
const workerPort = await withAbort(() => client.clientProvider.getDBWorkerPort(), abortController.signal).catch((ex) => {
|
|
19347
|
+
removeCloseListener();
|
|
19348
|
+
throw ex;
|
|
19349
|
+
});
|
|
19350
|
+
const remote = comlink__WEBPACK_IMPORTED_MODULE_7__.wrap(workerPort);
|
|
19351
|
+
const identifier = this.syncParams.dbParams.dbFilename;
|
|
19352
|
+
/**
|
|
19353
|
+
* The open could fail if the tab is closed while we're busy opening the database.
|
|
19354
|
+
* This operation is typically executed inside an exclusive portMutex lock.
|
|
19355
|
+
* We typically execute the closeListeners using the portMutex in a different context.
|
|
19356
|
+
* We can't rely on the closeListeners to abort the operation if the tab is closed.
|
|
19357
|
+
*/
|
|
19358
|
+
const db = await withAbort(() => remote(this.syncParams.dbParams), abortController.signal).finally(() => {
|
|
19359
|
+
// We can remove the close listener here since we no longer need it past this point.
|
|
19360
|
+
removeCloseListener();
|
|
19361
|
+
});
|
|
19362
|
+
clearTimeout(timeout);
|
|
19206
19363
|
const wrapped = new _db_adapters_WorkerWrappedAsyncDatabaseConnection__WEBPACK_IMPORTED_MODULE_5__.WorkerWrappedAsyncDatabaseConnection({
|
|
19207
19364
|
remote,
|
|
19208
19365
|
baseConnection: db,
|
|
@@ -19211,22 +19368,23 @@ class SharedSyncImplementation extends _powersync_common__WEBPACK_IMPORTED_MODUL
|
|
|
19211
19368
|
// that and ensure pending requests are aborted when the tab is closed.
|
|
19212
19369
|
remoteCanCloseUnexpectedly: true
|
|
19213
19370
|
});
|
|
19214
|
-
|
|
19371
|
+
client.closeListeners.push(async () => {
|
|
19215
19372
|
this.logger.info('Aborting open connection because associated tab closed.');
|
|
19216
19373
|
/**
|
|
19217
19374
|
* Don't await this close operation. It might never resolve if the tab is closed.
|
|
19218
|
-
* We
|
|
19219
|
-
*
|
|
19375
|
+
* We mark the remote as closed first, this will reject any pending requests.
|
|
19376
|
+
* We then call close. The close operation is configured to fire-and-forget, the main promise will reject immediately.
|
|
19220
19377
|
*/
|
|
19221
|
-
wrapped.close().catch((ex) => this.logger.warn('error closing database connection', ex));
|
|
19222
19378
|
wrapped.markRemoteClosed();
|
|
19379
|
+
wrapped.close().catch((ex) => this.logger.warn('error closing database connection', ex));
|
|
19223
19380
|
});
|
|
19224
19381
|
return wrapped;
|
|
19225
|
-
}
|
|
19226
|
-
|
|
19227
|
-
|
|
19228
|
-
|
|
19229
|
-
|
|
19382
|
+
}
|
|
19383
|
+
catch (ex) {
|
|
19384
|
+
this.logger.warn('Error opening internal DB', ex);
|
|
19385
|
+
await new Promise((resolve) => setTimeout(resolve, 1000));
|
|
19386
|
+
}
|
|
19387
|
+
}
|
|
19230
19388
|
}
|
|
19231
19389
|
/**
|
|
19232
19390
|
* A method to update the all shared statuses for each
|
|
@@ -19236,18 +19394,29 @@ class SharedSyncImplementation extends _powersync_common__WEBPACK_IMPORTED_MODUL
|
|
|
19236
19394
|
this.syncStatus = new _powersync_common__WEBPACK_IMPORTED_MODULE_0__.SyncStatus(status);
|
|
19237
19395
|
this.ports.forEach((p) => p.clientProvider.statusChanged(status));
|
|
19238
19396
|
}
|
|
19239
|
-
|
|
19240
|
-
|
|
19241
|
-
|
|
19242
|
-
|
|
19243
|
-
|
|
19244
|
-
|
|
19245
|
-
|
|
19397
|
+
}
|
|
19398
|
+
/**
|
|
19399
|
+
* Runs the action with an abort controller.
|
|
19400
|
+
*/
|
|
19401
|
+
function withAbort(action, signal) {
|
|
19402
|
+
return new Promise((resolve, reject) => {
|
|
19403
|
+
if (signal.aborted) {
|
|
19404
|
+
reject(new _powersync_common__WEBPACK_IMPORTED_MODULE_0__.AbortOperation('Operation aborted by abort controller'));
|
|
19405
|
+
return;
|
|
19246
19406
|
}
|
|
19247
|
-
|
|
19248
|
-
|
|
19249
|
-
|
|
19250
|
-
|
|
19407
|
+
function handleAbort() {
|
|
19408
|
+
signal.removeEventListener('abort', handleAbort);
|
|
19409
|
+
reject(new _powersync_common__WEBPACK_IMPORTED_MODULE_0__.AbortOperation('Operation aborted by abort controller'));
|
|
19410
|
+
}
|
|
19411
|
+
signal.addEventListener('abort', handleAbort, { once: true });
|
|
19412
|
+
function completePromise(action) {
|
|
19413
|
+
signal.removeEventListener('abort', handleAbort);
|
|
19414
|
+
action();
|
|
19415
|
+
}
|
|
19416
|
+
action()
|
|
19417
|
+
.then((data) => completePromise(() => resolve(data)))
|
|
19418
|
+
.catch((e) => completePromise(() => reject(e)));
|
|
19419
|
+
});
|
|
19251
19420
|
}
|
|
19252
19421
|
|
|
19253
19422
|
|
|
@@ -19279,12 +19448,11 @@ class WorkerClient {
|
|
|
19279
19448
|
sync;
|
|
19280
19449
|
port;
|
|
19281
19450
|
resolvedPort = null;
|
|
19451
|
+
resolvedPortPromise = null;
|
|
19282
19452
|
constructor(sync, port) {
|
|
19283
19453
|
this.sync = sync;
|
|
19284
19454
|
this.port = port;
|
|
19285
19455
|
comlink__WEBPACK_IMPORTED_MODULE_2__.expose(this, this.port);
|
|
19286
|
-
}
|
|
19287
|
-
async initialize() {
|
|
19288
19456
|
/**
|
|
19289
19457
|
* Adds an extra listener which can remove this port
|
|
19290
19458
|
* from the list of monitored ports.
|
|
@@ -19295,7 +19463,6 @@ class WorkerClient {
|
|
|
19295
19463
|
await this.removePort();
|
|
19296
19464
|
}
|
|
19297
19465
|
});
|
|
19298
|
-
this.resolvedPort = await this.sync.addPort(this.port);
|
|
19299
19466
|
}
|
|
19300
19467
|
async removePort() {
|
|
19301
19468
|
if (this.resolvedPort) {
|
|
@@ -19316,7 +19483,10 @@ class WorkerClient {
|
|
|
19316
19483
|
* When the client tab is closed, its lock will be returned. So when the shared worker attempts to acquire the lock,
|
|
19317
19484
|
* it can consider the connection to be closed.
|
|
19318
19485
|
*/
|
|
19319
|
-
addLockBasedCloseSignal(name) {
|
|
19486
|
+
async addLockBasedCloseSignal(name) {
|
|
19487
|
+
// Only add the port once the lock has been obtained on the client.
|
|
19488
|
+
this.resolvedPort = await this.sync.addPort(this.port);
|
|
19489
|
+
// Don't await this lock request
|
|
19320
19490
|
(0,_shared_navigator__WEBPACK_IMPORTED_MODULE_0__.getNavigatorLocks)().request(name, async () => {
|
|
19321
19491
|
await this.removePort();
|
|
19322
19492
|
});
|
|
@@ -19348,9 +19518,6 @@ class WorkerClient {
|
|
|
19348
19518
|
disconnect() {
|
|
19349
19519
|
return this.sync.disconnect();
|
|
19350
19520
|
}
|
|
19351
|
-
async _testUpdateAllStatuses(status) {
|
|
19352
|
-
return this.sync._testUpdateAllStatuses(status);
|
|
19353
|
-
}
|
|
19354
19521
|
}
|
|
19355
19522
|
|
|
19356
19523
|
|
|
@@ -19532,7 +19699,7 @@ logger.useDefaults();
|
|
|
19532
19699
|
const sharedSyncImplementation = new _SharedSyncImplementation__WEBPACK_IMPORTED_MODULE_1__.SharedSyncImplementation();
|
|
19533
19700
|
_self.onconnect = async function (event) {
|
|
19534
19701
|
const port = event.ports[0];
|
|
19535
|
-
|
|
19702
|
+
new _WorkerClient__WEBPACK_IMPORTED_MODULE_2__.WorkerClient(sharedSyncImplementation, port);
|
|
19536
19703
|
};
|
|
19537
19704
|
|
|
19538
19705
|
})();
|