@aws-amplify/datastore 4.7.6-api-v6-models.b3abc9b.0 → 5.0.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/README.md +4 -0
- package/lib/authModeStrategies/defaultAuthStrategy.js +3 -2
- package/lib/authModeStrategies/index.js +3 -3
- package/lib/authModeStrategies/multiAuthStrategy.js +38 -53
- package/lib/datastore/datastore.d.ts +4 -5
- package/lib/datastore/datastore.js +929 -1284
- package/lib/index.d.ts +1 -1
- package/lib/index.js +26 -13
- package/lib/predicates/index.js +54 -69
- package/lib/predicates/next.d.ts +2 -2
- package/lib/predicates/next.js +313 -462
- package/lib/predicates/sort.js +24 -28
- package/lib/ssr/index.js +2 -2
- package/lib/storage/adapter/AsyncStorageAdapter.js +120 -342
- package/lib/storage/adapter/AsyncStorageDatabase.js +217 -421
- package/lib/storage/adapter/InMemoryStore.js +28 -51
- package/lib/storage/adapter/InMemoryStore.native.js +5 -3
- package/lib/storage/adapter/IndexedDBAdapter.js +466 -871
- package/lib/storage/adapter/StorageAdapterBase.js +180 -330
- package/lib/storage/adapter/getDefaultAdapter/index.js +8 -10
- package/lib/storage/adapter/getDefaultAdapter/index.native.js +5 -4
- package/lib/storage/adapter/index.js +0 -1
- package/lib/storage/relationship.js +177 -253
- package/lib/storage/storage.d.ts +4 -4
- package/lib/storage/storage.js +255 -433
- package/lib/sync/datastoreConnectivity.d.ts +2 -2
- package/lib/sync/datastoreConnectivity.js +29 -39
- package/lib/sync/datastoreReachability/index.d.ts +1 -3
- package/lib/sync/datastoreReachability/index.js +3 -3
- package/lib/sync/datastoreReachability/index.native.d.ts +1 -3
- package/lib/sync/datastoreReachability/index.native.js +4 -5
- package/lib/sync/index.d.ts +2 -2
- package/lib/sync/index.js +522 -827
- package/lib/sync/merger.js +31 -63
- package/lib/sync/outbox.js +148 -232
- package/lib/sync/processors/errorMaps.d.ts +1 -1
- package/lib/sync/processors/errorMaps.js +30 -47
- package/lib/sync/processors/mutation.d.ts +2 -2
- package/lib/sync/processors/mutation.js +343 -502
- package/lib/sync/processors/subscription.d.ts +5 -2
- package/lib/sync/processors/subscription.js +283 -437
- package/lib/sync/processors/sync.d.ts +2 -2
- package/lib/sync/processors/sync.js +279 -404
- package/lib/sync/utils.d.ts +5 -4
- package/lib/sync/utils.js +267 -320
- package/lib/tsconfig.tsbuildinfo +1 -0
- package/lib/types.d.ts +138 -140
- package/lib/types.js +17 -24
- package/lib/util.d.ts +9 -17
- package/lib/util.js +387 -511
- package/lib-esm/authModeStrategies/defaultAuthStrategy.js +1 -2
- package/lib-esm/authModeStrategies/index.js +0 -1
- package/lib-esm/authModeStrategies/multiAuthStrategy.js +35 -52
- package/lib-esm/datastore/datastore.d.ts +4 -5
- package/lib-esm/datastore/datastore.js +888 -1247
- package/lib-esm/index.d.ts +1 -1
- package/lib-esm/index.js +6 -7
- package/lib-esm/predicates/index.js +53 -70
- package/lib-esm/predicates/next.d.ts +2 -2
- package/lib-esm/predicates/next.js +306 -459
- package/lib-esm/predicates/sort.js +23 -28
- package/lib-esm/ssr/index.js +1 -2
- package/lib-esm/storage/adapter/AsyncStorageAdapter.js +111 -338
- package/lib-esm/storage/adapter/AsyncStorageDatabase.js +212 -416
- package/lib-esm/storage/adapter/InMemoryStore.js +27 -52
- package/lib-esm/storage/adapter/InMemoryStore.native.js +0 -1
- package/lib-esm/storage/adapter/IndexedDBAdapter.js +438 -866
- package/lib-esm/storage/adapter/StorageAdapterBase.js +173 -325
- package/lib-esm/storage/adapter/getDefaultAdapter/index.js +2 -6
- package/lib-esm/storage/adapter/getDefaultAdapter/index.native.js +1 -2
- package/lib-esm/storage/adapter/index.js +1 -1
- package/lib-esm/storage/relationship.js +173 -251
- package/lib-esm/storage/storage.d.ts +4 -4
- package/lib-esm/storage/storage.js +242 -424
- package/lib-esm/sync/datastoreConnectivity.d.ts +2 -2
- package/lib-esm/sync/datastoreConnectivity.js +28 -39
- package/lib-esm/sync/datastoreReachability/index.d.ts +1 -3
- package/lib-esm/sync/datastoreReachability/index.js +2 -3
- package/lib-esm/sync/datastoreReachability/index.native.d.ts +1 -3
- package/lib-esm/sync/datastoreReachability/index.native.js +3 -4
- package/lib-esm/sync/index.d.ts +2 -2
- package/lib-esm/sync/index.js +502 -812
- package/lib-esm/sync/merger.js +28 -61
- package/lib-esm/sync/outbox.js +143 -228
- package/lib-esm/sync/processors/errorMaps.d.ts +1 -1
- package/lib-esm/sync/processors/errorMaps.js +32 -50
- package/lib-esm/sync/processors/mutation.d.ts +2 -2
- package/lib-esm/sync/processors/mutation.js +329 -490
- package/lib-esm/sync/processors/subscription.d.ts +5 -2
- package/lib-esm/sync/processors/subscription.js +266 -421
- package/lib-esm/sync/processors/sync.d.ts +2 -2
- package/lib-esm/sync/processors/sync.js +271 -397
- package/lib-esm/sync/utils.d.ts +5 -4
- package/lib-esm/sync/utils.js +252 -307
- package/lib-esm/tsconfig.tsbuildinfo +1 -0
- package/lib-esm/types.d.ts +138 -140
- package/lib-esm/types.js +16 -25
- package/lib-esm/util.d.ts +9 -17
- package/lib-esm/util.js +335 -497
- package/package.json +31 -26
- package/src/authModeStrategies/multiAuthStrategy.ts +15 -12
- package/src/datastore/datastore.ts +36 -35
- package/src/predicates/sort.ts +3 -1
- package/src/storage/adapter/InMemoryStore.ts +1 -1
- package/src/storage/adapter/IndexedDBAdapter.ts +2 -2
- package/src/storage/adapter/StorageAdapterBase.ts +2 -2
- package/src/storage/adapter/getDefaultAdapter/index.ts +1 -4
- package/src/storage/storage.ts +29 -24
- package/src/sync/datastoreConnectivity.ts +6 -6
- package/src/sync/datastoreReachability/index.native.ts +5 -3
- package/src/sync/datastoreReachability/index.ts +1 -1
- package/src/sync/index.ts +79 -89
- package/src/sync/processors/errorMaps.ts +7 -7
- package/src/sync/processors/mutation.ts +19 -13
- package/src/sync/processors/subscription.ts +221 -295
- package/src/sync/processors/sync.ts +11 -8
- package/src/sync/utils.ts +30 -15
- package/src/types.ts +4 -8
- package/src/util.ts +46 -9
- package/lib/.tsbuildinfo +0 -3
- package/lib/authModeStrategies/defaultAuthStrategy.js.map +0 -1
- package/lib/authModeStrategies/index.js.map +0 -1
- package/lib/authModeStrategies/multiAuthStrategy.js.map +0 -1
- package/lib/datastore/datastore.js.map +0 -1
- package/lib/index.js.map +0 -1
- package/lib/predicates/index.js.map +0 -1
- package/lib/predicates/next.js.map +0 -1
- package/lib/predicates/sort.js.map +0 -1
- package/lib/ssr/index.js.map +0 -1
- package/lib/storage/adapter/AsyncStorageAdapter.js.map +0 -1
- package/lib/storage/adapter/AsyncStorageDatabase.js.map +0 -1
- package/lib/storage/adapter/InMemoryStore.js.map +0 -1
- package/lib/storage/adapter/InMemoryStore.native.js.map +0 -1
- package/lib/storage/adapter/IndexedDBAdapter.js.map +0 -1
- package/lib/storage/adapter/StorageAdapterBase.js.map +0 -1
- package/lib/storage/adapter/getDefaultAdapter/index.js.map +0 -1
- package/lib/storage/adapter/getDefaultAdapter/index.native.js.map +0 -1
- package/lib/storage/adapter/index.js.map +0 -1
- package/lib/storage/relationship.js.map +0 -1
- package/lib/storage/storage.js.map +0 -1
- package/lib/sync/datastoreConnectivity.js.map +0 -1
- package/lib/sync/datastoreReachability/index.js.map +0 -1
- package/lib/sync/datastoreReachability/index.native.js.map +0 -1
- package/lib/sync/index.js.map +0 -1
- package/lib/sync/merger.js.map +0 -1
- package/lib/sync/outbox.js.map +0 -1
- package/lib/sync/processors/errorMaps.js.map +0 -1
- package/lib/sync/processors/mutation.js.map +0 -1
- package/lib/sync/processors/subscription.js.map +0 -1
- package/lib/sync/processors/sync.js.map +0 -1
- package/lib/sync/utils.js.map +0 -1
- package/lib/types.js.map +0 -1
- package/lib/util.js.map +0 -1
- package/lib-esm/.tsbuildinfo +0 -3
- package/lib-esm/authModeStrategies/defaultAuthStrategy.js.map +0 -1
- package/lib-esm/authModeStrategies/index.js.map +0 -1
- package/lib-esm/authModeStrategies/multiAuthStrategy.js.map +0 -1
- package/lib-esm/datastore/datastore.js.map +0 -1
- package/lib-esm/index.js.map +0 -1
- package/lib-esm/predicates/index.js.map +0 -1
- package/lib-esm/predicates/next.js.map +0 -1
- package/lib-esm/predicates/sort.js.map +0 -1
- package/lib-esm/ssr/index.js.map +0 -1
- package/lib-esm/storage/adapter/AsyncStorageAdapter.js.map +0 -1
- package/lib-esm/storage/adapter/AsyncStorageDatabase.js.map +0 -1
- package/lib-esm/storage/adapter/InMemoryStore.js.map +0 -1
- package/lib-esm/storage/adapter/InMemoryStore.native.js.map +0 -1
- package/lib-esm/storage/adapter/IndexedDBAdapter.js.map +0 -1
- package/lib-esm/storage/adapter/StorageAdapterBase.js.map +0 -1
- package/lib-esm/storage/adapter/getDefaultAdapter/index.js.map +0 -1
- package/lib-esm/storage/adapter/getDefaultAdapter/index.native.js.map +0 -1
- package/lib-esm/storage/adapter/index.js.map +0 -1
- package/lib-esm/storage/relationship.js.map +0 -1
- package/lib-esm/storage/storage.js.map +0 -1
- package/lib-esm/sync/datastoreConnectivity.js.map +0 -1
- package/lib-esm/sync/datastoreReachability/index.js.map +0 -1
- package/lib-esm/sync/datastoreReachability/index.native.js.map +0 -1
- package/lib-esm/sync/index.js.map +0 -1
- package/lib-esm/sync/merger.js.map +0 -1
- package/lib-esm/sync/outbox.js.map +0 -1
- package/lib-esm/sync/processors/errorMaps.js.map +0 -1
- package/lib-esm/sync/processors/mutation.js.map +0 -1
- package/lib-esm/sync/processors/subscription.js.map +0 -1
- package/lib-esm/sync/processors/sync.js.map +0 -1
- package/lib-esm/sync/utils.js.map +0 -1
- package/lib-esm/types.js.map +0 -1
- package/lib-esm/util.js.map +0 -1
package/lib/sync/index.js
CHANGED
|
@@ -1,24 +1,27 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
2
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
|
|
6
|
+
exports.SyncEngine = exports.ControlMessage = void 0;
|
|
4
7
|
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
5
8
|
// SPDX-License-Identifier: Apache-2.0
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
9
|
+
const utils_1 = require("@aws-amplify/core/internals/utils");
|
|
10
|
+
const core_1 = require("@aws-amplify/core");
|
|
11
|
+
const rxjs_1 = require("rxjs");
|
|
12
|
+
const predicates_1 = require("../predicates");
|
|
13
|
+
const types_1 = require("../types");
|
|
14
|
+
const util_1 = require("../util");
|
|
15
|
+
const datastoreConnectivity_1 = __importDefault(require("./datastoreConnectivity"));
|
|
16
|
+
const merger_1 = require("./merger");
|
|
17
|
+
const outbox_1 = require("./outbox");
|
|
18
|
+
const mutation_1 = require("./processors/mutation");
|
|
19
|
+
const subscription_1 = require("./processors/subscription");
|
|
20
|
+
const sync_1 = require("./processors/sync");
|
|
21
|
+
const utils_2 = require("./utils");
|
|
22
|
+
const api_graphql_1 = require("@aws-amplify/api-graphql");
|
|
23
|
+
const logger = new core_1.ConsoleLogger('DataStore');
|
|
24
|
+
const ownSymbol = Symbol('sync');
|
|
22
25
|
var ControlMessage;
|
|
23
26
|
(function (ControlMessage) {
|
|
24
27
|
ControlMessage["SYNC_ENGINE_STORAGE_SUBSCRIBED"] = "storageSubscribed";
|
|
@@ -32,10 +35,11 @@ var ControlMessage;
|
|
|
32
35
|
ControlMessage["SYNC_ENGINE_NETWORK_STATUS"] = "networkStatus";
|
|
33
36
|
ControlMessage["SYNC_ENGINE_READY"] = "ready";
|
|
34
37
|
})(ControlMessage = exports.ControlMessage || (exports.ControlMessage = {}));
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
38
|
+
class SyncEngine {
|
|
39
|
+
getModelSyncedStatus(modelConstructor) {
|
|
40
|
+
return this.modelSyncedStatus.get(modelConstructor);
|
|
41
|
+
}
|
|
42
|
+
constructor(schema, namespaceResolver, modelClasses, userModelClasses, storage, modelInstanceCreator, conflictHandler, errorHandler, syncPredicates, amplifyConfig = {}, authModeStrategy, amplifyContext, connectivityMonitor) {
|
|
39
43
|
this.schema = schema;
|
|
40
44
|
this.namespaceResolver = namespaceResolver;
|
|
41
45
|
this.modelClasses = modelClasses;
|
|
@@ -50,11 +54,11 @@ var SyncEngine = /** @class */ (function () {
|
|
|
50
54
|
this.online = false;
|
|
51
55
|
this.modelSyncedStatus = new WeakMap();
|
|
52
56
|
this.connectionDisrupted = false;
|
|
53
|
-
this.runningProcesses = new
|
|
54
|
-
this.waitForSleepState = new Promise(
|
|
55
|
-
|
|
57
|
+
this.runningProcesses = new utils_1.BackgroundProcessManager();
|
|
58
|
+
this.waitForSleepState = new Promise(resolve => {
|
|
59
|
+
this.syncQueriesObservableStartSleeping = resolve;
|
|
56
60
|
});
|
|
57
|
-
|
|
61
|
+
const MutationEvent = this.modelClasses['MutationEvent'];
|
|
58
62
|
this.outbox = new outbox_1.MutationEventOutbox(this.schema, MutationEvent, modelInstanceCreator, ownSymbol);
|
|
59
63
|
this.modelMerger = new merger_1.ModelMerger(this.outbox, ownSymbol);
|
|
60
64
|
this.syncQueriesProcessor = new sync_1.SyncProcessor(this.schema, this.syncPredicates, this.amplifyConfig, this.authModeStrategy, errorHandler, this.amplifyContext);
|
|
@@ -63,813 +67,510 @@ var SyncEngine = /** @class */ (function () {
|
|
|
63
67
|
this.datastoreConnectivity =
|
|
64
68
|
this.connectivityMonitor || new datastoreConnectivity_1.default();
|
|
65
69
|
}
|
|
66
|
-
|
|
67
|
-
return
|
|
68
|
-
};
|
|
69
|
-
SyncEngine.prototype.start = function (params) {
|
|
70
|
-
var _this = this;
|
|
71
|
-
return new zen_observable_ts_1.default(function (observer) {
|
|
70
|
+
start(params) {
|
|
71
|
+
return new rxjs_1.Observable(observer => {
|
|
72
72
|
logger.log('starting sync engine...');
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
this.stopDisruptionListener =
|
|
118
|
-
this.startDisruptionListener();
|
|
119
|
-
//#region GraphQL Subscriptions
|
|
120
|
-
_a = tslib_1.__read(this.subscriptionsProcessor.start(), 2), ctlSubsObservable_1 = _a[0], dataSubsObservable = _a[1];
|
|
121
|
-
_b.label = 2;
|
|
122
|
-
case 2:
|
|
123
|
-
_b.trys.push([2, 4, , 5]);
|
|
124
|
-
return [4 /*yield*/, new Promise(function (resolve, reject) {
|
|
125
|
-
onTerminate.then(reject);
|
|
126
|
-
var ctlSubsSubscription = ctlSubsObservable_1.subscribe({
|
|
127
|
-
next: function (msg) {
|
|
128
|
-
if (msg === subscription_1.CONTROL_MSG.CONNECTED) {
|
|
129
|
-
resolve();
|
|
130
|
-
}
|
|
131
|
-
},
|
|
132
|
-
error: function (err) {
|
|
133
|
-
reject(err);
|
|
134
|
-
var handleDisconnect = _this.disconnectionHandler();
|
|
135
|
-
handleDisconnect(err);
|
|
136
|
-
},
|
|
137
|
-
});
|
|
138
|
-
subscriptions.push(ctlSubsSubscription);
|
|
139
|
-
})];
|
|
140
|
-
case 3:
|
|
141
|
-
_b.sent();
|
|
142
|
-
return [3 /*break*/, 5];
|
|
143
|
-
case 4:
|
|
144
|
-
err_2 = _b.sent();
|
|
145
|
-
observer.error(err_2);
|
|
146
|
-
failedStarting();
|
|
147
|
-
return [2 /*return*/];
|
|
148
|
-
case 5:
|
|
149
|
-
logger.log('Realtime ready');
|
|
150
|
-
observer.next({
|
|
151
|
-
type: ControlMessage.SYNC_ENGINE_SUBSCRIPTIONS_ESTABLISHED,
|
|
152
|
-
});
|
|
153
|
-
_b.label = 6;
|
|
154
|
-
case 6:
|
|
155
|
-
_b.trys.push([6, 8, , 9]);
|
|
156
|
-
return [4 /*yield*/, new Promise(function (resolve, reject) {
|
|
157
|
-
var syncQuerySubscription = _this.syncQueriesObservable().subscribe({
|
|
158
|
-
next: function (message) {
|
|
159
|
-
var type = message.type;
|
|
160
|
-
if (type ===
|
|
161
|
-
ControlMessage.SYNC_ENGINE_SYNC_QUERIES_READY) {
|
|
162
|
-
resolve();
|
|
163
|
-
}
|
|
164
|
-
observer.next(message);
|
|
165
|
-
},
|
|
166
|
-
complete: function () {
|
|
167
|
-
resolve();
|
|
168
|
-
},
|
|
169
|
-
error: function (error) {
|
|
170
|
-
reject(error);
|
|
171
|
-
},
|
|
172
|
-
});
|
|
173
|
-
if (syncQuerySubscription) {
|
|
174
|
-
subscriptions.push(syncQuerySubscription);
|
|
175
|
-
}
|
|
176
|
-
})];
|
|
177
|
-
case 7:
|
|
178
|
-
_b.sent();
|
|
179
|
-
return [3 /*break*/, 9];
|
|
180
|
-
case 8:
|
|
181
|
-
error_1 = _b.sent();
|
|
182
|
-
observer.error(error_1);
|
|
183
|
-
failedStarting();
|
|
184
|
-
return [2 /*return*/];
|
|
185
|
-
case 9:
|
|
186
|
-
//#endregion
|
|
187
|
-
//#region process mutations (outbox)
|
|
188
|
-
subscriptions.push(this.mutationsProcessor
|
|
189
|
-
.start()
|
|
190
|
-
.subscribe(function (_a) {
|
|
191
|
-
var modelDefinition = _a.modelDefinition, item = _a.model, hasMore = _a.hasMore;
|
|
192
|
-
return _this.runningProcesses.add(function () { return tslib_1.__awaiter(_this, void 0, void 0, function () {
|
|
193
|
-
var modelConstructor, model;
|
|
194
|
-
var _this = this;
|
|
195
|
-
return tslib_1.__generator(this, function (_a) {
|
|
196
|
-
switch (_a.label) {
|
|
197
|
-
case 0:
|
|
198
|
-
modelConstructor = this.userModelClasses[modelDefinition.name];
|
|
199
|
-
model = this.modelInstanceCreator(modelConstructor, item);
|
|
200
|
-
return [4 /*yield*/, this.storage.runExclusive(function (storage) {
|
|
201
|
-
return _this.modelMerger.merge(storage, model, modelDefinition);
|
|
202
|
-
})];
|
|
203
|
-
case 1:
|
|
204
|
-
_a.sent();
|
|
205
|
-
observer.next({
|
|
206
|
-
type: ControlMessage.SYNC_ENGINE_OUTBOX_MUTATION_PROCESSED,
|
|
207
|
-
data: {
|
|
208
|
-
model: modelConstructor,
|
|
209
|
-
element: model,
|
|
210
|
-
},
|
|
211
|
-
});
|
|
212
|
-
observer.next({
|
|
213
|
-
type: ControlMessage.SYNC_ENGINE_OUTBOX_STATUS,
|
|
214
|
-
data: {
|
|
215
|
-
isEmpty: !hasMore,
|
|
216
|
-
},
|
|
217
|
-
});
|
|
218
|
-
return [2 /*return*/];
|
|
219
|
-
}
|
|
220
|
-
});
|
|
221
|
-
}); }, 'mutation processor event');
|
|
222
|
-
}));
|
|
223
|
-
//#endregion
|
|
224
|
-
//#region Merge subscriptions buffer
|
|
225
|
-
// TODO: extract to function
|
|
226
|
-
if (!isNode) {
|
|
227
|
-
subscriptions.push(dataSubsObservable.subscribe(function (_a) {
|
|
228
|
-
var _b = tslib_1.__read(_a, 3), _transformerMutationType = _b[0], modelDefinition = _b[1], item = _b[2];
|
|
229
|
-
return _this.runningProcesses.add(function () { return tslib_1.__awaiter(_this, void 0, void 0, function () {
|
|
230
|
-
var modelConstructor, model;
|
|
231
|
-
var _this = this;
|
|
232
|
-
return tslib_1.__generator(this, function (_a) {
|
|
233
|
-
switch (_a.label) {
|
|
234
|
-
case 0:
|
|
235
|
-
modelConstructor = this.userModelClasses[modelDefinition.name];
|
|
236
|
-
model = this.modelInstanceCreator(modelConstructor, item);
|
|
237
|
-
return [4 /*yield*/, this.storage.runExclusive(function (storage) {
|
|
238
|
-
return _this.modelMerger.merge(storage, model, modelDefinition);
|
|
239
|
-
})];
|
|
240
|
-
case 1:
|
|
241
|
-
_a.sent();
|
|
242
|
-
return [2 /*return*/];
|
|
243
|
-
}
|
|
244
|
-
});
|
|
245
|
-
}); }, 'subscription dataSubsObservable event');
|
|
246
|
-
}));
|
|
247
|
-
}
|
|
248
|
-
return [3 /*break*/, 11];
|
|
249
|
-
case 10:
|
|
250
|
-
if (!online) {
|
|
251
|
-
this.online = online;
|
|
252
|
-
observer.next({
|
|
253
|
-
type: ControlMessage.SYNC_ENGINE_NETWORK_STATUS,
|
|
254
|
-
data: {
|
|
255
|
-
active: this.online,
|
|
256
|
-
},
|
|
257
|
-
});
|
|
258
|
-
subscriptions.forEach(function (sub) { return sub.unsubscribe(); });
|
|
259
|
-
subscriptions = [];
|
|
260
|
-
}
|
|
261
|
-
_b.label = 11;
|
|
262
|
-
case 11:
|
|
263
|
-
doneStarting();
|
|
264
|
-
return [2 /*return*/];
|
|
265
|
-
}
|
|
266
|
-
});
|
|
267
|
-
}); }, 'datastore connectivity event')];
|
|
73
|
+
let subscriptions = [];
|
|
74
|
+
this.runningProcesses.add(async () => {
|
|
75
|
+
try {
|
|
76
|
+
await this.setupModels(params);
|
|
77
|
+
}
|
|
78
|
+
catch (err) {
|
|
79
|
+
observer.error(err);
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
// this is awaited at the bottom. so, we don't need to register
|
|
83
|
+
// this explicitly with the context. it's already contained.
|
|
84
|
+
const startPromise = new Promise((doneStarting, failedStarting) => {
|
|
85
|
+
this.datastoreConnectivity.status().subscribe(async ({ online }) => this.runningProcesses.isOpen &&
|
|
86
|
+
this.runningProcesses.add(async (onTerminate) => {
|
|
87
|
+
// From offline to online
|
|
88
|
+
if (online && !this.online) {
|
|
89
|
+
this.online = online;
|
|
90
|
+
observer.next({
|
|
91
|
+
type: ControlMessage.SYNC_ENGINE_NETWORK_STATUS,
|
|
92
|
+
data: {
|
|
93
|
+
active: this.online,
|
|
94
|
+
},
|
|
95
|
+
});
|
|
96
|
+
let ctlSubsObservable;
|
|
97
|
+
let dataSubsObservable;
|
|
98
|
+
this.stopDisruptionListener =
|
|
99
|
+
this.startDisruptionListener();
|
|
100
|
+
//#region GraphQL Subscriptions
|
|
101
|
+
[ctlSubsObservable, dataSubsObservable] =
|
|
102
|
+
this.subscriptionsProcessor.start();
|
|
103
|
+
try {
|
|
104
|
+
await new Promise((resolve, reject) => {
|
|
105
|
+
onTerminate.then(reject);
|
|
106
|
+
const ctlSubsSubscription = ctlSubsObservable.subscribe({
|
|
107
|
+
next: msg => {
|
|
108
|
+
if (msg === subscription_1.CONTROL_MSG.CONNECTED) {
|
|
109
|
+
resolve();
|
|
110
|
+
}
|
|
111
|
+
},
|
|
112
|
+
error: err => {
|
|
113
|
+
reject(err);
|
|
114
|
+
const handleDisconnect = this.disconnectionHandler();
|
|
115
|
+
handleDisconnect(err);
|
|
116
|
+
},
|
|
268
117
|
});
|
|
118
|
+
subscriptions.push(ctlSubsSubscription);
|
|
269
119
|
});
|
|
120
|
+
}
|
|
121
|
+
catch (err) {
|
|
122
|
+
observer.error(err);
|
|
123
|
+
failedStarting();
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
logger.log('Realtime ready');
|
|
127
|
+
observer.next({
|
|
128
|
+
type: ControlMessage.SYNC_ENGINE_SUBSCRIPTIONS_ESTABLISHED,
|
|
270
129
|
});
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
130
|
+
//#endregion
|
|
131
|
+
//#region Base & Sync queries
|
|
132
|
+
try {
|
|
133
|
+
await new Promise((resolve, reject) => {
|
|
134
|
+
const syncQuerySubscription = this.syncQueriesObservable().subscribe({
|
|
135
|
+
next: message => {
|
|
136
|
+
const { type } = message;
|
|
137
|
+
if (type ===
|
|
138
|
+
ControlMessage.SYNC_ENGINE_SYNC_QUERIES_READY) {
|
|
139
|
+
resolve();
|
|
140
|
+
}
|
|
141
|
+
observer.next(message);
|
|
142
|
+
},
|
|
143
|
+
complete: () => {
|
|
144
|
+
resolve();
|
|
145
|
+
},
|
|
146
|
+
error: error => {
|
|
147
|
+
reject(error);
|
|
148
|
+
},
|
|
149
|
+
});
|
|
150
|
+
if (syncQuerySubscription) {
|
|
151
|
+
subscriptions.push(syncQuerySubscription);
|
|
152
|
+
}
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
catch (error) {
|
|
156
|
+
observer.error(error);
|
|
157
|
+
failedStarting();
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
//#endregion
|
|
161
|
+
//#region process mutations (outbox)
|
|
162
|
+
subscriptions.push(this.mutationsProcessor
|
|
163
|
+
.start()
|
|
164
|
+
.subscribe(({ modelDefinition, model: item, hasMore }) => this.runningProcesses.add(async () => {
|
|
165
|
+
const modelConstructor = this.userModelClasses[modelDefinition.name];
|
|
166
|
+
const model = this.modelInstanceCreator(modelConstructor, item);
|
|
167
|
+
await this.storage.runExclusive(storage => this.modelMerger.merge(storage, model, modelDefinition));
|
|
168
|
+
observer.next({
|
|
169
|
+
type: ControlMessage.SYNC_ENGINE_OUTBOX_MUTATION_PROCESSED,
|
|
170
|
+
data: {
|
|
171
|
+
model: modelConstructor,
|
|
172
|
+
element: model,
|
|
173
|
+
},
|
|
174
|
+
});
|
|
175
|
+
observer.next({
|
|
176
|
+
type: ControlMessage.SYNC_ENGINE_OUTBOX_STATUS,
|
|
177
|
+
data: {
|
|
178
|
+
isEmpty: !hasMore,
|
|
179
|
+
},
|
|
180
|
+
});
|
|
181
|
+
}, 'mutation processor event')));
|
|
182
|
+
//#endregion
|
|
183
|
+
//#region Merge subscriptions buffer
|
|
184
|
+
subscriptions.push(dataSubsObservable.subscribe(([_transformerMutationType, modelDefinition, item]) => this.runningProcesses.add(async () => {
|
|
185
|
+
const modelConstructor = this.userModelClasses[modelDefinition.name];
|
|
186
|
+
const model = this.modelInstanceCreator(modelConstructor, item);
|
|
187
|
+
await this.storage.runExclusive(storage => this.modelMerger.merge(storage, model, modelDefinition));
|
|
188
|
+
}, 'subscription dataSubsObservable event')));
|
|
189
|
+
//#endregion
|
|
190
|
+
}
|
|
191
|
+
else if (!online) {
|
|
192
|
+
this.online = online;
|
|
193
|
+
observer.next({
|
|
194
|
+
type: ControlMessage.SYNC_ENGINE_NETWORK_STATUS,
|
|
195
|
+
data: {
|
|
196
|
+
active: this.online,
|
|
197
|
+
},
|
|
198
|
+
});
|
|
199
|
+
subscriptions.forEach(sub => sub.unsubscribe());
|
|
200
|
+
subscriptions = [];
|
|
201
|
+
}
|
|
202
|
+
doneStarting();
|
|
203
|
+
}, 'datastore connectivity event'));
|
|
204
|
+
});
|
|
205
|
+
this.storage
|
|
206
|
+
.observe(null, null, ownSymbol)
|
|
207
|
+
.pipe((0, rxjs_1.filter)(({ model }) => {
|
|
208
|
+
const modelDefinition = this.getModelDefinition(model);
|
|
209
|
+
return modelDefinition.syncable === true;
|
|
210
|
+
}))
|
|
211
|
+
.subscribe({
|
|
212
|
+
next: async ({ opType, model, element, condition }) => this.runningProcesses.add(async () => {
|
|
213
|
+
const namespace = this.schema.namespaces[this.namespaceResolver(model)];
|
|
214
|
+
const MutationEventConstructor = this.modelClasses['MutationEvent'];
|
|
215
|
+
const modelDefinition = this.getModelDefinition(model);
|
|
216
|
+
const graphQLCondition = (0, utils_2.predicateToGraphQLCondition)(condition, modelDefinition);
|
|
217
|
+
const mutationEvent = (0, utils_2.createMutationInstanceFromModelOperation)(namespace.relationships, this.getModelDefinition(model), opType, model, element, graphQLCondition, MutationEventConstructor, this.modelInstanceCreator);
|
|
218
|
+
await this.outbox.enqueue(this.storage, mutationEvent);
|
|
219
|
+
observer.next({
|
|
220
|
+
type: ControlMessage.SYNC_ENGINE_OUTBOX_MUTATION_ENQUEUED,
|
|
221
|
+
data: {
|
|
222
|
+
model,
|
|
223
|
+
element,
|
|
224
|
+
},
|
|
225
|
+
});
|
|
226
|
+
observer.next({
|
|
227
|
+
type: ControlMessage.SYNC_ENGINE_OUTBOX_STATUS,
|
|
228
|
+
data: {
|
|
229
|
+
isEmpty: false,
|
|
230
|
+
},
|
|
231
|
+
});
|
|
232
|
+
await startPromise;
|
|
233
|
+
// Set by the this.datastoreConnectivity.status().subscribe() loop
|
|
234
|
+
if (this.online) {
|
|
235
|
+
this.mutationsProcessor.resume();
|
|
236
|
+
}
|
|
237
|
+
}, 'storage event'),
|
|
238
|
+
});
|
|
239
|
+
observer.next({
|
|
240
|
+
type: ControlMessage.SYNC_ENGINE_STORAGE_SUBSCRIBED,
|
|
241
|
+
});
|
|
242
|
+
const hasMutationsInOutbox = (await this.outbox.peek(this.storage)) === undefined;
|
|
243
|
+
observer.next({
|
|
244
|
+
type: ControlMessage.SYNC_ENGINE_OUTBOX_STATUS,
|
|
245
|
+
data: {
|
|
246
|
+
isEmpty: hasMutationsInOutbox,
|
|
247
|
+
},
|
|
248
|
+
});
|
|
249
|
+
await startPromise;
|
|
250
|
+
observer.next({
|
|
251
|
+
type: ControlMessage.SYNC_ENGINE_READY,
|
|
252
|
+
});
|
|
253
|
+
}, 'sync start');
|
|
254
|
+
});
|
|
255
|
+
}
|
|
256
|
+
async getModelsMetadataWithNextFullSync(currentTimeStamp) {
|
|
257
|
+
const modelLastSync = new Map((await this.runningProcesses.add(() => this.getModelsMetadata(), 'sync/index getModelsMetadataWithNextFullSync')).map(({ namespace, model, lastSync, lastFullSync, fullSyncInterval, lastSyncPredicate, }) => {
|
|
258
|
+
const nextFullSync = lastFullSync + fullSyncInterval;
|
|
259
|
+
const syncFrom = !lastFullSync || nextFullSync < currentTimeStamp
|
|
260
|
+
? 0 // perform full sync if expired
|
|
261
|
+
: lastSync; // perform delta sync
|
|
262
|
+
return [
|
|
263
|
+
this.schema.namespaces[namespace].models[model],
|
|
264
|
+
[namespace, syncFrom],
|
|
265
|
+
];
|
|
266
|
+
}));
|
|
267
|
+
return modelLastSync;
|
|
268
|
+
}
|
|
269
|
+
syncQueriesObservable() {
|
|
270
|
+
if (!this.online) {
|
|
271
|
+
return (0, rxjs_1.of)({}); // TODO(v6): fix this
|
|
272
|
+
}
|
|
273
|
+
return new rxjs_1.Observable(observer => {
|
|
274
|
+
let syncQueriesSubscription;
|
|
275
|
+
this.runningProcesses.isOpen &&
|
|
276
|
+
this.runningProcesses.add(async (onTerminate) => {
|
|
277
|
+
let terminated = false;
|
|
278
|
+
while (!observer.closed && !terminated) {
|
|
279
|
+
const count = new WeakMap();
|
|
280
|
+
const modelLastSync = await this.getModelsMetadataWithNextFullSync(Date.now());
|
|
281
|
+
const paginatingModels = new Set(modelLastSync.keys());
|
|
282
|
+
let lastFullSyncStartedAt;
|
|
283
|
+
let syncInterval;
|
|
284
|
+
let start;
|
|
285
|
+
let syncDuration;
|
|
286
|
+
let lastStartedAt;
|
|
287
|
+
await new Promise((resolve, reject) => {
|
|
288
|
+
if (!this.runningProcesses.isOpen)
|
|
289
|
+
resolve();
|
|
290
|
+
onTerminate.then(() => resolve());
|
|
291
|
+
syncQueriesSubscription = this.syncQueriesProcessor
|
|
292
|
+
.start(modelLastSync)
|
|
279
293
|
.subscribe({
|
|
280
|
-
next:
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
294
|
+
next: async ({ namespace, modelDefinition, items, done, startedAt, isFullSync, }) => {
|
|
295
|
+
const modelConstructor = this.userModelClasses[modelDefinition.name];
|
|
296
|
+
if (!count.has(modelConstructor)) {
|
|
297
|
+
count.set(modelConstructor, {
|
|
298
|
+
new: 0,
|
|
299
|
+
updated: 0,
|
|
300
|
+
deleted: 0,
|
|
301
|
+
});
|
|
302
|
+
start = (0, util_1.getNow)();
|
|
303
|
+
lastStartedAt =
|
|
304
|
+
lastStartedAt === undefined
|
|
305
|
+
? startedAt
|
|
306
|
+
: Math.max(lastStartedAt, startedAt);
|
|
307
|
+
}
|
|
308
|
+
/**
|
|
309
|
+
* If there are mutations in the outbox for a given id, those need to be
|
|
310
|
+
* merged individually. Otherwise, we can merge them in batches.
|
|
311
|
+
*/
|
|
312
|
+
await this.storage.runExclusive(async (storage) => {
|
|
313
|
+
const idsInOutbox = await this.outbox.getModelIds(storage);
|
|
314
|
+
const oneByOne = [];
|
|
315
|
+
const page = items.filter(item => {
|
|
316
|
+
const itemId = (0, utils_2.getIdentifierValue)(modelDefinition, item);
|
|
317
|
+
if (!idsInOutbox.has(itemId)) {
|
|
318
|
+
return true;
|
|
319
|
+
}
|
|
320
|
+
oneByOne.push(item);
|
|
321
|
+
return false;
|
|
322
|
+
});
|
|
323
|
+
const opTypeCount = [];
|
|
324
|
+
for (const item of oneByOne) {
|
|
325
|
+
const opType = await this.modelMerger.merge(storage, item, modelDefinition);
|
|
326
|
+
if (opType !== undefined) {
|
|
327
|
+
opTypeCount.push([item, opType]);
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
opTypeCount.push(...(await this.modelMerger.mergePage(storage, modelConstructor, page, modelDefinition)));
|
|
331
|
+
const counts = count.get(modelConstructor);
|
|
332
|
+
opTypeCount.forEach(([, opType]) => {
|
|
333
|
+
switch (opType) {
|
|
334
|
+
case types_1.OpType.INSERT:
|
|
335
|
+
counts.new++;
|
|
336
|
+
break;
|
|
337
|
+
case types_1.OpType.UPDATE:
|
|
338
|
+
counts.updated++;
|
|
339
|
+
break;
|
|
340
|
+
case types_1.OpType.DELETE:
|
|
341
|
+
counts.deleted++;
|
|
342
|
+
break;
|
|
343
|
+
default:
|
|
344
|
+
throw new Error(`Invalid opType ${opType}`);
|
|
345
|
+
}
|
|
322
346
|
});
|
|
323
347
|
});
|
|
348
|
+
if (done) {
|
|
349
|
+
const { name: modelName } = modelDefinition;
|
|
350
|
+
//#region update last sync for type
|
|
351
|
+
let modelMetadata = await this.getModelMetadata(namespace, modelName);
|
|
352
|
+
const { lastFullSync, fullSyncInterval } = modelMetadata;
|
|
353
|
+
syncInterval = fullSyncInterval;
|
|
354
|
+
lastFullSyncStartedAt =
|
|
355
|
+
lastFullSyncStartedAt === undefined
|
|
356
|
+
? lastFullSync
|
|
357
|
+
: Math.max(lastFullSyncStartedAt, isFullSync ? startedAt : lastFullSync);
|
|
358
|
+
modelMetadata = this.modelClasses
|
|
359
|
+
.ModelMetadata.copyOf(modelMetadata, draft => {
|
|
360
|
+
draft.lastSync = startedAt;
|
|
361
|
+
draft.lastFullSync = isFullSync
|
|
362
|
+
? startedAt
|
|
363
|
+
: modelMetadata.lastFullSync;
|
|
364
|
+
});
|
|
365
|
+
await this.storage.save(modelMetadata, undefined, ownSymbol);
|
|
366
|
+
//#endregion
|
|
367
|
+
const counts = count.get(modelConstructor);
|
|
368
|
+
this.modelSyncedStatus.set(modelConstructor, true);
|
|
369
|
+
observer.next({
|
|
370
|
+
type: ControlMessage.SYNC_ENGINE_MODEL_SYNCED,
|
|
371
|
+
data: {
|
|
372
|
+
model: modelConstructor,
|
|
373
|
+
isFullSync,
|
|
374
|
+
isDeltaSync: !isFullSync,
|
|
375
|
+
counts,
|
|
376
|
+
},
|
|
377
|
+
});
|
|
378
|
+
paginatingModels.delete(modelDefinition);
|
|
379
|
+
if (paginatingModels.size === 0) {
|
|
380
|
+
syncDuration = (0, util_1.getNow)() - start;
|
|
381
|
+
resolve();
|
|
382
|
+
observer.next({
|
|
383
|
+
type: ControlMessage.SYNC_ENGINE_SYNC_QUERIES_READY,
|
|
384
|
+
});
|
|
385
|
+
syncQueriesSubscription.unsubscribe();
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
},
|
|
389
|
+
error: error => {
|
|
390
|
+
observer.error(error);
|
|
324
391
|
},
|
|
325
392
|
});
|
|
326
393
|
observer.next({
|
|
327
|
-
type: ControlMessage.
|
|
328
|
-
});
|
|
329
|
-
return [4 /*yield*/, this.outbox.peek(this.storage)];
|
|
330
|
-
case 4:
|
|
331
|
-
hasMutationsInOutbox = (_a.sent()) === undefined;
|
|
332
|
-
observer.next({
|
|
333
|
-
type: ControlMessage.SYNC_ENGINE_OUTBOX_STATUS,
|
|
394
|
+
type: ControlMessage.SYNC_ENGINE_SYNC_QUERIES_STARTED,
|
|
334
395
|
data: {
|
|
335
|
-
|
|
396
|
+
models: Array.from(paginatingModels).map(({ name }) => name),
|
|
336
397
|
},
|
|
337
398
|
});
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
399
|
+
});
|
|
400
|
+
// null is cast to 0 resulting in unexpected behavior.
|
|
401
|
+
// undefined in arithmetic operations results in NaN also resulting in unexpected behavior.
|
|
402
|
+
// If lastFullSyncStartedAt is null this is the first sync.
|
|
403
|
+
// Assume lastStartedAt is is also newest full sync.
|
|
404
|
+
let msNextFullSync;
|
|
405
|
+
if (!lastFullSyncStartedAt) {
|
|
406
|
+
msNextFullSync = syncInterval - syncDuration;
|
|
407
|
+
}
|
|
408
|
+
else {
|
|
409
|
+
msNextFullSync =
|
|
410
|
+
lastFullSyncStartedAt +
|
|
411
|
+
syncInterval -
|
|
412
|
+
(lastStartedAt + syncDuration);
|
|
413
|
+
}
|
|
414
|
+
logger.debug(`Next fullSync in ${msNextFullSync / 1000} seconds. (${new Date(Date.now() + msNextFullSync)})`);
|
|
415
|
+
// TODO: create `BackgroundProcessManager.sleep()` ... but, need to put
|
|
416
|
+
// a lot of thought into what that contract looks like to
|
|
417
|
+
// support possible use-cases:
|
|
418
|
+
//
|
|
419
|
+
// 1. non-cancelable
|
|
420
|
+
// 2. cancelable, unsleep on exit()
|
|
421
|
+
// 3. cancelable, throw Error on exit()
|
|
422
|
+
// 4. cancelable, callback first on exit()?
|
|
423
|
+
// 5. ... etc. ? ...
|
|
424
|
+
//
|
|
425
|
+
// TLDR; this is a lot of complexity here for a sleep(),
|
|
426
|
+
// but, it's not clear to me yet how to support an
|
|
427
|
+
// extensible, centralized cancelable `sleep()` elegantly.
|
|
428
|
+
await this.runningProcesses.add(async (onTerminate) => {
|
|
429
|
+
let sleepTimer;
|
|
430
|
+
let unsleep;
|
|
431
|
+
const sleep = new Promise(_unsleep => {
|
|
432
|
+
unsleep = _unsleep;
|
|
433
|
+
sleepTimer = setTimeout(unsleep, msNextFullSync);
|
|
434
|
+
});
|
|
435
|
+
onTerminate.then(() => {
|
|
436
|
+
terminated = true;
|
|
437
|
+
this.syncQueriesObservableStartSleeping();
|
|
438
|
+
unsleep();
|
|
343
439
|
});
|
|
344
|
-
|
|
440
|
+
this.unsleepSyncQueriesObservable = unsleep;
|
|
441
|
+
this.syncQueriesObservableStartSleeping();
|
|
442
|
+
return sleep;
|
|
443
|
+
}, 'syncQueriesObservable sleep');
|
|
444
|
+
this.unsleepSyncQueriesObservable = null;
|
|
445
|
+
this.waitForSleepState = new Promise(resolve => {
|
|
446
|
+
this.syncQueriesObservableStartSleeping = resolve;
|
|
447
|
+
});
|
|
345
448
|
}
|
|
346
|
-
});
|
|
347
|
-
}); }, 'sync start');
|
|
348
|
-
});
|
|
349
|
-
};
|
|
350
|
-
SyncEngine.prototype.getModelsMetadataWithNextFullSync = function (currentTimeStamp) {
|
|
351
|
-
return tslib_1.__awaiter(this, void 0, void 0, function () {
|
|
352
|
-
var modelLastSync, _a;
|
|
353
|
-
var _this = this;
|
|
354
|
-
return tslib_1.__generator(this, function (_b) {
|
|
355
|
-
switch (_b.label) {
|
|
356
|
-
case 0:
|
|
357
|
-
_a = Map.bind;
|
|
358
|
-
return [4 /*yield*/, this.runningProcesses.add(function () { return _this.getModelsMetadata(); }, 'sync/index getModelsMetadataWithNextFullSync')];
|
|
359
|
-
case 1:
|
|
360
|
-
modelLastSync = new (_a.apply(Map, [void 0, (_b.sent()).map(function (_a) {
|
|
361
|
-
var namespace = _a.namespace, model = _a.model, lastSync = _a.lastSync, lastFullSync = _a.lastFullSync, fullSyncInterval = _a.fullSyncInterval, lastSyncPredicate = _a.lastSyncPredicate;
|
|
362
|
-
var nextFullSync = lastFullSync + fullSyncInterval;
|
|
363
|
-
var syncFrom = !lastFullSync || nextFullSync < currentTimeStamp
|
|
364
|
-
? 0 // perform full sync if expired
|
|
365
|
-
: lastSync; // perform delta sync
|
|
366
|
-
return [
|
|
367
|
-
_this.schema.namespaces[namespace].models[model],
|
|
368
|
-
[namespace, syncFrom],
|
|
369
|
-
];
|
|
370
|
-
})]))();
|
|
371
|
-
return [2 /*return*/, modelLastSync];
|
|
372
|
-
}
|
|
373
|
-
});
|
|
374
|
-
});
|
|
375
|
-
};
|
|
376
|
-
SyncEngine.prototype.syncQueriesObservable = function () {
|
|
377
|
-
var _this = this;
|
|
378
|
-
if (!this.online) {
|
|
379
|
-
return zen_observable_ts_1.default.of();
|
|
380
|
-
}
|
|
381
|
-
return new zen_observable_ts_1.default(function (observer) {
|
|
382
|
-
var syncQueriesSubscription;
|
|
383
|
-
_this.runningProcesses.isOpen &&
|
|
384
|
-
_this.runningProcesses.add(function (onTerminate) { return tslib_1.__awaiter(_this, void 0, void 0, function () {
|
|
385
|
-
var terminated, _loop_1, this_1;
|
|
386
|
-
var _this = this;
|
|
387
|
-
return tslib_1.__generator(this, function (_a) {
|
|
388
|
-
switch (_a.label) {
|
|
389
|
-
case 0:
|
|
390
|
-
terminated = false;
|
|
391
|
-
_loop_1 = function () {
|
|
392
|
-
var count, modelLastSync, paginatingModels, lastFullSyncStartedAt, syncInterval, start, syncDuration, lastStartedAt, msNextFullSync;
|
|
393
|
-
return tslib_1.__generator(this, function (_a) {
|
|
394
|
-
switch (_a.label) {
|
|
395
|
-
case 0:
|
|
396
|
-
count = new WeakMap();
|
|
397
|
-
return [4 /*yield*/, this_1.getModelsMetadataWithNextFullSync(Date.now())];
|
|
398
|
-
case 1:
|
|
399
|
-
modelLastSync = _a.sent();
|
|
400
|
-
paginatingModels = new Set(modelLastSync.keys());
|
|
401
|
-
return [4 /*yield*/, new Promise(function (resolve, reject) {
|
|
402
|
-
if (!_this.runningProcesses.isOpen)
|
|
403
|
-
resolve();
|
|
404
|
-
onTerminate.then(function () { return resolve(); });
|
|
405
|
-
syncQueriesSubscription = _this.syncQueriesProcessor
|
|
406
|
-
.start(modelLastSync)
|
|
407
|
-
.subscribe({
|
|
408
|
-
next: function (_a) {
|
|
409
|
-
var namespace = _a.namespace, modelDefinition = _a.modelDefinition, items = _a.items, done = _a.done, startedAt = _a.startedAt, isFullSync = _a.isFullSync;
|
|
410
|
-
return tslib_1.__awaiter(_this, void 0, void 0, function () {
|
|
411
|
-
var modelConstructor, modelName, modelMetadata_1, lastFullSync, fullSyncInterval, counts;
|
|
412
|
-
var _this = this;
|
|
413
|
-
return tslib_1.__generator(this, function (_b) {
|
|
414
|
-
switch (_b.label) {
|
|
415
|
-
case 0:
|
|
416
|
-
modelConstructor = this.userModelClasses[modelDefinition.name];
|
|
417
|
-
if (!count.has(modelConstructor)) {
|
|
418
|
-
count.set(modelConstructor, {
|
|
419
|
-
new: 0,
|
|
420
|
-
updated: 0,
|
|
421
|
-
deleted: 0,
|
|
422
|
-
});
|
|
423
|
-
start = util_1.getNow();
|
|
424
|
-
lastStartedAt =
|
|
425
|
-
lastStartedAt === undefined
|
|
426
|
-
? startedAt
|
|
427
|
-
: Math.max(lastStartedAt, startedAt);
|
|
428
|
-
}
|
|
429
|
-
/**
|
|
430
|
-
* If there are mutations in the outbox for a given id, those need to be
|
|
431
|
-
* merged individually. Otherwise, we can merge them in batches.
|
|
432
|
-
*/
|
|
433
|
-
return [4 /*yield*/, this.storage.runExclusive(function (storage) { return tslib_1.__awaiter(_this, void 0, void 0, function () {
|
|
434
|
-
var idsInOutbox, oneByOne, page, opTypeCount, oneByOne_1, oneByOne_1_1, item, opType, e_1_1, _a, _b, _c, counts;
|
|
435
|
-
var e_1, _d;
|
|
436
|
-
return tslib_1.__generator(this, function (_e) {
|
|
437
|
-
switch (_e.label) {
|
|
438
|
-
case 0: return [4 /*yield*/, this.outbox.getModelIds(storage)];
|
|
439
|
-
case 1:
|
|
440
|
-
idsInOutbox = _e.sent();
|
|
441
|
-
oneByOne = [];
|
|
442
|
-
page = items.filter(function (item) {
|
|
443
|
-
var itemId = utils_1.getIdentifierValue(modelDefinition, item);
|
|
444
|
-
if (!idsInOutbox.has(itemId)) {
|
|
445
|
-
return true;
|
|
446
|
-
}
|
|
447
|
-
oneByOne.push(item);
|
|
448
|
-
return false;
|
|
449
|
-
});
|
|
450
|
-
opTypeCount = [];
|
|
451
|
-
_e.label = 2;
|
|
452
|
-
case 2:
|
|
453
|
-
_e.trys.push([2, 7, 8, 9]);
|
|
454
|
-
oneByOne_1 = tslib_1.__values(oneByOne), oneByOne_1_1 = oneByOne_1.next();
|
|
455
|
-
_e.label = 3;
|
|
456
|
-
case 3:
|
|
457
|
-
if (!!oneByOne_1_1.done) return [3 /*break*/, 6];
|
|
458
|
-
item = oneByOne_1_1.value;
|
|
459
|
-
return [4 /*yield*/, this.modelMerger.merge(storage, item, modelDefinition)];
|
|
460
|
-
case 4:
|
|
461
|
-
opType = _e.sent();
|
|
462
|
-
if (opType !== undefined) {
|
|
463
|
-
opTypeCount.push([item, opType]);
|
|
464
|
-
}
|
|
465
|
-
_e.label = 5;
|
|
466
|
-
case 5:
|
|
467
|
-
oneByOne_1_1 = oneByOne_1.next();
|
|
468
|
-
return [3 /*break*/, 3];
|
|
469
|
-
case 6: return [3 /*break*/, 9];
|
|
470
|
-
case 7:
|
|
471
|
-
e_1_1 = _e.sent();
|
|
472
|
-
e_1 = { error: e_1_1 };
|
|
473
|
-
return [3 /*break*/, 9];
|
|
474
|
-
case 8:
|
|
475
|
-
try {
|
|
476
|
-
if (oneByOne_1_1 && !oneByOne_1_1.done && (_d = oneByOne_1.return)) _d.call(oneByOne_1);
|
|
477
|
-
}
|
|
478
|
-
finally { if (e_1) throw e_1.error; }
|
|
479
|
-
return [7 /*endfinally*/];
|
|
480
|
-
case 9:
|
|
481
|
-
_b = (_a = opTypeCount.push).apply;
|
|
482
|
-
_c = [opTypeCount];
|
|
483
|
-
return [4 /*yield*/, this.modelMerger.mergePage(storage, modelConstructor, page, modelDefinition)];
|
|
484
|
-
case 10:
|
|
485
|
-
_b.apply(_a, _c.concat([tslib_1.__spread.apply(void 0, [(_e.sent())])]));
|
|
486
|
-
counts = count.get(modelConstructor);
|
|
487
|
-
opTypeCount.forEach(function (_a) {
|
|
488
|
-
var _b = tslib_1.__read(_a, 2), opType = _b[1];
|
|
489
|
-
switch (opType) {
|
|
490
|
-
case types_1.OpType.INSERT:
|
|
491
|
-
counts.new++;
|
|
492
|
-
break;
|
|
493
|
-
case types_1.OpType.UPDATE:
|
|
494
|
-
counts.updated++;
|
|
495
|
-
break;
|
|
496
|
-
case types_1.OpType.DELETE:
|
|
497
|
-
counts.deleted++;
|
|
498
|
-
break;
|
|
499
|
-
default:
|
|
500
|
-
throw new Error("Invalid opType " + opType);
|
|
501
|
-
}
|
|
502
|
-
});
|
|
503
|
-
return [2 /*return*/];
|
|
504
|
-
}
|
|
505
|
-
});
|
|
506
|
-
}); })];
|
|
507
|
-
case 1:
|
|
508
|
-
/**
|
|
509
|
-
* If there are mutations in the outbox for a given id, those need to be
|
|
510
|
-
* merged individually. Otherwise, we can merge them in batches.
|
|
511
|
-
*/
|
|
512
|
-
_b.sent();
|
|
513
|
-
if (!done) return [3 /*break*/, 4];
|
|
514
|
-
modelName = modelDefinition.name;
|
|
515
|
-
return [4 /*yield*/, this.getModelMetadata(namespace, modelName)];
|
|
516
|
-
case 2:
|
|
517
|
-
modelMetadata_1 = _b.sent();
|
|
518
|
-
lastFullSync = modelMetadata_1.lastFullSync, fullSyncInterval = modelMetadata_1.fullSyncInterval;
|
|
519
|
-
syncInterval = fullSyncInterval;
|
|
520
|
-
lastFullSyncStartedAt =
|
|
521
|
-
lastFullSyncStartedAt === undefined
|
|
522
|
-
? lastFullSync
|
|
523
|
-
: Math.max(lastFullSyncStartedAt, isFullSync ? startedAt : lastFullSync);
|
|
524
|
-
modelMetadata_1 = this.modelClasses
|
|
525
|
-
.ModelMetadata.copyOf(modelMetadata_1, function (draft) {
|
|
526
|
-
draft.lastSync = startedAt;
|
|
527
|
-
draft.lastFullSync = isFullSync
|
|
528
|
-
? startedAt
|
|
529
|
-
: modelMetadata_1.lastFullSync;
|
|
530
|
-
});
|
|
531
|
-
return [4 /*yield*/, this.storage.save(modelMetadata_1, undefined, ownSymbol)];
|
|
532
|
-
case 3:
|
|
533
|
-
_b.sent();
|
|
534
|
-
counts = count.get(modelConstructor);
|
|
535
|
-
this.modelSyncedStatus.set(modelConstructor, true);
|
|
536
|
-
observer.next({
|
|
537
|
-
type: ControlMessage.SYNC_ENGINE_MODEL_SYNCED,
|
|
538
|
-
data: {
|
|
539
|
-
model: modelConstructor,
|
|
540
|
-
isFullSync: isFullSync,
|
|
541
|
-
isDeltaSync: !isFullSync,
|
|
542
|
-
counts: counts,
|
|
543
|
-
},
|
|
544
|
-
});
|
|
545
|
-
paginatingModels.delete(modelDefinition);
|
|
546
|
-
if (paginatingModels.size === 0) {
|
|
547
|
-
syncDuration = util_1.getNow() - start;
|
|
548
|
-
resolve();
|
|
549
|
-
observer.next({
|
|
550
|
-
type: ControlMessage.SYNC_ENGINE_SYNC_QUERIES_READY,
|
|
551
|
-
});
|
|
552
|
-
syncQueriesSubscription.unsubscribe();
|
|
553
|
-
}
|
|
554
|
-
_b.label = 4;
|
|
555
|
-
case 4: return [2 /*return*/];
|
|
556
|
-
}
|
|
557
|
-
});
|
|
558
|
-
});
|
|
559
|
-
},
|
|
560
|
-
error: function (error) {
|
|
561
|
-
observer.error(error);
|
|
562
|
-
},
|
|
563
|
-
});
|
|
564
|
-
observer.next({
|
|
565
|
-
type: ControlMessage.SYNC_ENGINE_SYNC_QUERIES_STARTED,
|
|
566
|
-
data: {
|
|
567
|
-
models: Array.from(paginatingModels).map(function (_a) {
|
|
568
|
-
var name = _a.name;
|
|
569
|
-
return name;
|
|
570
|
-
}),
|
|
571
|
-
},
|
|
572
|
-
});
|
|
573
|
-
})];
|
|
574
|
-
case 2:
|
|
575
|
-
_a.sent();
|
|
576
|
-
if (!lastFullSyncStartedAt) {
|
|
577
|
-
msNextFullSync = syncInterval - syncDuration;
|
|
578
|
-
}
|
|
579
|
-
else {
|
|
580
|
-
msNextFullSync =
|
|
581
|
-
lastFullSyncStartedAt +
|
|
582
|
-
syncInterval -
|
|
583
|
-
(lastStartedAt + syncDuration);
|
|
584
|
-
}
|
|
585
|
-
logger.debug("Next fullSync in " + msNextFullSync / 1000 + " seconds. (" + new Date(Date.now() + msNextFullSync) + ")");
|
|
586
|
-
// TODO: create `BackgroundProcessManager.sleep()` ... but, need to put
|
|
587
|
-
// a lot of thought into what that contract looks like to
|
|
588
|
-
// support possible use-cases:
|
|
589
|
-
//
|
|
590
|
-
// 1. non-cancelable
|
|
591
|
-
// 2. cancelable, unsleep on exit()
|
|
592
|
-
// 3. cancelable, throw Error on exit()
|
|
593
|
-
// 4. cancelable, callback first on exit()?
|
|
594
|
-
// 5. ... etc. ? ...
|
|
595
|
-
//
|
|
596
|
-
// TLDR; this is a lot of complexity here for a sleep(),
|
|
597
|
-
// but, it's not clear to me yet how to support an
|
|
598
|
-
// extensible, centralized cancelable `sleep()` elegantly.
|
|
599
|
-
return [4 /*yield*/, this_1.runningProcesses.add(function (onTerminate) { return tslib_1.__awaiter(_this, void 0, void 0, function () {
|
|
600
|
-
var sleepTimer, unsleep, sleep;
|
|
601
|
-
var _this = this;
|
|
602
|
-
return tslib_1.__generator(this, function (_a) {
|
|
603
|
-
sleep = new Promise(function (_unsleep) {
|
|
604
|
-
unsleep = _unsleep;
|
|
605
|
-
sleepTimer = setTimeout(unsleep, msNextFullSync);
|
|
606
|
-
});
|
|
607
|
-
onTerminate.then(function () {
|
|
608
|
-
terminated = true;
|
|
609
|
-
_this.syncQueriesObservableStartSleeping();
|
|
610
|
-
unsleep();
|
|
611
|
-
});
|
|
612
|
-
this.unsleepSyncQueriesObservable = unsleep;
|
|
613
|
-
this.syncQueriesObservableStartSleeping();
|
|
614
|
-
return [2 /*return*/, sleep];
|
|
615
|
-
});
|
|
616
|
-
}); }, 'syncQueriesObservable sleep')];
|
|
617
|
-
case 3:
|
|
618
|
-
// TODO: create `BackgroundProcessManager.sleep()` ... but, need to put
|
|
619
|
-
// a lot of thought into what that contract looks like to
|
|
620
|
-
// support possible use-cases:
|
|
621
|
-
//
|
|
622
|
-
// 1. non-cancelable
|
|
623
|
-
// 2. cancelable, unsleep on exit()
|
|
624
|
-
// 3. cancelable, throw Error on exit()
|
|
625
|
-
// 4. cancelable, callback first on exit()?
|
|
626
|
-
// 5. ... etc. ? ...
|
|
627
|
-
//
|
|
628
|
-
// TLDR; this is a lot of complexity here for a sleep(),
|
|
629
|
-
// but, it's not clear to me yet how to support an
|
|
630
|
-
// extensible, centralized cancelable `sleep()` elegantly.
|
|
631
|
-
_a.sent();
|
|
632
|
-
this_1.unsleepSyncQueriesObservable = null;
|
|
633
|
-
this_1.waitForSleepState = new Promise(function (resolve) {
|
|
634
|
-
_this.syncQueriesObservableStartSleeping = resolve;
|
|
635
|
-
});
|
|
636
|
-
return [2 /*return*/];
|
|
637
|
-
}
|
|
638
|
-
});
|
|
639
|
-
};
|
|
640
|
-
this_1 = this;
|
|
641
|
-
_a.label = 1;
|
|
642
|
-
case 1:
|
|
643
|
-
if (!(!observer.closed && !terminated)) return [3 /*break*/, 3];
|
|
644
|
-
return [5 /*yield**/, _loop_1()];
|
|
645
|
-
case 2:
|
|
646
|
-
_a.sent();
|
|
647
|
-
return [3 /*break*/, 1];
|
|
648
|
-
case 3: return [2 /*return*/];
|
|
649
|
-
}
|
|
650
|
-
});
|
|
651
|
-
}); }, 'syncQueriesObservable main');
|
|
449
|
+
}, 'syncQueriesObservable main');
|
|
652
450
|
});
|
|
653
|
-
}
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
return function (msg) {
|
|
451
|
+
}
|
|
452
|
+
disconnectionHandler() {
|
|
453
|
+
return (msg) => {
|
|
657
454
|
// This implementation is tied to AWSAppSyncRealTimeProvider 'Connection closed', 'Timeout disconnect' msg
|
|
658
|
-
if (
|
|
659
|
-
|
|
660
|
-
|
|
455
|
+
if (api_graphql_1.CONTROL_MSG.CONNECTION_CLOSED === msg ||
|
|
456
|
+
api_graphql_1.CONTROL_MSG.TIMEOUT_DISCONNECT === msg) {
|
|
457
|
+
this.datastoreConnectivity.socketDisconnected();
|
|
661
458
|
}
|
|
662
459
|
};
|
|
663
|
-
}
|
|
664
|
-
|
|
460
|
+
}
|
|
461
|
+
unsubscribeConnectivity() {
|
|
665
462
|
this.datastoreConnectivity.unsubscribe();
|
|
666
|
-
}
|
|
463
|
+
}
|
|
667
464
|
/**
|
|
668
465
|
* Stops all subscription activities and resolves when all activies report
|
|
669
466
|
* that they're disconnected, done retrying, etc..
|
|
670
467
|
*/
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
return [4 /*yield*/, this.runningProcesses.close()];
|
|
711
|
-
case 5:
|
|
712
|
-
_a.sent();
|
|
713
|
-
return [4 /*yield*/, this.runningProcesses.open()];
|
|
714
|
-
case 6:
|
|
715
|
-
_a.sent();
|
|
716
|
-
logger.debug('sync engine stopped and ready to restart');
|
|
717
|
-
return [2 /*return*/];
|
|
718
|
-
}
|
|
719
|
-
});
|
|
720
|
-
});
|
|
721
|
-
};
|
|
722
|
-
SyncEngine.prototype.setupModels = function (params) {
|
|
723
|
-
return tslib_1.__awaiter(this, void 0, void 0, function () {
|
|
724
|
-
var fullSyncInterval, ModelMetadataConstructor, models, savedModel, promises, result, _a, _b, modelMetadata, modelName, e_2_1;
|
|
725
|
-
var e_2, _c;
|
|
726
|
-
var _this = this;
|
|
727
|
-
return tslib_1.__generator(this, function (_d) {
|
|
728
|
-
switch (_d.label) {
|
|
729
|
-
case 0:
|
|
730
|
-
fullSyncInterval = params.fullSyncInterval;
|
|
731
|
-
ModelMetadataConstructor = this.modelClasses
|
|
732
|
-
.ModelMetadata;
|
|
733
|
-
models = [];
|
|
734
|
-
Object.values(this.schema.namespaces).forEach(function (namespace) {
|
|
735
|
-
Object.values(namespace.models)
|
|
736
|
-
.filter(function (_a) {
|
|
737
|
-
var syncable = _a.syncable;
|
|
738
|
-
return syncable;
|
|
739
|
-
})
|
|
740
|
-
.forEach(function (model) {
|
|
741
|
-
models.push([namespace.name, model]);
|
|
742
|
-
if (namespace.name === util_1.USER) {
|
|
743
|
-
var modelConstructor = _this.userModelClasses[model.name];
|
|
744
|
-
_this.modelSyncedStatus.set(modelConstructor, false);
|
|
745
|
-
}
|
|
746
|
-
});
|
|
747
|
-
});
|
|
748
|
-
promises = models.map(function (_a) {
|
|
749
|
-
var _b = tslib_1.__read(_a, 2), namespace = _b[0], model = _b[1];
|
|
750
|
-
return tslib_1.__awaiter(_this, void 0, void 0, function () {
|
|
751
|
-
var modelMetadata, syncPredicate, lastSyncPredicate, prevSyncPredicate, syncPredicateUpdated_1;
|
|
752
|
-
var _c, _d, _e, _f;
|
|
753
|
-
return tslib_1.__generator(this, function (_g) {
|
|
754
|
-
switch (_g.label) {
|
|
755
|
-
case 0: return [4 /*yield*/, this.getModelMetadata(namespace, model.name)];
|
|
756
|
-
case 1:
|
|
757
|
-
modelMetadata = _g.sent();
|
|
758
|
-
syncPredicate = predicates_1.ModelPredicateCreator.getPredicates(this.syncPredicates.get(model), false);
|
|
759
|
-
lastSyncPredicate = syncPredicate
|
|
760
|
-
? JSON.stringify(syncPredicate)
|
|
761
|
-
: null;
|
|
762
|
-
if (!(modelMetadata === undefined)) return [3 /*break*/, 3];
|
|
763
|
-
return [4 /*yield*/, this.storage.save(this.modelInstanceCreator(ModelMetadataConstructor, {
|
|
764
|
-
model: model.name,
|
|
765
|
-
namespace: namespace,
|
|
766
|
-
lastSync: null,
|
|
767
|
-
fullSyncInterval: fullSyncInterval,
|
|
768
|
-
lastFullSync: null,
|
|
769
|
-
lastSyncPredicate: lastSyncPredicate,
|
|
770
|
-
}), undefined, ownSymbol)];
|
|
771
|
-
case 2:
|
|
772
|
-
_c = tslib_1.__read.apply(void 0, [_g.sent(), 1]), _d = tslib_1.__read(_c[0], 1), savedModel = _d[0];
|
|
773
|
-
return [3 /*break*/, 5];
|
|
774
|
-
case 3:
|
|
775
|
-
prevSyncPredicate = modelMetadata.lastSyncPredicate
|
|
776
|
-
? modelMetadata.lastSyncPredicate
|
|
777
|
-
: null;
|
|
778
|
-
syncPredicateUpdated_1 = prevSyncPredicate !== lastSyncPredicate;
|
|
779
|
-
return [4 /*yield*/, this.storage.save(ModelMetadataConstructor.copyOf(modelMetadata, function (draft) {
|
|
780
|
-
draft.fullSyncInterval = fullSyncInterval;
|
|
781
|
-
// perform a base sync if the syncPredicate changed in between calls to DataStore.start
|
|
782
|
-
// ensures that the local store contains all the data specified by the syncExpression
|
|
783
|
-
if (syncPredicateUpdated_1) {
|
|
784
|
-
draft.lastSync = null;
|
|
785
|
-
draft.lastFullSync = null;
|
|
786
|
-
draft.lastSyncPredicate = lastSyncPredicate;
|
|
787
|
-
}
|
|
788
|
-
}))];
|
|
789
|
-
case 4:
|
|
790
|
-
_e = tslib_1.__read.apply(void 0, [_g.sent(), 1]), _f = tslib_1.__read(_e[0], 1), savedModel = _f[0];
|
|
791
|
-
_g.label = 5;
|
|
792
|
-
case 5: return [2 /*return*/, savedModel];
|
|
793
|
-
}
|
|
794
|
-
});
|
|
795
|
-
});
|
|
796
|
-
});
|
|
797
|
-
result = {};
|
|
798
|
-
_d.label = 1;
|
|
799
|
-
case 1:
|
|
800
|
-
_d.trys.push([1, 6, 7, 8]);
|
|
801
|
-
return [4 /*yield*/, Promise.all(promises)];
|
|
802
|
-
case 2:
|
|
803
|
-
_a = tslib_1.__values.apply(void 0, [_d.sent()]), _b = _a.next();
|
|
804
|
-
_d.label = 3;
|
|
805
|
-
case 3:
|
|
806
|
-
if (!!_b.done) return [3 /*break*/, 5];
|
|
807
|
-
modelMetadata = _b.value;
|
|
808
|
-
modelName = modelMetadata.model;
|
|
809
|
-
result[modelName] = modelMetadata;
|
|
810
|
-
_d.label = 4;
|
|
811
|
-
case 4:
|
|
812
|
-
_b = _a.next();
|
|
813
|
-
return [3 /*break*/, 3];
|
|
814
|
-
case 5: return [3 /*break*/, 8];
|
|
815
|
-
case 6:
|
|
816
|
-
e_2_1 = _d.sent();
|
|
817
|
-
e_2 = { error: e_2_1 };
|
|
818
|
-
return [3 /*break*/, 8];
|
|
819
|
-
case 7:
|
|
820
|
-
try {
|
|
821
|
-
if (_b && !_b.done && (_c = _a.return)) _c.call(_a);
|
|
822
|
-
}
|
|
823
|
-
finally { if (e_2) throw e_2.error; }
|
|
824
|
-
return [7 /*endfinally*/];
|
|
825
|
-
case 8: return [2 /*return*/, result];
|
|
468
|
+
async stop() {
|
|
469
|
+
logger.debug('stopping sync engine');
|
|
470
|
+
/**
|
|
471
|
+
* Gracefully disconnecting subscribers first just prevents *more* work
|
|
472
|
+
* from entering the pipelines.
|
|
473
|
+
*/
|
|
474
|
+
this.unsubscribeConnectivity();
|
|
475
|
+
/**
|
|
476
|
+
* Stop listening for websocket connection disruption
|
|
477
|
+
*/
|
|
478
|
+
this.stopDisruptionListener && this.stopDisruptionListener();
|
|
479
|
+
/**
|
|
480
|
+
* aggressively shut down any lingering background processes.
|
|
481
|
+
* some of this might be semi-redundant with unsubscribing. however,
|
|
482
|
+
* unsubscribing doesn't allow us to wait for settling.
|
|
483
|
+
* (Whereas `stop()` does.)
|
|
484
|
+
*/
|
|
485
|
+
await this.mutationsProcessor.stop();
|
|
486
|
+
await this.subscriptionsProcessor.stop();
|
|
487
|
+
await this.datastoreConnectivity.stop();
|
|
488
|
+
await this.syncQueriesProcessor.stop();
|
|
489
|
+
await this.runningProcesses.close();
|
|
490
|
+
await this.runningProcesses.open();
|
|
491
|
+
logger.debug('sync engine stopped and ready to restart');
|
|
492
|
+
}
|
|
493
|
+
async setupModels(params) {
|
|
494
|
+
const { fullSyncInterval } = params;
|
|
495
|
+
const ModelMetadataConstructor = this.modelClasses
|
|
496
|
+
.ModelMetadata;
|
|
497
|
+
const models = [];
|
|
498
|
+
let savedModel;
|
|
499
|
+
Object.values(this.schema.namespaces).forEach(namespace => {
|
|
500
|
+
Object.values(namespace.models)
|
|
501
|
+
.filter(({ syncable }) => syncable)
|
|
502
|
+
.forEach(model => {
|
|
503
|
+
models.push([namespace.name, model]);
|
|
504
|
+
if (namespace.name === util_1.USER) {
|
|
505
|
+
const modelConstructor = this.userModelClasses[model.name];
|
|
506
|
+
this.modelSyncedStatus.set(modelConstructor, false);
|
|
826
507
|
}
|
|
827
508
|
});
|
|
828
509
|
});
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
510
|
+
const promises = models.map(async ([namespace, model]) => {
|
|
511
|
+
const modelMetadata = await this.getModelMetadata(namespace, model.name);
|
|
512
|
+
const syncPredicate = predicates_1.ModelPredicateCreator.getPredicates(this.syncPredicates.get(model), false);
|
|
513
|
+
const lastSyncPredicate = syncPredicate
|
|
514
|
+
? JSON.stringify(syncPredicate)
|
|
515
|
+
: null;
|
|
516
|
+
if (modelMetadata === undefined) {
|
|
517
|
+
[[savedModel]] = await this.storage.save(this.modelInstanceCreator(ModelMetadataConstructor, {
|
|
518
|
+
model: model.name,
|
|
519
|
+
namespace,
|
|
520
|
+
lastSync: null,
|
|
521
|
+
fullSyncInterval,
|
|
522
|
+
lastFullSync: null,
|
|
523
|
+
lastSyncPredicate,
|
|
524
|
+
}), undefined, ownSymbol);
|
|
525
|
+
}
|
|
526
|
+
else {
|
|
527
|
+
const prevSyncPredicate = modelMetadata.lastSyncPredicate
|
|
528
|
+
? modelMetadata.lastSyncPredicate
|
|
529
|
+
: null;
|
|
530
|
+
const syncPredicateUpdated = prevSyncPredicate !== lastSyncPredicate;
|
|
531
|
+
[[savedModel]] = await this.storage.save(ModelMetadataConstructor.copyOf(modelMetadata, draft => {
|
|
532
|
+
draft.fullSyncInterval = fullSyncInterval;
|
|
533
|
+
// perform a base sync if the syncPredicate changed in between calls to DataStore.start
|
|
534
|
+
// ensures that the local store contains all the data specified by the syncExpression
|
|
535
|
+
if (syncPredicateUpdated) {
|
|
536
|
+
draft.lastSync = null;
|
|
537
|
+
draft.lastFullSync = null;
|
|
538
|
+
draft.lastSyncPredicate = lastSyncPredicate;
|
|
539
|
+
}
|
|
540
|
+
}));
|
|
541
|
+
}
|
|
542
|
+
return savedModel;
|
|
844
543
|
});
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
544
|
+
const result = {};
|
|
545
|
+
for (const modelMetadata of await Promise.all(promises)) {
|
|
546
|
+
const { model: modelName } = modelMetadata;
|
|
547
|
+
result[modelName] = modelMetadata;
|
|
548
|
+
}
|
|
549
|
+
return result;
|
|
550
|
+
}
|
|
551
|
+
async getModelsMetadata() {
|
|
552
|
+
const ModelMetadata = this.modelClasses
|
|
553
|
+
.ModelMetadata;
|
|
554
|
+
const modelsMetadata = await this.storage.query(ModelMetadata);
|
|
555
|
+
return modelsMetadata;
|
|
556
|
+
}
|
|
557
|
+
async getModelMetadata(namespace, model) {
|
|
558
|
+
const ModelMetadata = this.modelClasses
|
|
559
|
+
.ModelMetadata;
|
|
560
|
+
const predicate = predicates_1.ModelPredicateCreator.createFromAST(this.schema.namespaces[util_1.SYNC].models[ModelMetadata.name], { and: [{ namespace: { eq: namespace } }, { model: { eq: model } }] });
|
|
561
|
+
const [modelMetadata] = await this.storage.query(ModelMetadata, predicate, {
|
|
562
|
+
page: 0,
|
|
563
|
+
limit: 1,
|
|
864
564
|
});
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
565
|
+
return modelMetadata;
|
|
566
|
+
}
|
|
567
|
+
getModelDefinition(modelConstructor) {
|
|
568
|
+
const namespaceName = this.namespaceResolver(modelConstructor);
|
|
569
|
+
const modelDefinition = this.schema.namespaces[namespaceName].models[modelConstructor.name];
|
|
869
570
|
return modelDefinition;
|
|
870
|
-
}
|
|
871
|
-
|
|
872
|
-
|
|
571
|
+
}
|
|
572
|
+
static getNamespace() {
|
|
573
|
+
const namespace = {
|
|
873
574
|
name: util_1.SYNC,
|
|
874
575
|
relationships: {},
|
|
875
576
|
enums: {
|
|
@@ -977,7 +678,7 @@ var SyncEngine = /** @class */ (function () {
|
|
|
977
678
|
},
|
|
978
679
|
};
|
|
979
680
|
return namespace;
|
|
980
|
-
}
|
|
681
|
+
}
|
|
981
682
|
/**
|
|
982
683
|
* listen for websocket connection disruption
|
|
983
684
|
*
|
|
@@ -985,44 +686,38 @@ var SyncEngine = /** @class */ (function () {
|
|
|
985
686
|
* from AppSync were missed. A sync needs to be triggered to
|
|
986
687
|
* retrieve the missed data.
|
|
987
688
|
*/
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
return core_1.Hub.listen('api', function (data) {
|
|
689
|
+
startDisruptionListener() {
|
|
690
|
+
return core_1.Hub.listen('api', (data) => {
|
|
991
691
|
if (data.source === 'PubSub' &&
|
|
992
|
-
data.payload.event ===
|
|
993
|
-
|
|
692
|
+
data.payload.event === api_graphql_1.CONNECTION_STATE_CHANGE) {
|
|
693
|
+
const connectionState = data.payload.data
|
|
994
694
|
.connectionState;
|
|
995
695
|
switch (connectionState) {
|
|
996
696
|
// Do not need to listen for ConnectionDisruptedPendingNetwork
|
|
997
697
|
// Normal network reconnection logic will handle the sync
|
|
998
|
-
case
|
|
999
|
-
|
|
698
|
+
case api_graphql_1.ConnectionState.ConnectionDisrupted:
|
|
699
|
+
this.connectionDisrupted = true;
|
|
1000
700
|
break;
|
|
1001
|
-
case
|
|
1002
|
-
if (
|
|
1003
|
-
|
|
701
|
+
case api_graphql_1.ConnectionState.Connected:
|
|
702
|
+
if (this.connectionDisrupted) {
|
|
703
|
+
this.scheduleSync();
|
|
1004
704
|
}
|
|
1005
|
-
|
|
705
|
+
this.connectionDisrupted = false;
|
|
1006
706
|
break;
|
|
1007
707
|
}
|
|
1008
708
|
}
|
|
1009
709
|
});
|
|
1010
|
-
}
|
|
710
|
+
}
|
|
1011
711
|
/*
|
|
1012
712
|
* Schedule a sync to start when syncQueriesObservable enters sleep state
|
|
1013
713
|
* Start sync immediately if syncQueriesObservable is already in sleep state
|
|
1014
714
|
*/
|
|
1015
|
-
|
|
1016
|
-
var _this = this;
|
|
715
|
+
scheduleSync() {
|
|
1017
716
|
return (this.runningProcesses.isOpen &&
|
|
1018
|
-
this.runningProcesses.add(
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
};
|
|
1025
|
-
return SyncEngine;
|
|
1026
|
-
}());
|
|
717
|
+
this.runningProcesses.add(() => this.waitForSleepState.then(() => {
|
|
718
|
+
// unsleepSyncQueriesObservable will be set if waitForSleepState has resolved
|
|
719
|
+
this.unsleepSyncQueriesObservable();
|
|
720
|
+
})));
|
|
721
|
+
}
|
|
722
|
+
}
|
|
1027
723
|
exports.SyncEngine = SyncEngine;
|
|
1028
|
-
//# sourceMappingURL=index.js.map
|