@powersync/web 0.0.0-dev-20251126195153 → 0.0.0-dev-20251129133952
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/index.umd.js +265 -127
- package/dist/index.umd.js.map +1 -1
- package/dist/worker/SharedSyncImplementation.umd.js +255 -105
- package/dist/worker/SharedSyncImplementation.umd.js.map +1 -1
- package/dist/worker/WASQLiteDB.umd.js +4 -4
- package/dist/worker/WASQLiteDB.umd.js.map +1 -1
- package/lib/src/db/adapters/AsyncDatabaseConnection.d.ts +3 -0
- package/lib/src/db/adapters/AsyncDatabaseConnection.js +6 -1
- package/lib/src/db/adapters/LockedAsyncDatabaseAdapter.d.ts +9 -0
- package/lib/src/db/adapters/LockedAsyncDatabaseAdapter.js +46 -8
- package/lib/src/db/adapters/WorkerWrappedAsyncDatabaseConnection.js +3 -2
- package/lib/src/db/sync/SharedWebStreamingSyncImplementation.d.ts +2 -1
- package/lib/src/db/sync/SharedWebStreamingSyncImplementation.js +48 -27
- package/lib/src/worker/sync/SharedSyncImplementation.d.ts +18 -3
- package/lib/src/worker/sync/SharedSyncImplementation.js +143 -76
- package/lib/src/worker/sync/WorkerClient.d.ts +3 -2
- package/lib/src/worker/sync/WorkerClient.js +26 -4
- package/lib/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/src/db/adapters/AsyncDatabaseConnection.ts +7 -0
- package/src/db/adapters/LockedAsyncDatabaseAdapter.ts +54 -9
- package/src/db/adapters/WorkerWrappedAsyncDatabaseConnection.ts +3 -2
- package/src/db/sync/SharedWebStreamingSyncImplementation.ts +60 -36
- package/src/worker/sync/SharedSyncImplementation.ts +171 -87
- package/src/worker/sync/WorkerClient.ts +28 -6
|
@@ -14,6 +14,9 @@ export type ProxiedQueryResult = Omit<QueryResult, 'rows'> & {
|
|
|
14
14
|
* @internal
|
|
15
15
|
*/
|
|
16
16
|
export type OnTableChangeCallback = (event: BatchedUpdateNotification) => void;
|
|
17
|
+
export declare class ConnectionClosedError extends Error {
|
|
18
|
+
constructor(message: string);
|
|
19
|
+
}
|
|
17
20
|
/**
|
|
18
21
|
* @internal
|
|
19
22
|
* An async Database connection which provides basic async SQL methods.
|
|
@@ -10,9 +10,15 @@ export interface LockedAsyncDatabaseAdapterOptions {
|
|
|
10
10
|
openConnection: () => Promise<AsyncDatabaseConnection>;
|
|
11
11
|
debugMode?: boolean;
|
|
12
12
|
logger?: ILogger;
|
|
13
|
+
defaultLockTimeoutMs?: number;
|
|
14
|
+
reOpenOnConnectionClosed?: boolean;
|
|
13
15
|
}
|
|
14
16
|
export type LockedAsyncDatabaseAdapterListener = DBAdapterListener & {
|
|
15
17
|
initialized?: () => void;
|
|
18
|
+
/**
|
|
19
|
+
* Fired when the database is re-opened after being closed.
|
|
20
|
+
*/
|
|
21
|
+
databaseReOpened?: () => void;
|
|
16
22
|
};
|
|
17
23
|
/**
|
|
18
24
|
* @internal
|
|
@@ -31,6 +37,8 @@ export declare class LockedAsyncDatabaseAdapter extends BaseObserver<LockedAsync
|
|
|
31
37
|
private _config;
|
|
32
38
|
protected pendingAbortControllers: Set<AbortController>;
|
|
33
39
|
protected requiresHolds: boolean | null;
|
|
40
|
+
protected requiresReOpen: boolean;
|
|
41
|
+
protected databaseOpenPromise: Promise<void> | null;
|
|
34
42
|
closing: boolean;
|
|
35
43
|
closed: boolean;
|
|
36
44
|
constructor(options: LockedAsyncDatabaseAdapterOptions);
|
|
@@ -40,6 +48,7 @@ export declare class LockedAsyncDatabaseAdapter extends BaseObserver<LockedAsync
|
|
|
40
48
|
* Init is automatic, this helps catch errors or explicitly await initialization
|
|
41
49
|
*/
|
|
42
50
|
init(): Promise<void>;
|
|
51
|
+
protected openInternalDB(): Promise<void>;
|
|
43
52
|
protected _init(): Promise<void>;
|
|
44
53
|
getConfiguration(): ResolvedWebSQLOpenOptions;
|
|
45
54
|
protected waitForInitialized(): Promise<void>;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { BaseObserver, createLogger } from '@powersync/common';
|
|
2
2
|
import { getNavigatorLocks } from '../..//shared/navigator';
|
|
3
|
+
import { ConnectionClosedError } from './AsyncDatabaseConnection';
|
|
3
4
|
import { WorkerWrappedAsyncDatabaseConnection } from './WorkerWrappedAsyncDatabaseConnection';
|
|
4
5
|
import { WASQLiteVFS } from './wa-sqlite/WASQLiteConnection';
|
|
5
6
|
/**
|
|
@@ -19,6 +20,8 @@ export class LockedAsyncDatabaseAdapter extends BaseObserver {
|
|
|
19
20
|
_config = null;
|
|
20
21
|
pendingAbortControllers;
|
|
21
22
|
requiresHolds;
|
|
23
|
+
requiresReOpen;
|
|
24
|
+
databaseOpenPromise = null;
|
|
22
25
|
closing;
|
|
23
26
|
closed;
|
|
24
27
|
constructor(options) {
|
|
@@ -30,6 +33,7 @@ export class LockedAsyncDatabaseAdapter extends BaseObserver {
|
|
|
30
33
|
this.closed = false;
|
|
31
34
|
this.closing = false;
|
|
32
35
|
this.requiresHolds = null;
|
|
36
|
+
this.requiresReOpen = false;
|
|
33
37
|
// Set the name if provided. We can query for the name if not available yet
|
|
34
38
|
this.debugMode = options.debugMode ?? false;
|
|
35
39
|
if (this.debugMode) {
|
|
@@ -68,17 +72,27 @@ export class LockedAsyncDatabaseAdapter extends BaseObserver {
|
|
|
68
72
|
async init() {
|
|
69
73
|
return this.initPromise;
|
|
70
74
|
}
|
|
71
|
-
async
|
|
75
|
+
async openInternalDB() {
|
|
76
|
+
// Dispose any previous table change listener.
|
|
77
|
+
this._disposeTableChangeListener?.();
|
|
78
|
+
this._disposeTableChangeListener = null;
|
|
79
|
+
const isReOpen = !!this._db;
|
|
72
80
|
this._db = await this.options.openConnection();
|
|
73
81
|
await this._db.init();
|
|
74
82
|
this._config = await this._db.getConfig();
|
|
75
83
|
await this.registerOnChangeListener(this._db);
|
|
76
|
-
|
|
84
|
+
if (isReOpen) {
|
|
85
|
+
this.iterateListeners((cb) => cb.databaseReOpened?.());
|
|
86
|
+
}
|
|
77
87
|
/**
|
|
78
88
|
* This is only required for the long-lived shared IndexedDB connections.
|
|
79
89
|
*/
|
|
80
90
|
this.requiresHolds = this._config.vfs == WASQLiteVFS.IDBBatchAtomicVFS;
|
|
81
91
|
}
|
|
92
|
+
async _init() {
|
|
93
|
+
await this.openInternalDB();
|
|
94
|
+
this.iterateListeners((cb) => cb.initialized?.());
|
|
95
|
+
}
|
|
82
96
|
getConfiguration() {
|
|
83
97
|
if (!this._config) {
|
|
84
98
|
throw new Error(`Cannot get config before initialization is completed`);
|
|
@@ -144,13 +158,13 @@ export class LockedAsyncDatabaseAdapter extends BaseObserver {
|
|
|
144
158
|
async readLock(fn, options) {
|
|
145
159
|
await this.waitForInitialized();
|
|
146
160
|
return this.acquireLock(async () => fn(this.generateDBHelpers({ execute: this._execute, executeRaw: this._executeRaw })), {
|
|
147
|
-
timeoutMs: options?.timeoutMs
|
|
161
|
+
timeoutMs: options?.timeoutMs ?? this.options.defaultLockTimeoutMs
|
|
148
162
|
});
|
|
149
163
|
}
|
|
150
164
|
async writeLock(fn, options) {
|
|
151
165
|
await this.waitForInitialized();
|
|
152
166
|
return this.acquireLock(async () => fn(this.generateDBHelpers({ execute: this._execute, executeRaw: this._executeRaw })), {
|
|
153
|
-
timeoutMs: options?.timeoutMs
|
|
167
|
+
timeoutMs: options?.timeoutMs ?? this.options.defaultLockTimeoutMs
|
|
154
168
|
});
|
|
155
169
|
}
|
|
156
170
|
async acquireLock(callback, options) {
|
|
@@ -161,7 +175,7 @@ export class LockedAsyncDatabaseAdapter extends BaseObserver {
|
|
|
161
175
|
const abortController = new AbortController();
|
|
162
176
|
this.pendingAbortControllers.add(abortController);
|
|
163
177
|
const { timeoutMs } = options ?? {};
|
|
164
|
-
const
|
|
178
|
+
const timeoutId = timeoutMs
|
|
165
179
|
? setTimeout(() => {
|
|
166
180
|
abortController.abort(`Timeout after ${timeoutMs}ms`);
|
|
167
181
|
this.pendingAbortControllers.delete(abortController);
|
|
@@ -169,13 +183,37 @@ export class LockedAsyncDatabaseAdapter extends BaseObserver {
|
|
|
169
183
|
: null;
|
|
170
184
|
return getNavigatorLocks().request(`db-lock-${this._dbIdentifier}`, { signal: abortController.signal }, async () => {
|
|
171
185
|
this.pendingAbortControllers.delete(abortController);
|
|
172
|
-
if (
|
|
173
|
-
clearTimeout(
|
|
186
|
+
if (timeoutId) {
|
|
187
|
+
clearTimeout(timeoutId);
|
|
174
188
|
}
|
|
175
|
-
|
|
189
|
+
let holdId = null;
|
|
176
190
|
try {
|
|
191
|
+
// The database is being opened in the background. Wait for it here.
|
|
192
|
+
if (this.databaseOpenPromise) {
|
|
193
|
+
try {
|
|
194
|
+
await this.databaseOpenPromise;
|
|
195
|
+
}
|
|
196
|
+
catch (ex) {
|
|
197
|
+
// This will cause a retry of opening the database.
|
|
198
|
+
const wrappedError = new ConnectionClosedError('Could not open database');
|
|
199
|
+
wrappedError.cause = ex;
|
|
200
|
+
throw wrappedError;
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
holdId = this.requiresHolds ? await this.baseDB.markHold() : null;
|
|
177
204
|
return await callback();
|
|
178
205
|
}
|
|
206
|
+
catch (ex) {
|
|
207
|
+
if (ex instanceof ConnectionClosedError) {
|
|
208
|
+
if (this.options.reOpenOnConnectionClosed && !this.databaseOpenPromise && !this.closing) {
|
|
209
|
+
// Immediately re-open the database. We need to miss as little table updates as possible.
|
|
210
|
+
this.databaseOpenPromise = this.openInternalDB().finally(() => {
|
|
211
|
+
this.databaseOpenPromise = null;
|
|
212
|
+
});
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
throw ex;
|
|
216
|
+
}
|
|
179
217
|
finally {
|
|
180
218
|
if (holdId) {
|
|
181
219
|
await this.baseDB.releaseHold(holdId);
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import * as Comlink from 'comlink';
|
|
2
|
+
import { ConnectionClosedError } from './AsyncDatabaseConnection';
|
|
2
3
|
/**
|
|
3
4
|
* Wraps a provided instance of {@link AsyncDatabaseConnection}, providing necessary proxy
|
|
4
5
|
* functions for worker listeners.
|
|
@@ -45,12 +46,12 @@ export class WorkerWrappedAsyncDatabaseConnection {
|
|
|
45
46
|
if (controller) {
|
|
46
47
|
return new Promise((resolve, reject) => {
|
|
47
48
|
if (controller.signal.aborted) {
|
|
48
|
-
reject(new
|
|
49
|
+
reject(new ConnectionClosedError('Called operation on closed remote'));
|
|
49
50
|
// Don't run the operation if we're going to reject
|
|
50
51
|
return;
|
|
51
52
|
}
|
|
52
53
|
function handleAbort() {
|
|
53
|
-
reject(new
|
|
54
|
+
reject(new ConnectionClosedError('Remote peer closed with request in flight'));
|
|
54
55
|
}
|
|
55
56
|
function completePromise(action) {
|
|
56
57
|
controller.signal.removeEventListener('abort', handleAbort);
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { PowerSyncConnectionOptions, PowerSyncCredentials, SubscribedStream, SyncStatusOptions } from '@powersync/common';
|
|
2
2
|
import * as Comlink from 'comlink';
|
|
3
3
|
import { AbstractSharedSyncClientProvider } from '../../worker/sync/AbstractSharedSyncClientProvider';
|
|
4
|
+
import { WorkerClient } from '../../worker/sync/WorkerClient';
|
|
4
5
|
import { WebDBAdapter } from '../adapters/WebDBAdapter';
|
|
5
6
|
import { WebStreamingSyncImplementation, WebStreamingSyncImplementationOptions } from './WebStreamingSyncImplementation';
|
|
6
|
-
import { WorkerClient } from '../../worker/sync/WorkerClient';
|
|
7
7
|
/**
|
|
8
8
|
* The shared worker will trigger methods on this side of the message port
|
|
9
9
|
* via this client provider.
|
|
@@ -41,6 +41,7 @@ export declare class SharedWebStreamingSyncImplementation extends WebStreamingSy
|
|
|
41
41
|
protected dbAdapter: WebDBAdapter;
|
|
42
42
|
private abortOnClose;
|
|
43
43
|
constructor(options: SharedWebStreamingSyncImplementationOptions);
|
|
44
|
+
protected _init(): Promise<void>;
|
|
44
45
|
/**
|
|
45
46
|
* Starts the sync process, this effectively acts as a call to
|
|
46
47
|
* `connect` if not yet connected.
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import * as Comlink from 'comlink';
|
|
2
|
+
import { getNavigatorLocks } from '../../shared/navigator';
|
|
2
3
|
import { AbstractSharedSyncClientProvider } from '../../worker/sync/AbstractSharedSyncClientProvider';
|
|
3
4
|
import { SharedSyncClientEvent } from '../../worker/sync/SharedSyncImplementation';
|
|
4
|
-
import { DEFAULT_CACHE_SIZE_KB,
|
|
5
|
+
import { DEFAULT_CACHE_SIZE_KB, TemporaryStorageOption, resolveWebSQLFlags } from '../adapters/web-sql-flags';
|
|
5
6
|
import { WebStreamingSyncImplementation } from './WebStreamingSyncImplementation';
|
|
6
|
-
import { getNavigatorLocks } from '../../shared/navigator';
|
|
7
7
|
/**
|
|
8
8
|
* The shared worker will trigger methods on this side of the message port
|
|
9
9
|
* via this client provider.
|
|
@@ -119,7 +119,19 @@ export class SharedWebStreamingSyncImplementation extends WebStreamingSyncImplem
|
|
|
119
119
|
type: 'module'
|
|
120
120
|
}).port;
|
|
121
121
|
}
|
|
122
|
+
/**
|
|
123
|
+
* Pass along any sync status updates to this listener
|
|
124
|
+
*/
|
|
125
|
+
this.clientProvider = new SharedSyncClientProvider(this.webOptions, (status) => {
|
|
126
|
+
this.updateSyncStatus(status);
|
|
127
|
+
}, options.db);
|
|
122
128
|
this.syncManager = Comlink.wrap(this.messagePort);
|
|
129
|
+
/**
|
|
130
|
+
* The sync worker will call this client provider when it needs
|
|
131
|
+
* to fetch credentials or upload data.
|
|
132
|
+
* This performs bi-directional method calling.
|
|
133
|
+
*/
|
|
134
|
+
Comlink.expose(this.clientProvider, this.messagePort);
|
|
123
135
|
this.syncManager.setLogLevel(this.logger.getLevel());
|
|
124
136
|
this.triggerCrudUpload = this.syncManager.triggerCrudUpload;
|
|
125
137
|
/**
|
|
@@ -128,9 +140,41 @@ export class SharedWebStreamingSyncImplementation extends WebStreamingSyncImplem
|
|
|
128
140
|
* DB worker, but a port to the DB worker can be transferred to the
|
|
129
141
|
* sync worker.
|
|
130
142
|
*/
|
|
143
|
+
this.isInitialized = this._init();
|
|
144
|
+
}
|
|
145
|
+
async _init() {
|
|
146
|
+
/**
|
|
147
|
+
* The general flow of initialization is:
|
|
148
|
+
* - The client requests a unique navigator lock.
|
|
149
|
+
* - Once the lock is acquired, we register the lock with the shared worker.
|
|
150
|
+
* - The shared worker can then request the same lock. The client has been closed if the shared worker can acquire the lock.
|
|
151
|
+
* - Once the shared worker knows the client's lock, we can guarentee that the shared worker will detect if the client has been closed.
|
|
152
|
+
* - This makes the client safe for the shared worker to use.
|
|
153
|
+
* - The client side lock is held until the client is disposed.
|
|
154
|
+
* - We resolve the top-level promise after the lock has been registered with the shared worker.
|
|
155
|
+
* - The client sends the params to the shared worker after locks have been registered.
|
|
156
|
+
*/
|
|
157
|
+
await new Promise((resolve) => {
|
|
158
|
+
// Request a random lock until this client is disposed. The name of the lock is sent to the shared worker, which
|
|
159
|
+
// will also attempt to acquire it. Since the lock is returned when the tab is closed, this allows the share worker
|
|
160
|
+
// to free resources associated with this tab.
|
|
161
|
+
// We take hold of this lock as soon-as-possible in order to cater for potentially closed tabs.
|
|
162
|
+
getNavigatorLocks().request(`tab-close-signal-${crypto.randomUUID()}`, async (lock) => {
|
|
163
|
+
if (this.abortOnClose.signal.aborted) {
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
166
|
+
// Awaiting here ensures the worker is waiting for the lock
|
|
167
|
+
await this.syncManager.addLockBasedCloseSignal(lock.name);
|
|
168
|
+
// The lock has been registered, we can continue with the initialization
|
|
169
|
+
resolve();
|
|
170
|
+
await new Promise((r) => {
|
|
171
|
+
this.abortOnClose.signal.onabort = () => r();
|
|
172
|
+
});
|
|
173
|
+
});
|
|
174
|
+
});
|
|
131
175
|
const { crudUploadThrottleMs, identifier, retryDelayMs } = this.options;
|
|
132
176
|
const flags = { ...this.webOptions.flags, workers: undefined };
|
|
133
|
-
|
|
177
|
+
await this.syncManager.setParams({
|
|
134
178
|
dbParams: this.dbAdapter.getConfiguration(),
|
|
135
179
|
streamOptions: {
|
|
136
180
|
crudUploadThrottleMs,
|
|
@@ -138,30 +182,7 @@ export class SharedWebStreamingSyncImplementation extends WebStreamingSyncImplem
|
|
|
138
182
|
retryDelayMs,
|
|
139
183
|
flags: flags
|
|
140
184
|
}
|
|
141
|
-
}, options.subscriptions);
|
|
142
|
-
/**
|
|
143
|
-
* Pass along any sync status updates to this listener
|
|
144
|
-
*/
|
|
145
|
-
this.clientProvider = new SharedSyncClientProvider(this.webOptions, (status) => {
|
|
146
|
-
this.iterateListeners((l) => this.updateSyncStatus(status));
|
|
147
|
-
}, options.db);
|
|
148
|
-
/**
|
|
149
|
-
* The sync worker will call this client provider when it needs
|
|
150
|
-
* to fetch credentials or upload data.
|
|
151
|
-
* This performs bi-directional method calling.
|
|
152
|
-
*/
|
|
153
|
-
Comlink.expose(this.clientProvider, this.messagePort);
|
|
154
|
-
// Request a random lock until this client is disposed. The name of the lock is sent to the shared worker, which
|
|
155
|
-
// will also attempt to acquire it. Since the lock is returned when the tab is closed, this allows the share worker
|
|
156
|
-
// to free resources associated with this tab.
|
|
157
|
-
getNavigatorLocks().request(`tab-close-signal-${crypto.randomUUID()}`, async (lock) => {
|
|
158
|
-
if (!this.abortOnClose.signal.aborted) {
|
|
159
|
-
this.syncManager.addLockBasedCloseSignal(lock.name);
|
|
160
|
-
await new Promise((r) => {
|
|
161
|
-
this.abortOnClose.signal.onabort = () => r();
|
|
162
|
-
});
|
|
163
|
-
}
|
|
164
|
-
});
|
|
185
|
+
}, this.options.subscriptions);
|
|
165
186
|
}
|
|
166
187
|
/**
|
|
167
188
|
* Starts the sync process, this effectively acts as a call to
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import { BaseObserver, ConnectionManager, DBAdapter, SubscribedStream, SyncStatus, type
|
|
1
|
+
import { BaseObserver, ConnectionManager, DBAdapter, SubscribedStream, SyncStatus, type ILogLevel, type ILogger, type PowerSyncConnectionOptions, type StreamingSyncImplementation, type StreamingSyncImplementationListener, type SyncStatusOptions } from '@powersync/common';
|
|
2
2
|
import { Mutex } from 'async-mutex';
|
|
3
3
|
import * as Comlink from 'comlink';
|
|
4
4
|
import { WebStreamingSyncImplementation, WebStreamingSyncImplementationOptions } from '../../db/sync/WebStreamingSyncImplementation';
|
|
5
|
+
import { WorkerWrappedAsyncDatabaseConnection } from '../../db/adapters/WorkerWrappedAsyncDatabaseConnection';
|
|
5
6
|
import { ResolvedWebSQLOpenOptions } from '../../db/adapters/web-sql-flags';
|
|
6
7
|
import { AbstractSharedSyncClientProvider } from './AbstractSharedSyncClientProvider';
|
|
7
8
|
/**
|
|
@@ -45,6 +46,11 @@ export type WrappedSyncPort = {
|
|
|
45
46
|
db?: DBAdapter;
|
|
46
47
|
currentSubscriptions: SubscribedStream[];
|
|
47
48
|
closeListeners: (() => void | Promise<void>)[];
|
|
49
|
+
/**
|
|
50
|
+
* If we can use Navigator locks to detect if the client has closed.
|
|
51
|
+
*/
|
|
52
|
+
isProtectedFromClose: boolean;
|
|
53
|
+
isClosing: boolean;
|
|
48
54
|
};
|
|
49
55
|
/**
|
|
50
56
|
* @internal
|
|
@@ -63,7 +69,6 @@ export declare class SharedSyncImplementation extends BaseObserver<SharedSyncImp
|
|
|
63
69
|
protected statusListener?: () => void;
|
|
64
70
|
protected fetchCredentialsController?: RemoteOperationAbortController;
|
|
65
71
|
protected uploadDataController?: RemoteOperationAbortController;
|
|
66
|
-
protected dbAdapter: DBAdapter | null;
|
|
67
72
|
protected syncParams: SharedSyncInitOptions | null;
|
|
68
73
|
protected logger: ILogger;
|
|
69
74
|
protected lastConnectOptions: PowerSyncConnectionOptions | undefined;
|
|
@@ -72,9 +77,14 @@ export declare class SharedSyncImplementation extends BaseObserver<SharedSyncImp
|
|
|
72
77
|
protected connectionManager: ConnectionManager;
|
|
73
78
|
syncStatus: SyncStatus;
|
|
74
79
|
broadCastLogger: ILogger;
|
|
80
|
+
protected distributedDB: DBAdapter | null;
|
|
75
81
|
constructor();
|
|
76
82
|
get lastSyncedAt(): Date | undefined;
|
|
77
83
|
get isConnected(): boolean;
|
|
84
|
+
/**
|
|
85
|
+
* Gets the last client port which we know is safe from unexpected closes.
|
|
86
|
+
*/
|
|
87
|
+
protected get lastWrappedPort(): WrappedSyncPort | undefined;
|
|
78
88
|
waitForStatus(status: SyncStatusOptions): Promise<void>;
|
|
79
89
|
waitUntilStatusMatches(predicate: (status: SyncStatus) => boolean): Promise<void>;
|
|
80
90
|
waitForReady(): Promise<void>;
|
|
@@ -102,6 +112,8 @@ export declare class SharedSyncImplementation extends BaseObserver<SharedSyncImp
|
|
|
102
112
|
clientProvider: Comlink.Remote<AbstractSharedSyncClientProvider>;
|
|
103
113
|
currentSubscriptions: never[];
|
|
104
114
|
closeListeners: never[];
|
|
115
|
+
isProtectedFromClose: false;
|
|
116
|
+
isClosing: false;
|
|
105
117
|
}>;
|
|
106
118
|
/**
|
|
107
119
|
* Removes a message port client from this manager's managed
|
|
@@ -113,7 +125,10 @@ export declare class SharedSyncImplementation extends BaseObserver<SharedSyncImp
|
|
|
113
125
|
getWriteCheckpoint(): Promise<string>;
|
|
114
126
|
protected withSyncImplementation<T>(callback: (sync: StreamingSyncImplementation) => Promise<T>): Promise<T>;
|
|
115
127
|
protected generateStreamingImplementation(): WebStreamingSyncImplementation;
|
|
116
|
-
|
|
128
|
+
/**
|
|
129
|
+
* Opens a worker wrapped database connection. Using the last connected client port.
|
|
130
|
+
*/
|
|
131
|
+
protected openInternalDB(): Promise<WorkerWrappedAsyncDatabaseConnection<ResolvedWebSQLOpenOptions>>;
|
|
117
132
|
/**
|
|
118
133
|
* A method to update the all shared statuses for each
|
|
119
134
|
* client.
|