@aws-amplify/datastore 3.14.1-unstable.2 → 3.14.1
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/CHANGELOG.md +12 -0
- package/dist/aws-amplify-datastore.js +2798 -1458
- package/dist/aws-amplify-datastore.js.map +1 -1
- package/dist/aws-amplify-datastore.min.js +10 -10
- package/dist/aws-amplify-datastore.min.js.map +1 -1
- package/lib/authModeStrategies/multiAuthStrategy.js +11 -0
- package/lib/authModeStrategies/multiAuthStrategy.js.map +1 -1
- package/lib/datastore/datastore.js +524 -323
- package/lib/datastore/datastore.js.map +1 -1
- package/lib/storage/adapter/IndexedDBAdapter.js +76 -25
- package/lib/storage/adapter/IndexedDBAdapter.js.map +1 -1
- package/lib/storage/storage.js +2 -2
- package/lib/storage/storage.js.map +1 -1
- package/lib/sync/datastoreConnectivity.js +45 -0
- package/lib/sync/datastoreConnectivity.js.map +1 -1
- package/lib/sync/index.js +518 -395
- package/lib/sync/index.js.map +1 -1
- package/lib/sync/merger.js +6 -0
- package/lib/sync/merger.js.map +1 -1
- package/lib/sync/outbox.js +66 -62
- package/lib/sync/outbox.js.map +1 -1
- package/lib/sync/processors/mutation.js +207 -165
- package/lib/sync/processors/mutation.js.map +1 -1
- package/lib/sync/processors/subscription.js +210 -175
- package/lib/sync/processors/subscription.js.map +1 -1
- package/lib/sync/processors/sync.js +95 -72
- package/lib/sync/processors/sync.js.map +1 -1
- package/lib/sync/utils.js +1 -3
- package/lib/sync/utils.js.map +1 -1
- package/lib/util.js +89 -0
- package/lib/util.js.map +1 -1
- package/lib-esm/authModeStrategies/multiAuthStrategy.d.ts +11 -0
- package/lib-esm/authModeStrategies/multiAuthStrategy.js +11 -0
- package/lib-esm/authModeStrategies/multiAuthStrategy.js.map +1 -1
- package/lib-esm/datastore/datastore.d.ts +95 -2
- package/lib-esm/datastore/datastore.js +524 -323
- package/lib-esm/datastore/datastore.js.map +1 -1
- package/lib-esm/storage/adapter/IndexedDBAdapter.d.ts +21 -0
- package/lib-esm/storage/adapter/IndexedDBAdapter.js +77 -26
- package/lib-esm/storage/adapter/IndexedDBAdapter.js.map +1 -1
- package/lib-esm/storage/storage.js +2 -2
- package/lib-esm/storage/storage.js.map +1 -1
- package/lib-esm/sync/datastoreConnectivity.d.ts +1 -0
- package/lib-esm/sync/datastoreConnectivity.js +45 -0
- package/lib-esm/sync/datastoreConnectivity.js.map +1 -1
- package/lib-esm/sync/index.d.ts +9 -1
- package/lib-esm/sync/index.js +519 -396
- package/lib-esm/sync/index.js.map +1 -1
- package/lib-esm/sync/merger.d.ts +6 -0
- package/lib-esm/sync/merger.js +6 -0
- package/lib-esm/sync/merger.js.map +1 -1
- package/lib-esm/sync/outbox.js +66 -62
- package/lib-esm/sync/outbox.js.map +1 -1
- package/lib-esm/sync/processors/mutation.d.ts +2 -0
- package/lib-esm/sync/processors/mutation.js +208 -166
- package/lib-esm/sync/processors/mutation.js.map +1 -1
- package/lib-esm/sync/processors/subscription.d.ts +2 -0
- package/lib-esm/sync/processors/subscription.js +211 -176
- package/lib-esm/sync/processors/subscription.js.map +1 -1
- package/lib-esm/sync/processors/sync.d.ts +2 -0
- package/lib-esm/sync/processors/sync.js +96 -73
- package/lib-esm/sync/processors/sync.js.map +1 -1
- package/lib-esm/sync/utils.js +1 -3
- package/lib-esm/sync/utils.js.map +1 -1
- package/lib-esm/util.d.ts +11 -0
- package/lib-esm/util.js +89 -0
- package/lib-esm/util.js.map +1 -1
- package/package.json +7 -7
- package/src/authModeStrategies/multiAuthStrategy.ts +11 -0
- package/src/datastore/datastore.ts +572 -366
- package/src/storage/adapter/IndexedDBAdapter.ts +50 -9
- package/src/storage/storage.ts +2 -2
- package/src/sync/datastoreConnectivity.ts +6 -0
- package/src/sync/index.ts +492 -400
- package/src/sync/merger.ts +6 -0
- package/src/sync/outbox.ts +1 -1
- package/src/sync/processors/mutation.ts +139 -104
- package/src/sync/processors/subscription.ts +287 -250
- package/src/sync/processors/sync.ts +88 -60
- package/src/sync/utils.ts +1 -3
- package/src/util.ts +92 -2
- package/lib/authModeStrategies/defaultAuthStrategy.d.ts +0 -2
- package/lib/authModeStrategies/index.d.ts +0 -2
- package/lib/authModeStrategies/multiAuthStrategy.d.ts +0 -2
- package/lib/datastore/datastore.d.ts +0 -63
- package/lib/index.d.ts +0 -15
- package/lib/predicates/index.d.ts +0 -16
- package/lib/predicates/sort.d.ts +0 -8
- package/lib/ssr/index.d.ts +0 -3
- package/lib/storage/adapter/AsyncStorageAdapter.d.ts +0 -41
- package/lib/storage/adapter/AsyncStorageDatabase.d.ts +0 -39
- package/lib/storage/adapter/InMemoryStore.d.ts +0 -11
- package/lib/storage/adapter/InMemoryStore.native.d.ts +0 -1
- package/lib/storage/adapter/IndexedDBAdapter.d.ts +0 -38
- package/lib/storage/adapter/getDefaultAdapter/index.d.ts +0 -3
- package/lib/storage/adapter/getDefaultAdapter/index.native.d.ts +0 -3
- package/lib/storage/adapter/index.d.ts +0 -9
- package/lib/storage/storage.d.ts +0 -49
- package/lib/sync/datastoreConnectivity.d.ts +0 -15
- package/lib/sync/datastoreReachability/index.d.ts +0 -3
- package/lib/sync/datastoreReachability/index.native.d.ts +0 -3
- package/lib/sync/index.d.ts +0 -81
- package/lib/sync/merger.d.ts +0 -11
- package/lib/sync/outbox.d.ts +0 -27
- package/lib/sync/processors/errorMaps.d.ts +0 -17
- package/lib/sync/processors/mutation.d.ts +0 -56
- package/lib/sync/processors/subscription.d.ts +0 -31
- package/lib/sync/processors/sync.d.ts +0 -26
- package/lib/sync/utils.d.ts +0 -42
- package/lib/types.d.ts +0 -501
- package/lib/util.d.ts +0 -145
package/src/sync/index.ts
CHANGED
|
@@ -1,4 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
browserOrNode,
|
|
3
|
+
ConsoleLogger as Logger,
|
|
4
|
+
BackgroundProcessManager,
|
|
5
|
+
} from '@aws-amplify/core';
|
|
2
6
|
import { CONTROL_MSG as PUBSUB_CONTROL_MSG } from '@aws-amplify/pubsub';
|
|
3
7
|
import Observable, { ZenObservable } from 'zen-observable-ts';
|
|
4
8
|
import { ModelInstanceCreator } from '../datastore/datastore';
|
|
@@ -113,6 +117,8 @@ export class SyncEngine {
|
|
|
113
117
|
boolean
|
|
114
118
|
> = new WeakMap();
|
|
115
119
|
|
|
120
|
+
private runningProcesses: BackgroundProcessManager;
|
|
121
|
+
|
|
116
122
|
public getModelSyncedStatus(
|
|
117
123
|
modelConstructor: PersistentModelConstructor<any>
|
|
118
124
|
): boolean {
|
|
@@ -131,8 +137,11 @@ export class SyncEngine {
|
|
|
131
137
|
private readonly syncPredicates: WeakMap<SchemaModel, ModelPredicate<any>>,
|
|
132
138
|
private readonly amplifyConfig: Record<string, any> = {},
|
|
133
139
|
private readonly authModeStrategy: AuthModeStrategy,
|
|
134
|
-
private readonly amplifyContext: AmplifyContext
|
|
140
|
+
private readonly amplifyContext: AmplifyContext,
|
|
141
|
+
private readonly connectivityMonitor?: DataStoreConnectivity
|
|
135
142
|
) {
|
|
143
|
+
this.runningProcesses = new BackgroundProcessManager();
|
|
144
|
+
|
|
136
145
|
const MutationEvent = this.modelClasses[
|
|
137
146
|
'MutationEvent'
|
|
138
147
|
] as PersistentModelConstructor<MutationEvent>;
|
|
@@ -178,7 +187,8 @@ export class SyncEngine {
|
|
|
178
187
|
this.amplifyContext
|
|
179
188
|
);
|
|
180
189
|
|
|
181
|
-
this.datastoreConnectivity =
|
|
190
|
+
this.datastoreConnectivity =
|
|
191
|
+
this.connectivityMonitor || new DataStoreConnectivity();
|
|
182
192
|
}
|
|
183
193
|
|
|
184
194
|
start(params: StartParams) {
|
|
@@ -187,7 +197,7 @@ export class SyncEngine {
|
|
|
187
197
|
|
|
188
198
|
let subscriptions: ZenObservable.Subscription[] = [];
|
|
189
199
|
|
|
190
|
-
(async () => {
|
|
200
|
+
this.runningProcesses.add(async () => {
|
|
191
201
|
try {
|
|
192
202
|
await this.setupModels(params);
|
|
193
203
|
} catch (err) {
|
|
@@ -195,179 +205,204 @@ export class SyncEngine {
|
|
|
195
205
|
return;
|
|
196
206
|
}
|
|
197
207
|
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
>;
|
|
215
|
-
|
|
216
|
-
if (isNode) {
|
|
217
|
-
logger.warn(
|
|
218
|
-
'Realtime disabled when in a server-side environment'
|
|
219
|
-
);
|
|
220
|
-
} else {
|
|
221
|
-
//#region GraphQL Subscriptions
|
|
222
|
-
[
|
|
223
|
-
// const ctlObservable: Observable<CONTROL_MSG>
|
|
224
|
-
ctlSubsObservable,
|
|
225
|
-
// const dataObservable: Observable<[TransformerMutationType, SchemaModel, Readonly<{
|
|
226
|
-
// id: string;
|
|
227
|
-
// } & Record<string, any>>]>
|
|
228
|
-
dataSubsObservable,
|
|
229
|
-
] = this.subscriptionsProcessor.start();
|
|
230
|
-
|
|
231
|
-
try {
|
|
232
|
-
await new Promise((resolve, reject) => {
|
|
233
|
-
const ctlSubsSubscription = ctlSubsObservable.subscribe({
|
|
234
|
-
next: msg => {
|
|
235
|
-
if (msg === CONTROL_MSG.CONNECTED) {
|
|
236
|
-
resolve();
|
|
237
|
-
}
|
|
238
|
-
},
|
|
239
|
-
error: err => {
|
|
240
|
-
reject(err);
|
|
241
|
-
const handleDisconnect = this.disconnectionHandler();
|
|
242
|
-
handleDisconnect(err);
|
|
243
|
-
},
|
|
244
|
-
});
|
|
245
|
-
|
|
246
|
-
subscriptions.push(ctlSubsSubscription);
|
|
208
|
+
// this is awaited at the bottom. so, we don't need to register
|
|
209
|
+
// this explicitly with the context. it's already contained.
|
|
210
|
+
const startPromise = new Promise((doneStarting, failedStarting) => {
|
|
211
|
+
this.datastoreConnectivity.status().subscribe(
|
|
212
|
+
async ({ online }) =>
|
|
213
|
+
this.runningProcesses.isOpen &&
|
|
214
|
+
this.runningProcesses.add(async onTerminate => {
|
|
215
|
+
// From offline to online
|
|
216
|
+
if (online && !this.online) {
|
|
217
|
+
this.online = online;
|
|
218
|
+
|
|
219
|
+
observer.next({
|
|
220
|
+
type: ControlMessage.SYNC_ENGINE_NETWORK_STATUS,
|
|
221
|
+
data: {
|
|
222
|
+
active: this.online,
|
|
223
|
+
},
|
|
247
224
|
});
|
|
248
|
-
} catch (err) {
|
|
249
|
-
observer.error(err);
|
|
250
|
-
return;
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
logger.log('Realtime ready');
|
|
254
|
-
|
|
255
|
-
observer.next({
|
|
256
|
-
type: ControlMessage.SYNC_ENGINE_SUBSCRIPTIONS_ESTABLISHED,
|
|
257
|
-
});
|
|
258
|
-
|
|
259
|
-
//#endregion
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
//#region Base & Sync queries
|
|
263
|
-
try {
|
|
264
|
-
await new Promise((resolve, reject) => {
|
|
265
|
-
const syncQuerySubscription =
|
|
266
|
-
this.syncQueriesObservable().subscribe({
|
|
267
|
-
next: message => {
|
|
268
|
-
const { type } = message;
|
|
269
|
-
|
|
270
|
-
if (
|
|
271
|
-
type === ControlMessage.SYNC_ENGINE_SYNC_QUERIES_READY
|
|
272
|
-
) {
|
|
273
|
-
resolve();
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
observer.next(message);
|
|
277
|
-
},
|
|
278
|
-
complete: () => {
|
|
279
|
-
resolve();
|
|
280
|
-
},
|
|
281
|
-
error: error => {
|
|
282
|
-
reject(error);
|
|
283
|
-
},
|
|
284
|
-
});
|
|
285
|
-
|
|
286
|
-
if (syncQuerySubscription) {
|
|
287
|
-
subscriptions.push(syncQuerySubscription);
|
|
288
|
-
}
|
|
289
|
-
});
|
|
290
|
-
} catch (error) {
|
|
291
|
-
observer.error(error);
|
|
292
|
-
return;
|
|
293
|
-
}
|
|
294
|
-
//#endregion
|
|
295
225
|
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
.subscribe(({ modelDefinition, model: item, hasMore }) => {
|
|
301
|
-
const modelConstructor = this.userModelClasses[
|
|
302
|
-
modelDefinition.name
|
|
303
|
-
] as PersistentModelConstructor<any>;
|
|
304
|
-
|
|
305
|
-
const model = this.modelInstanceCreator(
|
|
306
|
-
modelConstructor,
|
|
307
|
-
item
|
|
308
|
-
);
|
|
226
|
+
let ctlSubsObservable: Observable<CONTROL_MSG>;
|
|
227
|
+
let dataSubsObservable: Observable<
|
|
228
|
+
[TransformerMutationType, SchemaModel, PersistentModel]
|
|
229
|
+
>;
|
|
309
230
|
|
|
310
|
-
|
|
311
|
-
|
|
231
|
+
// NOTE: need a way to override this conditional for testing.
|
|
232
|
+
if (isNode) {
|
|
233
|
+
logger.warn(
|
|
234
|
+
'Realtime disabled when in a server-side environment'
|
|
312
235
|
);
|
|
236
|
+
} else {
|
|
237
|
+
//#region GraphQL Subscriptions
|
|
238
|
+
[
|
|
239
|
+
// const ctlObservable: Observable<CONTROL_MSG>
|
|
240
|
+
ctlSubsObservable,
|
|
241
|
+
// const dataObservable: Observable<[TransformerMutationType, SchemaModel, Readonly<{
|
|
242
|
+
// id: string;
|
|
243
|
+
// } & Record<string, any>>]>
|
|
244
|
+
dataSubsObservable,
|
|
245
|
+
] = this.subscriptionsProcessor.start();
|
|
246
|
+
|
|
247
|
+
try {
|
|
248
|
+
await new Promise((resolve, reject) => {
|
|
249
|
+
onTerminate.then(reject);
|
|
250
|
+
const ctlSubsSubscription = ctlSubsObservable.subscribe(
|
|
251
|
+
{
|
|
252
|
+
next: msg => {
|
|
253
|
+
if (msg === CONTROL_MSG.CONNECTED) {
|
|
254
|
+
resolve();
|
|
255
|
+
}
|
|
256
|
+
},
|
|
257
|
+
error: err => {
|
|
258
|
+
reject(err);
|
|
259
|
+
const handleDisconnect =
|
|
260
|
+
this.disconnectionHandler();
|
|
261
|
+
handleDisconnect(err);
|
|
262
|
+
},
|
|
263
|
+
}
|
|
264
|
+
);
|
|
265
|
+
|
|
266
|
+
subscriptions.push(ctlSubsSubscription);
|
|
267
|
+
});
|
|
268
|
+
} catch (err) {
|
|
269
|
+
observer.error(err);
|
|
270
|
+
failedStarting();
|
|
271
|
+
return;
|
|
272
|
+
}
|
|
313
273
|
|
|
314
|
-
|
|
315
|
-
type: ControlMessage.SYNC_ENGINE_OUTBOX_MUTATION_PROCESSED,
|
|
316
|
-
data: {
|
|
317
|
-
model: modelConstructor,
|
|
318
|
-
element: model,
|
|
319
|
-
},
|
|
320
|
-
});
|
|
274
|
+
logger.log('Realtime ready');
|
|
321
275
|
|
|
322
276
|
observer.next({
|
|
323
|
-
type: ControlMessage.
|
|
324
|
-
data: {
|
|
325
|
-
isEmpty: !hasMore,
|
|
326
|
-
},
|
|
277
|
+
type: ControlMessage.SYNC_ENGINE_SUBSCRIPTIONS_ESTABLISHED,
|
|
327
278
|
});
|
|
328
|
-
})
|
|
329
|
-
);
|
|
330
|
-
//#endregion
|
|
331
|
-
|
|
332
|
-
//#region Merge subscriptions buffer
|
|
333
|
-
// TODO: extract to function
|
|
334
|
-
if (!isNode) {
|
|
335
|
-
subscriptions.push(
|
|
336
|
-
dataSubsObservable.subscribe(
|
|
337
|
-
([_transformerMutationType, modelDefinition, item]) => {
|
|
338
|
-
const modelConstructor = this.userModelClasses[
|
|
339
|
-
modelDefinition.name
|
|
340
|
-
] as PersistentModelConstructor<any>;
|
|
341
|
-
|
|
342
|
-
const model = this.modelInstanceCreator(
|
|
343
|
-
modelConstructor,
|
|
344
|
-
item
|
|
345
|
-
);
|
|
346
279
|
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
);
|
|
350
|
-
}
|
|
351
|
-
)
|
|
352
|
-
);
|
|
353
|
-
}
|
|
354
|
-
//#endregion
|
|
355
|
-
} else if (!online) {
|
|
356
|
-
this.online = online;
|
|
280
|
+
//#endregion
|
|
281
|
+
}
|
|
357
282
|
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
283
|
+
//#region Base & Sync queries
|
|
284
|
+
try {
|
|
285
|
+
await new Promise((resolve, reject) => {
|
|
286
|
+
const syncQuerySubscription =
|
|
287
|
+
this.syncQueriesObservable().subscribe({
|
|
288
|
+
next: message => {
|
|
289
|
+
const { type } = message;
|
|
290
|
+
|
|
291
|
+
if (
|
|
292
|
+
type ===
|
|
293
|
+
ControlMessage.SYNC_ENGINE_SYNC_QUERIES_READY
|
|
294
|
+
) {
|
|
295
|
+
resolve();
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
observer.next(message);
|
|
299
|
+
},
|
|
300
|
+
complete: () => {
|
|
301
|
+
resolve();
|
|
302
|
+
},
|
|
303
|
+
error: error => {
|
|
304
|
+
reject(error);
|
|
305
|
+
},
|
|
306
|
+
});
|
|
307
|
+
|
|
308
|
+
if (syncQuerySubscription) {
|
|
309
|
+
subscriptions.push(syncQuerySubscription);
|
|
310
|
+
}
|
|
311
|
+
});
|
|
312
|
+
} catch (error) {
|
|
313
|
+
observer.error(error);
|
|
314
|
+
failedStarting();
|
|
315
|
+
return;
|
|
316
|
+
}
|
|
317
|
+
//#endregion
|
|
318
|
+
|
|
319
|
+
//#region process mutations (outbox)
|
|
320
|
+
subscriptions.push(
|
|
321
|
+
this.mutationsProcessor
|
|
322
|
+
.start()
|
|
323
|
+
.subscribe(({ modelDefinition, model: item, hasMore }) =>
|
|
324
|
+
this.runningProcesses.add(async () => {
|
|
325
|
+
const modelConstructor = this.userModelClasses[
|
|
326
|
+
modelDefinition.name
|
|
327
|
+
] as PersistentModelConstructor<any>;
|
|
328
|
+
|
|
329
|
+
const model = this.modelInstanceCreator(
|
|
330
|
+
modelConstructor,
|
|
331
|
+
item
|
|
332
|
+
);
|
|
333
|
+
|
|
334
|
+
await this.storage.runExclusive(storage =>
|
|
335
|
+
this.modelMerger.merge(
|
|
336
|
+
storage,
|
|
337
|
+
model,
|
|
338
|
+
modelDefinition
|
|
339
|
+
)
|
|
340
|
+
);
|
|
341
|
+
|
|
342
|
+
observer.next({
|
|
343
|
+
type: ControlMessage.SYNC_ENGINE_OUTBOX_MUTATION_PROCESSED,
|
|
344
|
+
data: {
|
|
345
|
+
model: modelConstructor,
|
|
346
|
+
element: model,
|
|
347
|
+
},
|
|
348
|
+
});
|
|
349
|
+
|
|
350
|
+
observer.next({
|
|
351
|
+
type: ControlMessage.SYNC_ENGINE_OUTBOX_STATUS,
|
|
352
|
+
data: {
|
|
353
|
+
isEmpty: !hasMore,
|
|
354
|
+
},
|
|
355
|
+
});
|
|
356
|
+
}, 'mutation processor event')
|
|
357
|
+
)
|
|
358
|
+
);
|
|
359
|
+
//#endregion
|
|
360
|
+
|
|
361
|
+
//#region Merge subscriptions buffer
|
|
362
|
+
// TODO: extract to function
|
|
363
|
+
if (!isNode) {
|
|
364
|
+
subscriptions.push(
|
|
365
|
+
dataSubsObservable.subscribe(
|
|
366
|
+
([_transformerMutationType, modelDefinition, item]) =>
|
|
367
|
+
this.runningProcesses.add(async () => {
|
|
368
|
+
const modelConstructor = this.userModelClasses[
|
|
369
|
+
modelDefinition.name
|
|
370
|
+
] as PersistentModelConstructor<any>;
|
|
371
|
+
|
|
372
|
+
const model = this.modelInstanceCreator(
|
|
373
|
+
modelConstructor,
|
|
374
|
+
item
|
|
375
|
+
);
|
|
376
|
+
|
|
377
|
+
await this.storage.runExclusive(storage =>
|
|
378
|
+
this.modelMerger.merge(
|
|
379
|
+
storage,
|
|
380
|
+
model,
|
|
381
|
+
modelDefinition
|
|
382
|
+
)
|
|
383
|
+
);
|
|
384
|
+
}, 'subscription dataSubsObservable event')
|
|
385
|
+
)
|
|
386
|
+
);
|
|
387
|
+
}
|
|
388
|
+
//#endregion
|
|
389
|
+
} else if (!online) {
|
|
390
|
+
this.online = online;
|
|
391
|
+
|
|
392
|
+
observer.next({
|
|
393
|
+
type: ControlMessage.SYNC_ENGINE_NETWORK_STATUS,
|
|
394
|
+
data: {
|
|
395
|
+
active: this.online,
|
|
396
|
+
},
|
|
397
|
+
});
|
|
364
398
|
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
399
|
+
subscriptions.forEach(sub => sub.unsubscribe());
|
|
400
|
+
subscriptions = [];
|
|
401
|
+
}
|
|
368
402
|
|
|
369
|
-
|
|
370
|
-
|
|
403
|
+
doneStarting();
|
|
404
|
+
}, 'datastore connectivity event')
|
|
405
|
+
);
|
|
371
406
|
});
|
|
372
407
|
|
|
373
408
|
this.storage
|
|
@@ -377,51 +412,52 @@ export class SyncEngine {
|
|
|
377
412
|
return modelDefinition.syncable === true;
|
|
378
413
|
})
|
|
379
414
|
.subscribe({
|
|
380
|
-
next: async ({ opType, model, element, condition }) =>
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
element,
|
|
397
|
-
graphQLCondition,
|
|
398
|
-
MutationEventConstructor,
|
|
399
|
-
this.modelInstanceCreator
|
|
400
|
-
);
|
|
401
|
-
|
|
402
|
-
await this.outbox.enqueue(this.storage, mutationEvent);
|
|
403
|
-
|
|
404
|
-
observer.next({
|
|
405
|
-
type: ControlMessage.SYNC_ENGINE_OUTBOX_MUTATION_ENQUEUED,
|
|
406
|
-
data: {
|
|
415
|
+
next: async ({ opType, model, element, condition }) =>
|
|
416
|
+
this.runningProcesses.add(async () => {
|
|
417
|
+
const namespace =
|
|
418
|
+
this.schema.namespaces[this.namespaceResolver(model)];
|
|
419
|
+
const MutationEventConstructor = this.modelClasses[
|
|
420
|
+
'MutationEvent'
|
|
421
|
+
] as PersistentModelConstructor<MutationEvent>;
|
|
422
|
+
const modelDefinition = this.getModelDefinition(model);
|
|
423
|
+
const graphQLCondition = predicateToGraphQLCondition(
|
|
424
|
+
condition,
|
|
425
|
+
modelDefinition
|
|
426
|
+
);
|
|
427
|
+
const mutationEvent = createMutationInstanceFromModelOperation(
|
|
428
|
+
namespace.relationships,
|
|
429
|
+
this.getModelDefinition(model),
|
|
430
|
+
opType,
|
|
407
431
|
model,
|
|
408
432
|
element,
|
|
409
|
-
|
|
410
|
-
|
|
433
|
+
graphQLCondition,
|
|
434
|
+
MutationEventConstructor,
|
|
435
|
+
this.modelInstanceCreator
|
|
436
|
+
);
|
|
411
437
|
|
|
412
|
-
|
|
413
|
-
type: ControlMessage.SYNC_ENGINE_OUTBOX_STATUS,
|
|
414
|
-
data: {
|
|
415
|
-
isEmpty: false,
|
|
416
|
-
},
|
|
417
|
-
});
|
|
438
|
+
await this.outbox.enqueue(this.storage, mutationEvent);
|
|
418
439
|
|
|
419
|
-
|
|
440
|
+
observer.next({
|
|
441
|
+
type: ControlMessage.SYNC_ENGINE_OUTBOX_MUTATION_ENQUEUED,
|
|
442
|
+
data: {
|
|
443
|
+
model,
|
|
444
|
+
element,
|
|
445
|
+
},
|
|
446
|
+
});
|
|
420
447
|
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
448
|
+
observer.next({
|
|
449
|
+
type: ControlMessage.SYNC_ENGINE_OUTBOX_STATUS,
|
|
450
|
+
data: {
|
|
451
|
+
isEmpty: false,
|
|
452
|
+
},
|
|
453
|
+
});
|
|
454
|
+
|
|
455
|
+
await startPromise;
|
|
456
|
+
|
|
457
|
+
if (this.online) {
|
|
458
|
+
this.mutationsProcessor.resume();
|
|
459
|
+
}
|
|
460
|
+
}, 'storage event'),
|
|
425
461
|
});
|
|
426
462
|
|
|
427
463
|
observer.next({
|
|
@@ -442,11 +478,7 @@ export class SyncEngine {
|
|
|
442
478
|
observer.next({
|
|
443
479
|
type: ControlMessage.SYNC_ENGINE_READY,
|
|
444
480
|
});
|
|
445
|
-
})
|
|
446
|
-
|
|
447
|
-
return () => {
|
|
448
|
-
subscriptions.forEach(sub => sub.unsubscribe());
|
|
449
|
-
};
|
|
481
|
+
}, 'sync start');
|
|
450
482
|
});
|
|
451
483
|
}
|
|
452
484
|
|
|
@@ -454,7 +486,12 @@ export class SyncEngine {
|
|
|
454
486
|
currentTimeStamp: number
|
|
455
487
|
): Promise<Map<SchemaModel, [string, number]>> {
|
|
456
488
|
const modelLastSync: Map<SchemaModel, [string, number]> = new Map(
|
|
457
|
-
(
|
|
489
|
+
(
|
|
490
|
+
await this.runningProcesses.add(
|
|
491
|
+
() => this.getModelsMetadata(),
|
|
492
|
+
'sync/index getModelsMetadataWithNextFullSync'
|
|
493
|
+
)
|
|
494
|
+
).map(
|
|
458
495
|
({
|
|
459
496
|
namespace,
|
|
460
497
|
model,
|
|
@@ -489,224 +526,249 @@ export class SyncEngine {
|
|
|
489
526
|
|
|
490
527
|
return new Observable<ControlMessageType<ControlMessage>>(observer => {
|
|
491
528
|
let syncQueriesSubscription: ZenObservable.Subscription;
|
|
492
|
-
let waitTimeoutId: ReturnType<typeof setTimeout>;
|
|
493
|
-
|
|
494
|
-
(async () => {
|
|
495
|
-
while (!observer.closed) {
|
|
496
|
-
const count: WeakMap<
|
|
497
|
-
PersistentModelConstructor<any>,
|
|
498
|
-
{
|
|
499
|
-
new: number;
|
|
500
|
-
updated: number;
|
|
501
|
-
deleted: number;
|
|
502
|
-
}
|
|
503
|
-
> = new WeakMap();
|
|
504
|
-
|
|
505
|
-
const modelLastSync = await this.getModelsMetadataWithNextFullSync(
|
|
506
|
-
Date.now()
|
|
507
|
-
);
|
|
508
|
-
const paginatingModels = new Set(modelLastSync.keys());
|
|
509
|
-
|
|
510
|
-
let newestFullSyncStartedAt: number;
|
|
511
|
-
let theInterval: number;
|
|
512
|
-
|
|
513
|
-
let start: number;
|
|
514
|
-
let duration: number;
|
|
515
|
-
let newestStartedAt: number;
|
|
516
|
-
await new Promise(resolve => {
|
|
517
|
-
syncQueriesSubscription = this.syncQueriesProcessor
|
|
518
|
-
.start(modelLastSync)
|
|
519
|
-
.subscribe({
|
|
520
|
-
next: async ({
|
|
521
|
-
namespace,
|
|
522
|
-
modelDefinition,
|
|
523
|
-
items,
|
|
524
|
-
done,
|
|
525
|
-
startedAt,
|
|
526
|
-
isFullSync,
|
|
527
|
-
}) => {
|
|
528
|
-
const modelConstructor = this.userModelClasses[
|
|
529
|
-
modelDefinition.name
|
|
530
|
-
] as PersistentModelConstructor<any>;
|
|
531
|
-
|
|
532
|
-
if (!count.has(modelConstructor)) {
|
|
533
|
-
count.set(modelConstructor, {
|
|
534
|
-
new: 0,
|
|
535
|
-
updated: 0,
|
|
536
|
-
deleted: 0,
|
|
537
|
-
});
|
|
538
529
|
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
530
|
+
this.runningProcesses.isOpen &&
|
|
531
|
+
this.runningProcesses.add(async onTerminate => {
|
|
532
|
+
let terminated = false;
|
|
533
|
+
|
|
534
|
+
while (!observer.closed && !terminated) {
|
|
535
|
+
const count: WeakMap<
|
|
536
|
+
PersistentModelConstructor<any>,
|
|
537
|
+
{
|
|
538
|
+
new: number;
|
|
539
|
+
updated: number;
|
|
540
|
+
deleted: number;
|
|
541
|
+
}
|
|
542
|
+
> = new WeakMap();
|
|
543
|
+
|
|
544
|
+
const modelLastSync = await this.getModelsMetadataWithNextFullSync(
|
|
545
|
+
Date.now()
|
|
546
|
+
);
|
|
547
|
+
const paginatingModels = new Set(modelLastSync.keys());
|
|
548
|
+
|
|
549
|
+
let newestFullSyncStartedAt: number;
|
|
550
|
+
let theInterval: number;
|
|
551
|
+
|
|
552
|
+
let start: number;
|
|
553
|
+
let duration: number;
|
|
554
|
+
let newestStartedAt: number;
|
|
555
|
+
await new Promise((resolve, reject) => {
|
|
556
|
+
if (!this.runningProcesses.isOpen) resolve();
|
|
557
|
+
onTerminate.then(() => resolve());
|
|
558
|
+
syncQueriesSubscription = this.syncQueriesProcessor
|
|
559
|
+
.start(modelLastSync)
|
|
560
|
+
.subscribe({
|
|
561
|
+
next: async ({
|
|
562
|
+
namespace,
|
|
563
|
+
modelDefinition,
|
|
564
|
+
items,
|
|
565
|
+
done,
|
|
566
|
+
startedAt,
|
|
567
|
+
isFullSync,
|
|
568
|
+
}) => {
|
|
569
|
+
const modelConstructor = this.userModelClasses[
|
|
570
|
+
modelDefinition.name
|
|
571
|
+
] as PersistentModelConstructor<any>;
|
|
545
572
|
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
573
|
+
if (!count.has(modelConstructor)) {
|
|
574
|
+
count.set(modelConstructor, {
|
|
575
|
+
new: 0,
|
|
576
|
+
updated: 0,
|
|
577
|
+
deleted: 0,
|
|
578
|
+
});
|
|
552
579
|
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
580
|
+
start = getNow();
|
|
581
|
+
newestStartedAt =
|
|
582
|
+
newestStartedAt === undefined
|
|
583
|
+
? startedAt
|
|
584
|
+
: Math.max(newestStartedAt, startedAt);
|
|
585
|
+
}
|
|
556
586
|
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
587
|
+
/**
|
|
588
|
+
* If there are mutations in the outbox for a given id, those need to be
|
|
589
|
+
* merged individually. Otherwise, we can merge them in batches.
|
|
590
|
+
*/
|
|
591
|
+
await this.storage.runExclusive(async storage => {
|
|
592
|
+
const idsInOutbox = await this.outbox.getModelIds(
|
|
593
|
+
storage
|
|
594
|
+
);
|
|
560
595
|
|
|
561
|
-
oneByOne
|
|
562
|
-
|
|
563
|
-
|
|
596
|
+
const oneByOne: ModelInstanceMetadata[] = [];
|
|
597
|
+
const page = items.filter(item => {
|
|
598
|
+
const itemId = getIdentifierValue(
|
|
599
|
+
modelDefinition,
|
|
600
|
+
item
|
|
601
|
+
);
|
|
564
602
|
|
|
565
|
-
|
|
603
|
+
if (!idsInOutbox.has(itemId)) {
|
|
604
|
+
return true;
|
|
605
|
+
}
|
|
566
606
|
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
item,
|
|
571
|
-
modelDefinition
|
|
572
|
-
);
|
|
607
|
+
oneByOne.push(item);
|
|
608
|
+
return false;
|
|
609
|
+
});
|
|
573
610
|
|
|
574
|
-
|
|
575
|
-
opTypeCount.push([item, opType]);
|
|
576
|
-
}
|
|
577
|
-
}
|
|
611
|
+
const opTypeCount: [any, OpType][] = [];
|
|
578
612
|
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
))
|
|
586
|
-
);
|
|
613
|
+
for (const item of oneByOne) {
|
|
614
|
+
const opType = await this.modelMerger.merge(
|
|
615
|
+
storage,
|
|
616
|
+
item,
|
|
617
|
+
modelDefinition
|
|
618
|
+
);
|
|
587
619
|
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
switch (opType) {
|
|
592
|
-
case OpType.INSERT:
|
|
593
|
-
counts.new++;
|
|
594
|
-
break;
|
|
595
|
-
case OpType.UPDATE:
|
|
596
|
-
counts.updated++;
|
|
597
|
-
break;
|
|
598
|
-
case OpType.DELETE:
|
|
599
|
-
counts.deleted++;
|
|
600
|
-
break;
|
|
601
|
-
default:
|
|
602
|
-
exhaustiveCheck(opType);
|
|
620
|
+
if (opType !== undefined) {
|
|
621
|
+
opTypeCount.push([item, opType]);
|
|
622
|
+
}
|
|
603
623
|
}
|
|
604
|
-
});
|
|
605
|
-
});
|
|
606
|
-
|
|
607
|
-
if (done) {
|
|
608
|
-
const { name: modelName } = modelDefinition;
|
|
609
624
|
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
625
|
+
opTypeCount.push(
|
|
626
|
+
...(await this.modelMerger.mergePage(
|
|
627
|
+
storage,
|
|
628
|
+
modelConstructor,
|
|
629
|
+
page,
|
|
630
|
+
modelDefinition
|
|
631
|
+
))
|
|
632
|
+
);
|
|
615
633
|
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
draft.lastFullSync = isFullSync
|
|
634
|
-
? startedAt
|
|
635
|
-
: modelMetadata.lastFullSync;
|
|
634
|
+
const counts = count.get(modelConstructor);
|
|
635
|
+
|
|
636
|
+
opTypeCount.forEach(([, opType]) => {
|
|
637
|
+
switch (opType) {
|
|
638
|
+
case OpType.INSERT:
|
|
639
|
+
counts.new++;
|
|
640
|
+
break;
|
|
641
|
+
case OpType.UPDATE:
|
|
642
|
+
counts.updated++;
|
|
643
|
+
break;
|
|
644
|
+
case OpType.DELETE:
|
|
645
|
+
counts.deleted++;
|
|
646
|
+
break;
|
|
647
|
+
default:
|
|
648
|
+
exhaustiveCheck(opType);
|
|
649
|
+
}
|
|
650
|
+
});
|
|
636
651
|
});
|
|
637
652
|
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
undefined,
|
|
641
|
-
ownSymbol
|
|
642
|
-
);
|
|
643
|
-
//#endregion
|
|
653
|
+
if (done) {
|
|
654
|
+
const { name: modelName } = modelDefinition;
|
|
644
655
|
|
|
645
|
-
|
|
656
|
+
//#region update last sync for type
|
|
657
|
+
let modelMetadata = await this.getModelMetadata(
|
|
658
|
+
namespace,
|
|
659
|
+
modelName
|
|
660
|
+
);
|
|
646
661
|
|
|
647
|
-
|
|
662
|
+
const { lastFullSync, fullSyncInterval } = modelMetadata;
|
|
663
|
+
|
|
664
|
+
theInterval = fullSyncInterval;
|
|
665
|
+
|
|
666
|
+
newestFullSyncStartedAt =
|
|
667
|
+
newestFullSyncStartedAt === undefined
|
|
668
|
+
? lastFullSync
|
|
669
|
+
: Math.max(
|
|
670
|
+
newestFullSyncStartedAt,
|
|
671
|
+
isFullSync ? startedAt : lastFullSync
|
|
672
|
+
);
|
|
673
|
+
|
|
674
|
+
modelMetadata = (
|
|
675
|
+
this.modelClasses
|
|
676
|
+
.ModelMetadata as PersistentModelConstructor<ModelMetadata>
|
|
677
|
+
).copyOf(modelMetadata, draft => {
|
|
678
|
+
draft.lastSync = startedAt;
|
|
679
|
+
draft.lastFullSync = isFullSync
|
|
680
|
+
? startedAt
|
|
681
|
+
: modelMetadata.lastFullSync;
|
|
682
|
+
});
|
|
648
683
|
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
counts,
|
|
656
|
-
},
|
|
657
|
-
});
|
|
684
|
+
await this.storage.save(
|
|
685
|
+
modelMetadata,
|
|
686
|
+
undefined,
|
|
687
|
+
ownSymbol
|
|
688
|
+
);
|
|
689
|
+
//#endregion
|
|
658
690
|
|
|
659
|
-
|
|
691
|
+
const counts = count.get(modelConstructor);
|
|
692
|
+
|
|
693
|
+
this.modelSyncedStatus.set(modelConstructor, true);
|
|
660
694
|
|
|
661
|
-
if (paginatingModels.size === 0) {
|
|
662
|
-
duration = getNow() - start;
|
|
663
|
-
resolve();
|
|
664
695
|
observer.next({
|
|
665
|
-
type: ControlMessage.
|
|
696
|
+
type: ControlMessage.SYNC_ENGINE_MODEL_SYNCED,
|
|
697
|
+
data: {
|
|
698
|
+
model: modelConstructor,
|
|
699
|
+
isFullSync,
|
|
700
|
+
isDeltaSync: !isFullSync,
|
|
701
|
+
counts,
|
|
702
|
+
},
|
|
666
703
|
});
|
|
667
|
-
|
|
704
|
+
|
|
705
|
+
paginatingModels.delete(modelDefinition);
|
|
706
|
+
|
|
707
|
+
if (paginatingModels.size === 0) {
|
|
708
|
+
duration = getNow() - start;
|
|
709
|
+
resolve();
|
|
710
|
+
observer.next({
|
|
711
|
+
type: ControlMessage.SYNC_ENGINE_SYNC_QUERIES_READY,
|
|
712
|
+
});
|
|
713
|
+
syncQueriesSubscription.unsubscribe();
|
|
714
|
+
}
|
|
668
715
|
}
|
|
669
|
-
}
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
716
|
+
},
|
|
717
|
+
error: error => {
|
|
718
|
+
observer.error(error);
|
|
719
|
+
},
|
|
720
|
+
});
|
|
721
|
+
|
|
722
|
+
observer.next({
|
|
723
|
+
type: ControlMessage.SYNC_ENGINE_SYNC_QUERIES_STARTED,
|
|
724
|
+
data: {
|
|
725
|
+
models: Array.from(paginatingModels).map(({ name }) => name),
|
|
673
726
|
},
|
|
674
727
|
});
|
|
675
|
-
|
|
676
|
-
observer.next({
|
|
677
|
-
type: ControlMessage.SYNC_ENGINE_SYNC_QUERIES_STARTED,
|
|
678
|
-
data: {
|
|
679
|
-
models: Array.from(paginatingModels).map(({ name }) => name),
|
|
680
|
-
},
|
|
681
728
|
});
|
|
682
|
-
});
|
|
683
729
|
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
730
|
+
const msNextFullSync =
|
|
731
|
+
newestFullSyncStartedAt +
|
|
732
|
+
theInterval -
|
|
733
|
+
(newestStartedAt + duration);
|
|
734
|
+
|
|
735
|
+
logger.debug(
|
|
736
|
+
`Next fullSync in ${msNextFullSync / 1000} seconds. (${new Date(
|
|
737
|
+
Date.now() + msNextFullSync
|
|
738
|
+
)})`
|
|
739
|
+
);
|
|
740
|
+
|
|
741
|
+
// TODO: create `BackgroundProcessManager.sleep()` ... but, need to put
|
|
742
|
+
// a lot of thought into what that contract looks like to
|
|
743
|
+
// support possible use-cases:
|
|
744
|
+
//
|
|
745
|
+
// 1. non-cancelable
|
|
746
|
+
// 2. cancelable, unsleep on exit()
|
|
747
|
+
// 3. cancelable, throw Error on exit()
|
|
748
|
+
// 4. cancelable, callback first on exit()?
|
|
749
|
+
// 5. ... etc. ? ...
|
|
750
|
+
//
|
|
751
|
+
// TLDR; this is a lot of complexity here for a sleep(),
|
|
752
|
+
// but, it's not clear to me yet how to support an
|
|
753
|
+
// extensible, centralized cancelable `sleep()` elegantly.
|
|
754
|
+
await this.runningProcesses.add(async onTerminate => {
|
|
755
|
+
let sleepTimer;
|
|
756
|
+
let unsleep;
|
|
757
|
+
|
|
758
|
+
const sleep = new Promise(_unsleep => {
|
|
759
|
+
unsleep = _unsleep;
|
|
760
|
+
sleepTimer = setTimeout(unsleep, msNextFullSync);
|
|
761
|
+
});
|
|
700
762
|
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
763
|
+
onTerminate.then(() => {
|
|
764
|
+
terminated = true;
|
|
765
|
+
unsleep();
|
|
766
|
+
});
|
|
705
767
|
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
768
|
+
return sleep;
|
|
769
|
+
}, 'syncQueriesObservable sleep');
|
|
770
|
+
}
|
|
771
|
+
}, 'syncQueriesObservable main');
|
|
710
772
|
});
|
|
711
773
|
}
|
|
712
774
|
|
|
@@ -726,6 +788,36 @@ export class SyncEngine {
|
|
|
726
788
|
this.datastoreConnectivity.unsubscribe();
|
|
727
789
|
}
|
|
728
790
|
|
|
791
|
+
/**
|
|
792
|
+
* Stops all subscription activities and resolves when all activies report
|
|
793
|
+
* that they're disconnected, done retrying, etc..
|
|
794
|
+
*/
|
|
795
|
+
public async stop() {
|
|
796
|
+
logger.debug('stopping sync engine');
|
|
797
|
+
|
|
798
|
+
/**
|
|
799
|
+
* Gracefully disconnecting subscribers first just prevents *more* work
|
|
800
|
+
* from entering the pipelines.
|
|
801
|
+
*/
|
|
802
|
+
this.unsubscribeConnectivity();
|
|
803
|
+
|
|
804
|
+
/**
|
|
805
|
+
* aggressively shut down any lingering background processes.
|
|
806
|
+
* some of this might be semi-redundant with unsubscribing. however,
|
|
807
|
+
* unsubscribing doesn't allow us to wait for settling.
|
|
808
|
+
* (Whereas `stop()` does.)
|
|
809
|
+
*/
|
|
810
|
+
|
|
811
|
+
await this.mutationsProcessor.stop();
|
|
812
|
+
await this.subscriptionsProcessor.stop();
|
|
813
|
+
await this.datastoreConnectivity.stop();
|
|
814
|
+
await this.syncQueriesProcessor.stop();
|
|
815
|
+
await this.runningProcesses.close();
|
|
816
|
+
await this.runningProcesses.open();
|
|
817
|
+
|
|
818
|
+
logger.debug('sync engine stopped and ready to restart');
|
|
819
|
+
}
|
|
820
|
+
|
|
729
821
|
private async setupModels(params: StartParams) {
|
|
730
822
|
const { fullSyncInterval } = params;
|
|
731
823
|
const ModelMetadataConstructor = this.modelClasses
|