@powersync/common 1.22.2 → 1.24.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.mjs +3 -3
- package/lib/client/AbstractPowerSyncDatabase.d.ts +7 -12
- package/lib/client/AbstractPowerSyncDatabase.js +17 -3
- package/lib/client/sync/stream/AbstractRemote.d.ts +16 -1
- package/lib/client/sync/stream/AbstractRemote.js +20 -7
- package/lib/client/sync/stream/AbstractStreamingSyncImplementation.d.ts +29 -6
- package/lib/client/sync/stream/AbstractStreamingSyncImplementation.js +23 -8
- package/lib/db/crud/SyncStatus.d.ts +2 -0
- package/lib/db/crud/SyncStatus.js +5 -1
- package/package.json +1 -1
|
@@ -10,25 +10,18 @@ import { PowerSyncBackendConnector } from './connection/PowerSyncBackendConnecto
|
|
|
10
10
|
import { BucketStorageAdapter } from './sync/bucket/BucketStorageAdapter.js';
|
|
11
11
|
import { CrudBatch } from './sync/bucket/CrudBatch.js';
|
|
12
12
|
import { CrudTransaction } from './sync/bucket/CrudTransaction.js';
|
|
13
|
-
import { PowerSyncConnectionOptions, StreamingSyncImplementation, StreamingSyncImplementationListener } from './sync/stream/AbstractStreamingSyncImplementation.js';
|
|
13
|
+
import { type AdditionalConnectionOptions, type PowerSyncConnectionOptions, StreamingSyncImplementation, StreamingSyncImplementationListener, type RequiredAdditionalConnectionOptions } from './sync/stream/AbstractStreamingSyncImplementation.js';
|
|
14
14
|
export interface DisconnectAndClearOptions {
|
|
15
15
|
/** When set to false, data in local-only tables is preserved. */
|
|
16
16
|
clearLocal?: boolean;
|
|
17
17
|
}
|
|
18
|
-
export interface BasePowerSyncDatabaseOptions {
|
|
18
|
+
export interface BasePowerSyncDatabaseOptions extends AdditionalConnectionOptions {
|
|
19
19
|
/** Schema used for the local database. */
|
|
20
20
|
schema: Schema;
|
|
21
21
|
/**
|
|
22
|
-
*
|
|
23
|
-
* from the PowerSync backend after an error occurs.
|
|
22
|
+
* @deprecated Use {@link retryDelayMs} instead as this will be removed in future releases.
|
|
24
23
|
*/
|
|
25
24
|
retryDelay?: number;
|
|
26
|
-
/**
|
|
27
|
-
* Backend Connector CRUD operations are throttled
|
|
28
|
-
* to occur at most every `crudUploadThrottleMs`
|
|
29
|
-
* milliseconds.
|
|
30
|
-
*/
|
|
31
|
-
crudUploadThrottleMs?: number;
|
|
32
25
|
logger?: ILogger;
|
|
33
26
|
}
|
|
34
27
|
export interface PowerSyncDatabaseOptions extends BasePowerSyncDatabaseOptions {
|
|
@@ -89,7 +82,7 @@ export interface PowerSyncCloseOptions {
|
|
|
89
82
|
export declare const DEFAULT_POWERSYNC_CLOSE_OPTIONS: PowerSyncCloseOptions;
|
|
90
83
|
export declare const DEFAULT_WATCH_THROTTLE_MS = 30;
|
|
91
84
|
export declare const DEFAULT_POWERSYNC_DB_OPTIONS: {
|
|
92
|
-
|
|
85
|
+
retryDelayMs: number;
|
|
93
86
|
logger: Logger.ILogger;
|
|
94
87
|
crudUploadThrottleMs: number;
|
|
95
88
|
};
|
|
@@ -148,11 +141,12 @@ export declare abstract class AbstractPowerSyncDatabase extends BaseObserver<Pow
|
|
|
148
141
|
* Whether a connection to the PowerSync service is currently open.
|
|
149
142
|
*/
|
|
150
143
|
get connected(): boolean;
|
|
144
|
+
get connecting(): boolean;
|
|
151
145
|
/**
|
|
152
146
|
* Opens the DBAdapter given open options using a default open factory
|
|
153
147
|
*/
|
|
154
148
|
protected abstract openDBAdapter(options: PowerSyncDatabaseOptionsWithSettings): DBAdapter;
|
|
155
|
-
protected abstract generateSyncStreamImplementation(connector: PowerSyncBackendConnector): StreamingSyncImplementation;
|
|
149
|
+
protected abstract generateSyncStreamImplementation(connector: PowerSyncBackendConnector, options: RequiredAdditionalConnectionOptions): StreamingSyncImplementation;
|
|
156
150
|
protected abstract generateBucketStorageAdapter(): BucketStorageAdapter;
|
|
157
151
|
/**
|
|
158
152
|
* @returns A promise which will resolve once initialization is completed.
|
|
@@ -185,6 +179,7 @@ export declare abstract class AbstractPowerSyncDatabase extends BaseObserver<Pow
|
|
|
185
179
|
* While initializing is automatic, this helps to catch and report initialization errors.
|
|
186
180
|
*/
|
|
187
181
|
init(): Promise<void>;
|
|
182
|
+
resolvedConnectionOptions(options?: PowerSyncConnectionOptions): RequiredAdditionalConnectionOptions;
|
|
188
183
|
/**
|
|
189
184
|
* Connects to stream of events from the PowerSync instance.
|
|
190
185
|
*/
|
|
@@ -13,7 +13,7 @@ import { PSInternalTable } from './sync/bucket/BucketStorageAdapter.js';
|
|
|
13
13
|
import { CrudBatch } from './sync/bucket/CrudBatch.js';
|
|
14
14
|
import { CrudEntry } from './sync/bucket/CrudEntry.js';
|
|
15
15
|
import { CrudTransaction } from './sync/bucket/CrudTransaction.js';
|
|
16
|
-
import { DEFAULT_CRUD_UPLOAD_THROTTLE_MS } from './sync/stream/AbstractStreamingSyncImplementation.js';
|
|
16
|
+
import { DEFAULT_CRUD_UPLOAD_THROTTLE_MS, DEFAULT_RETRY_DELAY_MS } from './sync/stream/AbstractStreamingSyncImplementation.js';
|
|
17
17
|
import { runOnSchemaChange } from './runOnSchemaChange.js';
|
|
18
18
|
const POWERSYNC_TABLE_MATCH = /(^ps_data__|^ps_data_local__)/;
|
|
19
19
|
const DEFAULT_DISCONNECT_CLEAR_OPTIONS = {
|
|
@@ -24,7 +24,7 @@ export const DEFAULT_POWERSYNC_CLOSE_OPTIONS = {
|
|
|
24
24
|
};
|
|
25
25
|
export const DEFAULT_WATCH_THROTTLE_MS = 30;
|
|
26
26
|
export const DEFAULT_POWERSYNC_DB_OPTIONS = {
|
|
27
|
-
|
|
27
|
+
retryDelayMs: 5000,
|
|
28
28
|
logger: Logger.get('PowerSyncDatabase'),
|
|
29
29
|
crudUploadThrottleMs: DEFAULT_CRUD_UPLOAD_THROTTLE_MS
|
|
30
30
|
};
|
|
@@ -114,6 +114,9 @@ export class AbstractPowerSyncDatabase extends BaseObserver {
|
|
|
114
114
|
get connected() {
|
|
115
115
|
return this.currentStatus?.connected || false;
|
|
116
116
|
}
|
|
117
|
+
get connecting() {
|
|
118
|
+
return this.currentStatus?.connecting || false;
|
|
119
|
+
}
|
|
117
120
|
/**
|
|
118
121
|
* @returns A promise which will resolve once initialization is completed.
|
|
119
122
|
*/
|
|
@@ -222,6 +225,13 @@ export class AbstractPowerSyncDatabase extends BaseObserver {
|
|
|
222
225
|
async init() {
|
|
223
226
|
return this.waitForReady();
|
|
224
227
|
}
|
|
228
|
+
// Use the options passed in during connect, or fallback to the options set during database creation or fallback to the default options
|
|
229
|
+
resolvedConnectionOptions(options) {
|
|
230
|
+
return {
|
|
231
|
+
retryDelayMs: options?.retryDelayMs ?? this.options.retryDelayMs ?? this.options.retryDelay ?? DEFAULT_RETRY_DELAY_MS,
|
|
232
|
+
crudUploadThrottleMs: options?.crudUploadThrottleMs ?? this.options.crudUploadThrottleMs ?? DEFAULT_CRUD_UPLOAD_THROTTLE_MS
|
|
233
|
+
};
|
|
234
|
+
}
|
|
225
235
|
/**
|
|
226
236
|
* Connects to stream of events from the PowerSync instance.
|
|
227
237
|
*/
|
|
@@ -232,7 +242,11 @@ export class AbstractPowerSyncDatabase extends BaseObserver {
|
|
|
232
242
|
if (this.closed) {
|
|
233
243
|
throw new Error('Cannot connect using a closed client');
|
|
234
244
|
}
|
|
235
|
-
|
|
245
|
+
const { retryDelayMs, crudUploadThrottleMs } = this.resolvedConnectionOptions(options);
|
|
246
|
+
this.syncStreamImplementation = this.generateSyncStreamImplementation(connector, {
|
|
247
|
+
retryDelayMs,
|
|
248
|
+
crudUploadThrottleMs,
|
|
249
|
+
});
|
|
236
250
|
this.syncStatusListenerDisposer = this.syncStreamImplementation.registerListener({
|
|
237
251
|
statusChanged: (status) => {
|
|
238
252
|
this.currentStatus = new SyncStatus({
|
|
@@ -16,6 +16,21 @@ export type SyncStreamOptions = {
|
|
|
16
16
|
abortSignal?: AbortSignal;
|
|
17
17
|
fetchOptions?: Request;
|
|
18
18
|
};
|
|
19
|
+
export declare enum FetchStrategy {
|
|
20
|
+
/**
|
|
21
|
+
* Queues multiple sync events before processing, reducing round-trips.
|
|
22
|
+
* This comes at the cost of more processing overhead, which may cause ACK timeouts on older/weaker devices for big enough datasets.
|
|
23
|
+
*/
|
|
24
|
+
Buffered = "buffered",
|
|
25
|
+
/**
|
|
26
|
+
* Processes each sync event immediately before requesting the next.
|
|
27
|
+
* This reduces processing overhead and improves real-time responsiveness.
|
|
28
|
+
*/
|
|
29
|
+
Sequential = "sequential"
|
|
30
|
+
}
|
|
31
|
+
export type SocketSyncStreamOptions = SyncStreamOptions & {
|
|
32
|
+
fetchStrategy: FetchStrategy;
|
|
33
|
+
};
|
|
19
34
|
export type FetchImplementation = typeof fetch;
|
|
20
35
|
/**
|
|
21
36
|
* Class wrapper for providing a fetch implementation.
|
|
@@ -72,7 +87,7 @@ export declare abstract class AbstractRemote {
|
|
|
72
87
|
/**
|
|
73
88
|
* Connects to the sync/stream websocket endpoint
|
|
74
89
|
*/
|
|
75
|
-
socketStream(options:
|
|
90
|
+
socketStream(options: SocketSyncStreamOptions): Promise<DataStream<StreamingSyncLine>>;
|
|
76
91
|
/**
|
|
77
92
|
* Connects to the sync/stream http endpoint
|
|
78
93
|
*/
|
|
@@ -9,13 +9,25 @@ import { version as POWERSYNC_JS_VERSION } from '../../../../package.json';
|
|
|
9
9
|
const POWERSYNC_TRAILING_SLASH_MATCH = /\/+$/;
|
|
10
10
|
// Refresh at least 30 sec before it expires
|
|
11
11
|
const REFRESH_CREDENTIALS_SAFETY_PERIOD_MS = 30_000;
|
|
12
|
-
const SYNC_QUEUE_REQUEST_N = 10;
|
|
13
12
|
const SYNC_QUEUE_REQUEST_LOW_WATER = 5;
|
|
14
13
|
// Keep alive message is sent every period
|
|
15
14
|
const KEEP_ALIVE_MS = 20_000;
|
|
16
15
|
// The ACK must be received in this period
|
|
17
16
|
const KEEP_ALIVE_LIFETIME_MS = 30_000;
|
|
18
17
|
export const DEFAULT_REMOTE_LOGGER = Logger.get('PowerSyncRemote');
|
|
18
|
+
export var FetchStrategy;
|
|
19
|
+
(function (FetchStrategy) {
|
|
20
|
+
/**
|
|
21
|
+
* Queues multiple sync events before processing, reducing round-trips.
|
|
22
|
+
* This comes at the cost of more processing overhead, which may cause ACK timeouts on older/weaker devices for big enough datasets.
|
|
23
|
+
*/
|
|
24
|
+
FetchStrategy["Buffered"] = "buffered";
|
|
25
|
+
/**
|
|
26
|
+
* Processes each sync event immediately before requesting the next.
|
|
27
|
+
* This reduces processing overhead and improves real-time responsiveness.
|
|
28
|
+
*/
|
|
29
|
+
FetchStrategy["Sequential"] = "sequential";
|
|
30
|
+
})(FetchStrategy || (FetchStrategy = {}));
|
|
19
31
|
/**
|
|
20
32
|
* Class wrapper for providing a fetch implementation.
|
|
21
33
|
* The class wrapper is used to distinguish the fetchImplementation
|
|
@@ -144,7 +156,8 @@ export class AbstractRemote {
|
|
|
144
156
|
* Connects to the sync/stream websocket endpoint
|
|
145
157
|
*/
|
|
146
158
|
async socketStream(options) {
|
|
147
|
-
const { path } = options;
|
|
159
|
+
const { path, fetchStrategy = FetchStrategy.Buffered } = options;
|
|
160
|
+
const syncQueueRequestSize = fetchStrategy == FetchStrategy.Buffered ? 10 : 1;
|
|
148
161
|
const request = await this.buildRequest(path);
|
|
149
162
|
const bson = await this.getBSON();
|
|
150
163
|
// Add the user agent in the setup payload - we can't set custom
|
|
@@ -197,7 +210,7 @@ export class AbstractRemote {
|
|
|
197
210
|
// Helps to prevent double close scenarios
|
|
198
211
|
rsocket.onClose(() => (socketIsClosed = true));
|
|
199
212
|
// We initially request this amount and expect these to arrive eventually
|
|
200
|
-
let pendingEventsCount =
|
|
213
|
+
let pendingEventsCount = syncQueueRequestSize;
|
|
201
214
|
const disposeClosedListener = stream.registerListener({
|
|
202
215
|
closed: () => {
|
|
203
216
|
closeSocket();
|
|
@@ -211,7 +224,7 @@ export class AbstractRemote {
|
|
|
211
224
|
metadata: Buffer.from(bson.serialize({
|
|
212
225
|
path
|
|
213
226
|
}))
|
|
214
|
-
},
|
|
227
|
+
}, syncQueueRequestSize, // The initial N amount
|
|
215
228
|
{
|
|
216
229
|
onError: (e) => {
|
|
217
230
|
// Don't log closed as an error
|
|
@@ -250,10 +263,10 @@ export class AbstractRemote {
|
|
|
250
263
|
const l = stream.registerListener({
|
|
251
264
|
lowWater: async () => {
|
|
252
265
|
// Request to fill up the queue
|
|
253
|
-
const required =
|
|
266
|
+
const required = syncQueueRequestSize - pendingEventsCount;
|
|
254
267
|
if (required > 0) {
|
|
255
|
-
socket.request(
|
|
256
|
-
pendingEventsCount =
|
|
268
|
+
socket.request(syncQueueRequestSize - pendingEventsCount);
|
|
269
|
+
pendingEventsCount = syncQueueRequestSize;
|
|
257
270
|
}
|
|
258
271
|
},
|
|
259
272
|
closed: () => {
|
|
@@ -2,7 +2,7 @@ import Logger, { ILogger } from 'js-logger';
|
|
|
2
2
|
import { SyncStatus, SyncStatusOptions } from '../../../db/crud/SyncStatus.js';
|
|
3
3
|
import { BaseListener, BaseObserver, Disposable } from '../../../utils/BaseObserver.js';
|
|
4
4
|
import { BucketStorageAdapter } from '../bucket/BucketStorageAdapter.js';
|
|
5
|
-
import { AbstractRemote } from './AbstractRemote.js';
|
|
5
|
+
import { AbstractRemote, FetchStrategy } from './AbstractRemote.js';
|
|
6
6
|
import { StreamingSyncRequestParameterType } from './streaming-sync-types.js';
|
|
7
7
|
export declare enum LockType {
|
|
8
8
|
CRUD = "crud",
|
|
@@ -20,10 +20,9 @@ export interface LockOptions<T> {
|
|
|
20
20
|
type: LockType;
|
|
21
21
|
signal?: AbortSignal;
|
|
22
22
|
}
|
|
23
|
-
export interface AbstractStreamingSyncImplementationOptions {
|
|
23
|
+
export interface AbstractStreamingSyncImplementationOptions extends AdditionalConnectionOptions {
|
|
24
24
|
adapter: BucketStorageAdapter;
|
|
25
25
|
uploadCrud: () => Promise<void>;
|
|
26
|
-
crudUploadThrottleMs?: number;
|
|
27
26
|
/**
|
|
28
27
|
* An identifier for which PowerSync DB this sync implementation is
|
|
29
28
|
* linked to. Most commonly DB name, but not restricted to DB name.
|
|
@@ -31,7 +30,6 @@ export interface AbstractStreamingSyncImplementationOptions {
|
|
|
31
30
|
identifier?: string;
|
|
32
31
|
logger?: ILogger;
|
|
33
32
|
remote: AbstractRemote;
|
|
34
|
-
retryDelayMs?: number;
|
|
35
33
|
}
|
|
36
34
|
export interface StreamingSyncImplementationListener extends BaseListener {
|
|
37
35
|
/**
|
|
@@ -48,18 +46,41 @@ export interface StreamingSyncImplementationListener extends BaseListener {
|
|
|
48
46
|
* Configurable options to be used when connecting to the PowerSync
|
|
49
47
|
* backend instance.
|
|
50
48
|
*/
|
|
51
|
-
export interface PowerSyncConnectionOptions {
|
|
49
|
+
export interface PowerSyncConnectionOptions extends BaseConnectionOptions, AdditionalConnectionOptions {
|
|
50
|
+
}
|
|
51
|
+
/** @internal */
|
|
52
|
+
export interface BaseConnectionOptions {
|
|
52
53
|
/**
|
|
53
54
|
* The connection method to use when streaming updates from
|
|
54
55
|
* the PowerSync backend instance.
|
|
55
56
|
* Defaults to a HTTP streaming connection.
|
|
56
57
|
*/
|
|
57
58
|
connectionMethod?: SyncStreamConnectionMethod;
|
|
59
|
+
/**
|
|
60
|
+
* The fetch strategy to use when streaming updates from the PowerSync backend instance.
|
|
61
|
+
*/
|
|
62
|
+
fetchStrategy?: FetchStrategy;
|
|
58
63
|
/**
|
|
59
64
|
* These parameters are passed to the sync rules, and will be available under the`user_parameters` object.
|
|
60
65
|
*/
|
|
61
66
|
params?: Record<string, StreamingSyncRequestParameterType>;
|
|
62
67
|
}
|
|
68
|
+
/** @internal */
|
|
69
|
+
export interface AdditionalConnectionOptions {
|
|
70
|
+
/**
|
|
71
|
+
* Delay for retrying sync streaming operations
|
|
72
|
+
* from the PowerSync backend after an error occurs.
|
|
73
|
+
*/
|
|
74
|
+
retryDelayMs?: number;
|
|
75
|
+
/**
|
|
76
|
+
* Backend Connector CRUD operations are throttled
|
|
77
|
+
* to occur at most every `crudUploadThrottleMs`
|
|
78
|
+
* milliseconds.
|
|
79
|
+
*/
|
|
80
|
+
crudUploadThrottleMs?: number;
|
|
81
|
+
}
|
|
82
|
+
/** @internal */
|
|
83
|
+
export type RequiredAdditionalConnectionOptions = Required<AdditionalConnectionOptions>;
|
|
63
84
|
export interface StreamingSyncImplementation extends BaseObserver<StreamingSyncImplementationListener>, Disposable {
|
|
64
85
|
/**
|
|
65
86
|
* Connects to the sync service
|
|
@@ -80,12 +101,14 @@ export interface StreamingSyncImplementation extends BaseObserver<StreamingSyncI
|
|
|
80
101
|
waitForStatus(status: SyncStatusOptions): Promise<void>;
|
|
81
102
|
}
|
|
82
103
|
export declare const DEFAULT_CRUD_UPLOAD_THROTTLE_MS = 1000;
|
|
104
|
+
export declare const DEFAULT_RETRY_DELAY_MS = 5000;
|
|
83
105
|
export declare const DEFAULT_STREAMING_SYNC_OPTIONS: {
|
|
84
106
|
retryDelayMs: number;
|
|
85
107
|
logger: Logger.ILogger;
|
|
86
108
|
crudUploadThrottleMs: number;
|
|
87
109
|
};
|
|
88
|
-
export
|
|
110
|
+
export type RequiredPowerSyncConnectionOptions = Required<BaseConnectionOptions>;
|
|
111
|
+
export declare const DEFAULT_STREAM_CONNECTION_OPTIONS: RequiredPowerSyncConnectionOptions;
|
|
89
112
|
export declare abstract class AbstractStreamingSyncImplementation extends BaseObserver<StreamingSyncImplementationListener> implements StreamingSyncImplementation {
|
|
90
113
|
protected _lastSyncedAt: Date | null;
|
|
91
114
|
protected options: AbstractStreamingSyncImplementationOptions;
|
|
@@ -4,6 +4,7 @@ import { AbortOperation } from '../../../utils/AbortOperation.js';
|
|
|
4
4
|
import { BaseObserver } from '../../../utils/BaseObserver.js';
|
|
5
5
|
import { throttleLeadingTrailing } from '../../../utils/throttle.js';
|
|
6
6
|
import { SyncDataBucket } from '../bucket/SyncDataBucket.js';
|
|
7
|
+
import { FetchStrategy } from './AbstractRemote.js';
|
|
7
8
|
import { isStreamingKeepalive, isStreamingSyncCheckpoint, isStreamingSyncCheckpointComplete, isStreamingSyncCheckpointDiff, isStreamingSyncData } from './streaming-sync-types.js';
|
|
8
9
|
export var LockType;
|
|
9
10
|
(function (LockType) {
|
|
@@ -16,13 +17,15 @@ export var SyncStreamConnectionMethod;
|
|
|
16
17
|
SyncStreamConnectionMethod["WEB_SOCKET"] = "web-socket";
|
|
17
18
|
})(SyncStreamConnectionMethod || (SyncStreamConnectionMethod = {}));
|
|
18
19
|
export const DEFAULT_CRUD_UPLOAD_THROTTLE_MS = 1000;
|
|
20
|
+
export const DEFAULT_RETRY_DELAY_MS = 5000;
|
|
19
21
|
export const DEFAULT_STREAMING_SYNC_OPTIONS = {
|
|
20
|
-
retryDelayMs:
|
|
22
|
+
retryDelayMs: DEFAULT_RETRY_DELAY_MS,
|
|
21
23
|
logger: Logger.get('PowerSyncStream'),
|
|
22
24
|
crudUploadThrottleMs: DEFAULT_CRUD_UPLOAD_THROTTLE_MS
|
|
23
25
|
};
|
|
24
26
|
export const DEFAULT_STREAM_CONNECTION_OPTIONS = {
|
|
25
27
|
connectionMethod: SyncStreamConnectionMethod.WEB_SOCKET,
|
|
28
|
+
fetchStrategy: FetchStrategy.Buffered,
|
|
26
29
|
params: {}
|
|
27
30
|
};
|
|
28
31
|
export class AbstractStreamingSyncImplementation extends BaseObserver {
|
|
@@ -38,6 +41,7 @@ export class AbstractStreamingSyncImplementation extends BaseObserver {
|
|
|
38
41
|
this.options = { ...DEFAULT_STREAMING_SYNC_OPTIONS, ...options };
|
|
39
42
|
this.syncStatus = new SyncStatus({
|
|
40
43
|
connected: false,
|
|
44
|
+
connecting: false,
|
|
41
45
|
lastSyncedAt: undefined,
|
|
42
46
|
dataFlow: {
|
|
43
47
|
uploading: false,
|
|
@@ -207,7 +211,7 @@ The next upload iteration will be delayed.`);
|
|
|
207
211
|
}
|
|
208
212
|
this.streamingSyncPromise = undefined;
|
|
209
213
|
this.abortController = null;
|
|
210
|
-
this.updateSyncStatus({ connected: false });
|
|
214
|
+
this.updateSyncStatus({ connected: false, connecting: false });
|
|
211
215
|
}
|
|
212
216
|
/**
|
|
213
217
|
* @deprecated use [connect instead]
|
|
@@ -238,6 +242,7 @@ The next upload iteration will be delayed.`);
|
|
|
238
242
|
this.crudUpdateListener = undefined;
|
|
239
243
|
this.updateSyncStatus({
|
|
240
244
|
connected: false,
|
|
245
|
+
connecting: false,
|
|
241
246
|
dataFlow: {
|
|
242
247
|
downloading: false
|
|
243
248
|
}
|
|
@@ -250,6 +255,7 @@ The next upload iteration will be delayed.`);
|
|
|
250
255
|
* - Close any sync stream ReadableStreams (which will also close any established network requests)
|
|
251
256
|
*/
|
|
252
257
|
while (true) {
|
|
258
|
+
this.updateSyncStatus({ connecting: true });
|
|
253
259
|
try {
|
|
254
260
|
if (signal?.aborted) {
|
|
255
261
|
break;
|
|
@@ -280,6 +286,7 @@ The next upload iteration will be delayed.`);
|
|
|
280
286
|
else {
|
|
281
287
|
this.logger.error(ex);
|
|
282
288
|
}
|
|
289
|
+
// On error, wait a little before retrying
|
|
283
290
|
await this.delayRetry();
|
|
284
291
|
}
|
|
285
292
|
finally {
|
|
@@ -288,13 +295,13 @@ The next upload iteration will be delayed.`);
|
|
|
288
295
|
nestedAbortController = new AbortController();
|
|
289
296
|
}
|
|
290
297
|
this.updateSyncStatus({
|
|
291
|
-
connected: false
|
|
298
|
+
connected: false,
|
|
299
|
+
connecting: true // May be unnecessary
|
|
292
300
|
});
|
|
293
|
-
// On error, wait a little before retrying
|
|
294
301
|
}
|
|
295
302
|
}
|
|
296
303
|
// Mark as disconnected if here
|
|
297
|
-
this.updateSyncStatus({ connected: false });
|
|
304
|
+
this.updateSyncStatus({ connected: false, connecting: false });
|
|
298
305
|
}
|
|
299
306
|
async streamingSyncIteration(signal, options) {
|
|
300
307
|
return await this.obtainLock({
|
|
@@ -334,9 +341,16 @@ The next upload iteration will be delayed.`);
|
|
|
334
341
|
client_id: clientId
|
|
335
342
|
}
|
|
336
343
|
};
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
344
|
+
let stream;
|
|
345
|
+
if (resolvedOptions?.connectionMethod == SyncStreamConnectionMethod.HTTP) {
|
|
346
|
+
stream = await this.options.remote.postStream(syncOptions);
|
|
347
|
+
}
|
|
348
|
+
else {
|
|
349
|
+
stream = await this.options.remote.socketStream({
|
|
350
|
+
...syncOptions,
|
|
351
|
+
...{ fetchStrategy: resolvedOptions.fetchStrategy }
|
|
352
|
+
});
|
|
353
|
+
}
|
|
340
354
|
this.logger.debug('Stream established. Processing events');
|
|
341
355
|
while (!stream.closed) {
|
|
342
356
|
const line = await stream.read();
|
|
@@ -489,6 +503,7 @@ The next upload iteration will be delayed.`);
|
|
|
489
503
|
updateSyncStatus(options) {
|
|
490
504
|
const updatedStatus = new SyncStatus({
|
|
491
505
|
connected: options.connected ?? this.syncStatus.connected,
|
|
506
|
+
connecting: !options.connected && (options.connecting ?? this.syncStatus.connecting),
|
|
492
507
|
lastSyncedAt: options.lastSyncedAt ?? this.syncStatus.lastSyncedAt,
|
|
493
508
|
dataFlow: {
|
|
494
509
|
...this.syncStatus.dataFlowStatus,
|
|
@@ -4,6 +4,7 @@ export type SyncDataFlowStatus = Partial<{
|
|
|
4
4
|
}>;
|
|
5
5
|
export type SyncStatusOptions = {
|
|
6
6
|
connected?: boolean;
|
|
7
|
+
connecting?: boolean;
|
|
7
8
|
dataFlow?: SyncDataFlowStatus;
|
|
8
9
|
lastSyncedAt?: Date;
|
|
9
10
|
hasSynced?: boolean;
|
|
@@ -15,6 +16,7 @@ export declare class SyncStatus {
|
|
|
15
16
|
* true if currently connected.
|
|
16
17
|
*/
|
|
17
18
|
get connected(): boolean;
|
|
19
|
+
get connecting(): boolean;
|
|
18
20
|
/**
|
|
19
21
|
* Time that a last sync has fully completed, if any.
|
|
20
22
|
* Currently this is reset to null after a restart.
|
|
@@ -9,6 +9,9 @@ export class SyncStatus {
|
|
|
9
9
|
get connected() {
|
|
10
10
|
return this.options.connected ?? false;
|
|
11
11
|
}
|
|
12
|
+
get connecting() {
|
|
13
|
+
return this.options.connecting ?? false;
|
|
14
|
+
}
|
|
12
15
|
/**
|
|
13
16
|
* Time that a last sync has fully completed, if any.
|
|
14
17
|
* Currently this is reset to null after a restart.
|
|
@@ -44,11 +47,12 @@ export class SyncStatus {
|
|
|
44
47
|
}
|
|
45
48
|
getMessage() {
|
|
46
49
|
const dataFlow = this.dataFlowStatus;
|
|
47
|
-
return `SyncStatus<connected: ${this.connected} lastSyncedAt: ${this.lastSyncedAt} hasSynced: ${this.hasSynced}. Downloading: ${dataFlow.downloading}. Uploading: ${dataFlow.uploading}`;
|
|
50
|
+
return `SyncStatus<connected: ${this.connected} connecting: ${this.connecting} lastSyncedAt: ${this.lastSyncedAt} hasSynced: ${this.hasSynced}. Downloading: ${dataFlow.downloading}. Uploading: ${dataFlow.uploading}`;
|
|
48
51
|
}
|
|
49
52
|
toJSON() {
|
|
50
53
|
return {
|
|
51
54
|
connected: this.connected,
|
|
55
|
+
connecting: this.connecting,
|
|
52
56
|
dataFlow: this.dataFlowStatus,
|
|
53
57
|
lastSyncedAt: this.lastSyncedAt,
|
|
54
58
|
hasSynced: this.hasSynced
|