@aws-amplify/datastore 3.12.6-next.20 → 3.12.6-next.32

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.
Files changed (144) hide show
  1. package/CHANGELOG.md +58 -0
  2. package/lib/authModeStrategies/multiAuthStrategy.js +13 -2
  3. package/lib/authModeStrategies/multiAuthStrategy.js.map +1 -1
  4. package/lib/datastore/datastore.js +648 -344
  5. package/lib/datastore/datastore.js.map +1 -1
  6. package/lib/predicates/index.js +12 -2
  7. package/lib/predicates/index.js.map +1 -1
  8. package/lib/storage/adapter/AsyncStorageAdapter.js +354 -203
  9. package/lib/storage/adapter/AsyncStorageAdapter.js.map +1 -1
  10. package/lib/storage/adapter/AsyncStorageDatabase.js +65 -28
  11. package/lib/storage/adapter/AsyncStorageDatabase.js.map +1 -1
  12. package/lib/storage/adapter/IndexedDBAdapter.js +444 -271
  13. package/lib/storage/adapter/IndexedDBAdapter.js.map +1 -1
  14. package/lib/storage/storage.js +93 -28
  15. package/lib/storage/storage.js.map +1 -1
  16. package/lib/sync/datastoreConnectivity.js +9 -0
  17. package/lib/sync/datastoreConnectivity.js.map +1 -1
  18. package/lib/sync/index.js +522 -397
  19. package/lib/sync/index.js.map +1 -1
  20. package/lib/sync/merger.js +13 -6
  21. package/lib/sync/merger.js.map +1 -1
  22. package/lib/sync/outbox.js +77 -71
  23. package/lib/sync/outbox.js.map +1 -1
  24. package/lib/sync/processors/mutation.js +269 -209
  25. package/lib/sync/processors/mutation.js.map +1 -1
  26. package/lib/sync/processors/subscription.js +213 -178
  27. package/lib/sync/processors/subscription.js.map +1 -1
  28. package/lib/sync/processors/sync.js +126 -121
  29. package/lib/sync/processors/sync.js.map +1 -1
  30. package/lib/sync/utils.js +43 -8
  31. package/lib/sync/utils.js.map +1 -1
  32. package/lib/types.js +10 -1
  33. package/lib/types.js.map +1 -1
  34. package/lib/util.js +419 -166
  35. package/lib/util.js.map +1 -1
  36. package/lib-esm/authModeStrategies/multiAuthStrategy.d.ts +11 -0
  37. package/lib-esm/authModeStrategies/multiAuthStrategy.js +12 -1
  38. package/lib-esm/authModeStrategies/multiAuthStrategy.js.map +1 -1
  39. package/lib-esm/datastore/datastore.d.ts +107 -17
  40. package/lib-esm/datastore/datastore.js +648 -344
  41. package/lib-esm/datastore/datastore.js.map +1 -1
  42. package/lib-esm/index.d.ts +3 -19
  43. package/lib-esm/predicates/index.d.ts +3 -2
  44. package/lib-esm/predicates/index.js +13 -3
  45. package/lib-esm/predicates/index.js.map +1 -1
  46. package/lib-esm/storage/adapter/AsyncStorageAdapter.d.ts +4 -3
  47. package/lib-esm/storage/adapter/AsyncStorageAdapter.js +355 -204
  48. package/lib-esm/storage/adapter/AsyncStorageAdapter.js.map +1 -1
  49. package/lib-esm/storage/adapter/AsyncStorageDatabase.d.ts +14 -4
  50. package/lib-esm/storage/adapter/AsyncStorageDatabase.js +66 -29
  51. package/lib-esm/storage/adapter/AsyncStorageDatabase.js.map +1 -1
  52. package/lib-esm/storage/adapter/IndexedDBAdapter.d.ts +26 -4
  53. package/lib-esm/storage/adapter/IndexedDBAdapter.js +445 -272
  54. package/lib-esm/storage/adapter/IndexedDBAdapter.js.map +1 -1
  55. package/lib-esm/storage/adapter/index.d.ts +1 -1
  56. package/lib-esm/storage/storage.d.ts +1 -1
  57. package/lib-esm/storage/storage.js +93 -28
  58. package/lib-esm/storage/storage.js.map +1 -1
  59. package/lib-esm/sync/datastoreConnectivity.d.ts +1 -0
  60. package/lib-esm/sync/datastoreConnectivity.js +10 -1
  61. package/lib-esm/sync/datastoreConnectivity.js.map +1 -1
  62. package/lib-esm/sync/index.d.ts +31 -5
  63. package/lib-esm/sync/index.js +524 -399
  64. package/lib-esm/sync/index.js.map +1 -1
  65. package/lib-esm/sync/merger.d.ts +9 -3
  66. package/lib-esm/sync/merger.js +13 -6
  67. package/lib-esm/sync/merger.js.map +1 -1
  68. package/lib-esm/sync/outbox.d.ts +2 -2
  69. package/lib-esm/sync/outbox.js +78 -72
  70. package/lib-esm/sync/outbox.js.map +1 -1
  71. package/lib-esm/sync/processors/mutation.d.ts +2 -0
  72. package/lib-esm/sync/processors/mutation.js +270 -210
  73. package/lib-esm/sync/processors/mutation.js.map +1 -1
  74. package/lib-esm/sync/processors/subscription.d.ts +2 -0
  75. package/lib-esm/sync/processors/subscription.js +213 -178
  76. package/lib-esm/sync/processors/subscription.js.map +1 -1
  77. package/lib-esm/sync/processors/sync.d.ts +2 -1
  78. package/lib-esm/sync/processors/sync.js +126 -121
  79. package/lib-esm/sync/processors/sync.js.map +1 -1
  80. package/lib-esm/sync/utils.d.ts +3 -2
  81. package/lib-esm/sync/utils.js +45 -11
  82. package/lib-esm/sync/utils.js.map +1 -1
  83. package/lib-esm/types.d.ts +65 -26
  84. package/lib-esm/types.js +9 -2
  85. package/lib-esm/types.js.map +1 -1
  86. package/lib-esm/util.d.ts +67 -24
  87. package/lib-esm/util.js +419 -166
  88. package/lib-esm/util.js.map +1 -1
  89. package/package.json +13 -7
  90. package/src/authModeStrategies/multiAuthStrategy.ts +12 -1
  91. package/src/datastore/datastore.ts +798 -397
  92. package/src/predicates/index.ts +32 -10
  93. package/src/storage/adapter/AsyncStorageAdapter.ts +309 -93
  94. package/src/storage/adapter/AsyncStorageDatabase.ts +74 -26
  95. package/src/storage/adapter/IndexedDBAdapter.ts +358 -134
  96. package/src/storage/adapter/index.ts +1 -1
  97. package/src/storage/storage.ts +69 -22
  98. package/src/sync/datastoreConnectivity.ts +6 -0
  99. package/src/sync/index.ts +521 -412
  100. package/src/sync/merger.ts +20 -4
  101. package/src/sync/outbox.ts +22 -9
  102. package/src/sync/processors/mutation.ts +188 -150
  103. package/src/sync/processors/subscription.ts +289 -253
  104. package/src/sync/processors/sync.ts +151 -138
  105. package/src/sync/utils.ts +67 -12
  106. package/src/types.ts +182 -30
  107. package/src/util.ts +505 -176
  108. package/build.js +0 -5
  109. package/dist/aws-amplify-datastore.js +0 -83311
  110. package/dist/aws-amplify-datastore.js.map +0 -1
  111. package/dist/aws-amplify-datastore.min.js +0 -168
  112. package/dist/aws-amplify-datastore.min.js.map +0 -1
  113. package/index.js +0 -7
  114. package/lib/authModeStrategies/defaultAuthStrategy.d.ts +0 -2
  115. package/lib/authModeStrategies/index.d.ts +0 -2
  116. package/lib/authModeStrategies/multiAuthStrategy.d.ts +0 -2
  117. package/lib/datastore/datastore.d.ts +0 -66
  118. package/lib/index.d.ts +0 -31
  119. package/lib/predicates/index.d.ts +0 -15
  120. package/lib/predicates/sort.d.ts +0 -8
  121. package/lib/ssr/index.d.ts +0 -3
  122. package/lib/storage/adapter/AsyncStorageAdapter.d.ts +0 -40
  123. package/lib/storage/adapter/AsyncStorageDatabase.d.ts +0 -29
  124. package/lib/storage/adapter/InMemoryStore.d.ts +0 -11
  125. package/lib/storage/adapter/InMemoryStore.native.d.ts +0 -1
  126. package/lib/storage/adapter/IndexedDBAdapter.d.ts +0 -37
  127. package/lib/storage/adapter/getDefaultAdapter/index.d.ts +0 -3
  128. package/lib/storage/adapter/getDefaultAdapter/index.native.d.ts +0 -3
  129. package/lib/storage/adapter/index.d.ts +0 -9
  130. package/lib/storage/storage.d.ts +0 -49
  131. package/lib/sync/datastoreConnectivity.d.ts +0 -15
  132. package/lib/sync/datastoreReachability/index.d.ts +0 -3
  133. package/lib/sync/datastoreReachability/index.native.d.ts +0 -3
  134. package/lib/sync/index.d.ts +0 -63
  135. package/lib/sync/merger.d.ts +0 -11
  136. package/lib/sync/outbox.d.ts +0 -27
  137. package/lib/sync/processors/errorMaps.d.ts +0 -17
  138. package/lib/sync/processors/mutation.d.ts +0 -56
  139. package/lib/sync/processors/subscription.d.ts +0 -31
  140. package/lib/sync/processors/sync.d.ts +0 -27
  141. package/lib/sync/utils.d.ts +0 -41
  142. package/lib/types.d.ts +0 -462
  143. package/lib/util.d.ts +0 -113
  144. package/webpack.config.dev.js +0 -6
package/lib/sync/index.js CHANGED
@@ -31,7 +31,7 @@ var ControlMessage;
31
31
  ControlMessage["SYNC_ENGINE_READY"] = "ready";
32
32
  })(ControlMessage = exports.ControlMessage || (exports.ControlMessage = {}));
33
33
  var SyncEngine = /** @class */ (function () {
34
- function SyncEngine(schema, namespaceResolver, modelClasses, userModelClasses, storage, modelInstanceCreator, conflictHandler, errorHandler, syncPredicates, amplifyConfig, authModeStrategy, amplifyContext) {
34
+ function SyncEngine(schema, namespaceResolver, modelClasses, userModelClasses, storage, modelInstanceCreator, conflictHandler, errorHandler, syncPredicates, amplifyConfig, authModeStrategy, amplifyContext, connectivityMonitor) {
35
35
  if (amplifyConfig === void 0) { amplifyConfig = {}; }
36
36
  this.schema = schema;
37
37
  this.namespaceResolver = namespaceResolver;
@@ -43,15 +43,18 @@ var SyncEngine = /** @class */ (function () {
43
43
  this.amplifyConfig = amplifyConfig;
44
44
  this.authModeStrategy = authModeStrategy;
45
45
  this.amplifyContext = amplifyContext;
46
+ this.connectivityMonitor = connectivityMonitor;
46
47
  this.online = false;
47
48
  this.modelSyncedStatus = new WeakMap();
49
+ this.runningProcesses = new core_1.BackgroundProcessManager();
48
50
  var MutationEvent = this.modelClasses['MutationEvent'];
49
51
  this.outbox = new outbox_1.MutationEventOutbox(this.schema, MutationEvent, modelInstanceCreator, ownSymbol);
50
52
  this.modelMerger = new merger_1.ModelMerger(this.outbox, ownSymbol);
51
53
  this.syncQueriesProcessor = new sync_1.SyncProcessor(this.schema, this.syncPredicates, this.amplifyConfig, this.authModeStrategy, errorHandler, this.amplifyContext);
52
54
  this.subscriptionsProcessor = new subscription_1.SubscriptionProcessor(this.schema, this.syncPredicates, this.amplifyConfig, this.authModeStrategy, errorHandler, this.amplifyContext);
53
55
  this.mutationsProcessor = new mutation_1.MutationProcessor(this.schema, this.storage, this.userModelClasses, this.outbox, this.modelInstanceCreator, MutationEvent, this.amplifyConfig, this.authModeStrategy, errorHandler, conflictHandler, this.amplifyContext);
54
- this.datastoreConnectivity = new datastoreConnectivity_1.default();
56
+ this.datastoreConnectivity =
57
+ this.connectivityMonitor || new datastoreConnectivity_1.default();
55
58
  }
56
59
  SyncEngine.prototype.getModelSyncedStatus = function (modelConstructor) {
57
60
  return this.modelSyncedStatus.get(modelConstructor);
@@ -61,7 +64,7 @@ var SyncEngine = /** @class */ (function () {
61
64
  return new zen_observable_ts_1.default(function (observer) {
62
65
  logger.log('starting sync engine...');
63
66
  var subscriptions = [];
64
- (function () { return tslib_1.__awaiter(_this, void 0, void 0, function () {
67
+ _this.runningProcesses.add(function () { return tslib_1.__awaiter(_this, void 0, void 0, function () {
65
68
  var err_1, startPromise, hasMutationsInOutbox;
66
69
  var _this = this;
67
70
  return tslib_1.__generator(this, function (_a) {
@@ -77,154 +80,188 @@ var SyncEngine = /** @class */ (function () {
77
80
  observer.error(err_1);
78
81
  return [2 /*return*/];
79
82
  case 3:
80
- startPromise = new Promise(function (resolve) {
83
+ startPromise = new Promise(function (doneStarting, failedStarting) {
81
84
  _this.datastoreConnectivity.status().subscribe(function (_a) {
82
85
  var online = _a.online;
83
86
  return tslib_1.__awaiter(_this, void 0, void 0, function () {
84
- var ctlSubsObservable_1, dataSubsObservable, err_2, error_1;
85
- var _b;
86
87
  var _this = this;
87
- return tslib_1.__generator(this, function (_c) {
88
- switch (_c.label) {
89
- case 0:
90
- if (!(online && !this.online)) return [3 /*break*/, 10];
91
- this.online = online;
92
- observer.next({
93
- type: ControlMessage.SYNC_ENGINE_NETWORK_STATUS,
94
- data: {
95
- active: this.online,
96
- },
97
- });
98
- dataSubsObservable = void 0;
99
- if (!isNode) return [3 /*break*/, 1];
100
- logger.warn('Realtime disabled when in a server-side environment');
101
- return [3 /*break*/, 6];
102
- case 1:
103
- //#region GraphQL Subscriptions
104
- _b = tslib_1.__read(this.subscriptionsProcessor.start(), 2),
105
- // const ctlObservable: Observable<CONTROL_MSG>
106
- ctlSubsObservable_1 = _b[0],
107
- // const dataObservable: Observable<[TransformerMutationType, SchemaModel, Readonly<{
108
- // id: string;
109
- // } & Record<string, any>>]>
110
- dataSubsObservable = _b[1];
111
- _c.label = 2;
112
- case 2:
113
- _c.trys.push([2, 4, , 5]);
114
- return [4 /*yield*/, new Promise(function (resolve, reject) {
115
- var ctlSubsSubscription = ctlSubsObservable_1.subscribe({
116
- next: function (msg) {
117
- if (msg === subscription_1.CONTROL_MSG.CONNECTED) {
118
- resolve();
88
+ return tslib_1.__generator(this, function (_b) {
89
+ return [2 /*return*/, this.runningProcesses.isOpen &&
90
+ this.runningProcesses.add(function (onTerminate) { return tslib_1.__awaiter(_this, void 0, void 0, function () {
91
+ var ctlSubsObservable_1, dataSubsObservable, err_2, error_1;
92
+ var _a;
93
+ var _this = this;
94
+ return tslib_1.__generator(this, function (_b) {
95
+ switch (_b.label) {
96
+ case 0:
97
+ if (!(online && !this.online)) return [3 /*break*/, 10];
98
+ this.online = online;
99
+ observer.next({
100
+ type: ControlMessage.SYNC_ENGINE_NETWORK_STATUS,
101
+ data: {
102
+ active: this.online,
103
+ },
104
+ });
105
+ dataSubsObservable = void 0;
106
+ if (!isNode) return [3 /*break*/, 1];
107
+ logger.warn('Realtime disabled when in a server-side environment');
108
+ return [3 /*break*/, 6];
109
+ case 1:
110
+ //#region GraphQL Subscriptions
111
+ _a = tslib_1.__read(this.subscriptionsProcessor.start(), 2),
112
+ // const ctlObservable: Observable<CONTROL_MSG>
113
+ ctlSubsObservable_1 = _a[0],
114
+ // const dataObservable: Observable<[TransformerMutationType, SchemaModel, Readonly<{
115
+ // id: string;
116
+ // } & Record<string, any>>]>
117
+ dataSubsObservable = _a[1];
118
+ _b.label = 2;
119
+ case 2:
120
+ _b.trys.push([2, 4, , 5]);
121
+ return [4 /*yield*/, new Promise(function (resolve, reject) {
122
+ onTerminate.then(reject);
123
+ var ctlSubsSubscription = ctlSubsObservable_1.subscribe({
124
+ next: function (msg) {
125
+ if (msg === subscription_1.CONTROL_MSG.CONNECTED) {
126
+ resolve();
127
+ }
128
+ },
129
+ error: function (err) {
130
+ reject(err);
131
+ var handleDisconnect = _this.disconnectionHandler();
132
+ handleDisconnect(err);
133
+ },
134
+ });
135
+ subscriptions.push(ctlSubsSubscription);
136
+ })];
137
+ case 3:
138
+ _b.sent();
139
+ return [3 /*break*/, 5];
140
+ case 4:
141
+ err_2 = _b.sent();
142
+ observer.error(err_2);
143
+ failedStarting();
144
+ return [2 /*return*/];
145
+ case 5:
146
+ logger.log('Realtime ready');
147
+ observer.next({
148
+ type: ControlMessage.SYNC_ENGINE_SUBSCRIPTIONS_ESTABLISHED,
149
+ });
150
+ _b.label = 6;
151
+ case 6:
152
+ _b.trys.push([6, 8, , 9]);
153
+ return [4 /*yield*/, new Promise(function (resolve, reject) {
154
+ var syncQuerySubscription = _this.syncQueriesObservable().subscribe({
155
+ next: function (message) {
156
+ var type = message.type;
157
+ if (type ===
158
+ ControlMessage.SYNC_ENGINE_SYNC_QUERIES_READY) {
159
+ resolve();
160
+ }
161
+ observer.next(message);
162
+ },
163
+ complete: function () {
164
+ resolve();
165
+ },
166
+ error: function (error) {
167
+ reject(error);
168
+ },
169
+ });
170
+ if (syncQuerySubscription) {
171
+ subscriptions.push(syncQuerySubscription);
172
+ }
173
+ })];
174
+ case 7:
175
+ _b.sent();
176
+ return [3 /*break*/, 9];
177
+ case 8:
178
+ error_1 = _b.sent();
179
+ observer.error(error_1);
180
+ failedStarting();
181
+ return [2 /*return*/];
182
+ case 9:
183
+ //#endregion
184
+ //#region process mutations (outbox)
185
+ subscriptions.push(this.mutationsProcessor
186
+ .start()
187
+ .subscribe(function (_a) {
188
+ var modelDefinition = _a.modelDefinition, item = _a.model, hasMore = _a.hasMore;
189
+ return _this.runningProcesses.add(function () { return tslib_1.__awaiter(_this, void 0, void 0, function () {
190
+ var modelConstructor, model;
191
+ var _this = this;
192
+ return tslib_1.__generator(this, function (_a) {
193
+ switch (_a.label) {
194
+ case 0:
195
+ modelConstructor = this.userModelClasses[modelDefinition.name];
196
+ model = this.modelInstanceCreator(modelConstructor, item);
197
+ return [4 /*yield*/, this.storage.runExclusive(function (storage) {
198
+ return _this.modelMerger.merge(storage, model, modelDefinition);
199
+ })];
200
+ case 1:
201
+ _a.sent();
202
+ observer.next({
203
+ type: ControlMessage.SYNC_ENGINE_OUTBOX_MUTATION_PROCESSED,
204
+ data: {
205
+ model: modelConstructor,
206
+ element: model,
207
+ },
208
+ });
209
+ observer.next({
210
+ type: ControlMessage.SYNC_ENGINE_OUTBOX_STATUS,
211
+ data: {
212
+ isEmpty: !hasMore,
213
+ },
214
+ });
215
+ return [2 /*return*/];
216
+ }
217
+ });
218
+ }); }, 'mutation processor event');
219
+ }));
220
+ //#endregion
221
+ //#region Merge subscriptions buffer
222
+ // TODO: extract to function
223
+ if (!isNode) {
224
+ subscriptions.push(dataSubsObservable.subscribe(function (_a) {
225
+ var _b = tslib_1.__read(_a, 3), _transformerMutationType = _b[0], modelDefinition = _b[1], item = _b[2];
226
+ return _this.runningProcesses.add(function () { return tslib_1.__awaiter(_this, void 0, void 0, function () {
227
+ var modelConstructor, model;
228
+ var _this = this;
229
+ return tslib_1.__generator(this, function (_a) {
230
+ switch (_a.label) {
231
+ case 0:
232
+ modelConstructor = this.userModelClasses[modelDefinition.name];
233
+ model = this.modelInstanceCreator(modelConstructor, item);
234
+ return [4 /*yield*/, this.storage.runExclusive(function (storage) {
235
+ return _this.modelMerger.merge(storage, model, modelDefinition);
236
+ })];
237
+ case 1:
238
+ _a.sent();
239
+ return [2 /*return*/];
240
+ }
241
+ });
242
+ }); }, 'subscription dataSubsObservable event');
243
+ }));
119
244
  }
120
- },
121
- error: function (err) {
122
- reject(err);
123
- var handleDisconnect = _this.disconnectionHandler();
124
- handleDisconnect(err);
125
- },
126
- });
127
- subscriptions.push(ctlSubsSubscription);
128
- })];
129
- case 3:
130
- _c.sent();
131
- return [3 /*break*/, 5];
132
- case 4:
133
- err_2 = _c.sent();
134
- observer.error(err_2);
135
- return [2 /*return*/];
136
- case 5:
137
- logger.log('Realtime ready');
138
- observer.next({
139
- type: ControlMessage.SYNC_ENGINE_SUBSCRIPTIONS_ESTABLISHED,
140
- });
141
- _c.label = 6;
142
- case 6:
143
- _c.trys.push([6, 8, , 9]);
144
- return [4 /*yield*/, new Promise(function (resolve, reject) {
145
- var syncQuerySubscription = _this.syncQueriesObservable().subscribe({
146
- next: function (message) {
147
- var type = message.type;
148
- if (type === ControlMessage.SYNC_ENGINE_SYNC_QUERIES_READY) {
149
- resolve();
245
+ return [3 /*break*/, 11];
246
+ case 10:
247
+ if (!online) {
248
+ this.online = online;
249
+ observer.next({
250
+ type: ControlMessage.SYNC_ENGINE_NETWORK_STATUS,
251
+ data: {
252
+ active: this.online,
253
+ },
254
+ });
255
+ subscriptions.forEach(function (sub) { return sub.unsubscribe(); });
256
+ subscriptions = [];
150
257
  }
151
- observer.next(message);
152
- },
153
- complete: function () {
154
- resolve();
155
- },
156
- error: function (error) {
157
- reject(error);
158
- },
159
- });
160
- if (syncQuerySubscription) {
161
- subscriptions.push(syncQuerySubscription);
258
+ _b.label = 11;
259
+ case 11:
260
+ doneStarting();
261
+ return [2 /*return*/];
162
262
  }
163
- })];
164
- case 7:
165
- _c.sent();
166
- return [3 /*break*/, 9];
167
- case 8:
168
- error_1 = _c.sent();
169
- observer.error(error_1);
170
- return [2 /*return*/];
171
- case 9:
172
- //#endregion
173
- //#region process mutations
174
- subscriptions.push(this.mutationsProcessor
175
- .start()
176
- .subscribe(function (_a) {
177
- var modelDefinition = _a.modelDefinition, item = _a.model, hasMore = _a.hasMore;
178
- var modelConstructor = _this.userModelClasses[modelDefinition.name];
179
- var model = _this.modelInstanceCreator(modelConstructor, item);
180
- _this.storage.runExclusive(function (storage) {
181
- return _this.modelMerger.merge(storage, model);
182
- });
183
- observer.next({
184
- type: ControlMessage.SYNC_ENGINE_OUTBOX_MUTATION_PROCESSED,
185
- data: {
186
- model: modelConstructor,
187
- element: model,
188
- },
189
- });
190
- observer.next({
191
- type: ControlMessage.SYNC_ENGINE_OUTBOX_STATUS,
192
- data: {
193
- isEmpty: !hasMore,
194
- },
195
263
  });
196
- }));
197
- //#endregion
198
- //#region Merge subscriptions buffer
199
- // TODO: extract to function
200
- if (!isNode) {
201
- subscriptions.push(dataSubsObservable.subscribe(function (_a) {
202
- var _b = tslib_1.__read(_a, 3), _transformerMutationType = _b[0], modelDefinition = _b[1], item = _b[2];
203
- var modelConstructor = _this.userModelClasses[modelDefinition.name];
204
- var model = _this.modelInstanceCreator(modelConstructor, item);
205
- _this.storage.runExclusive(function (storage) {
206
- return _this.modelMerger.merge(storage, model);
207
- });
208
- }));
209
- }
210
- return [3 /*break*/, 11];
211
- case 10:
212
- if (!online) {
213
- this.online = online;
214
- observer.next({
215
- type: ControlMessage.SYNC_ENGINE_NETWORK_STATUS,
216
- data: {
217
- active: this.online,
218
- },
219
- });
220
- subscriptions.forEach(function (sub) { return sub.unsubscribe(); });
221
- subscriptions = [];
222
- }
223
- _c.label = 11;
224
- case 11:
225
- resolve();
226
- return [2 /*return*/];
227
- }
264
+ }); }, 'datastore connectivity event')];
228
265
  });
229
266
  });
230
267
  });
@@ -240,38 +277,44 @@ var SyncEngine = /** @class */ (function () {
240
277
  next: function (_a) {
241
278
  var opType = _a.opType, model = _a.model, element = _a.element, condition = _a.condition;
242
279
  return tslib_1.__awaiter(_this, void 0, void 0, function () {
243
- var namespace, MutationEventConstructor, graphQLCondition, mutationEvent;
280
+ var _this = this;
244
281
  return tslib_1.__generator(this, function (_b) {
245
- switch (_b.label) {
246
- case 0:
247
- namespace = this.schema.namespaces[this.namespaceResolver(model)];
248
- MutationEventConstructor = this.modelClasses['MutationEvent'];
249
- graphQLCondition = utils_1.predicateToGraphQLCondition(condition);
250
- mutationEvent = utils_1.createMutationInstanceFromModelOperation(namespace.relationships, this.getModelDefinition(model), opType, model, element, graphQLCondition, MutationEventConstructor, this.modelInstanceCreator);
251
- return [4 /*yield*/, this.outbox.enqueue(this.storage, mutationEvent)];
252
- case 1:
253
- _b.sent();
254
- observer.next({
255
- type: ControlMessage.SYNC_ENGINE_OUTBOX_MUTATION_ENQUEUED,
256
- data: {
257
- model: model,
258
- element: element,
259
- },
260
- });
261
- observer.next({
262
- type: ControlMessage.SYNC_ENGINE_OUTBOX_STATUS,
263
- data: {
264
- isEmpty: false,
265
- },
282
+ return [2 /*return*/, this.runningProcesses.add(function () { return tslib_1.__awaiter(_this, void 0, void 0, function () {
283
+ var namespace, MutationEventConstructor, modelDefinition, graphQLCondition, mutationEvent;
284
+ return tslib_1.__generator(this, function (_a) {
285
+ switch (_a.label) {
286
+ case 0:
287
+ namespace = this.schema.namespaces[this.namespaceResolver(model)];
288
+ MutationEventConstructor = this.modelClasses['MutationEvent'];
289
+ modelDefinition = this.getModelDefinition(model);
290
+ graphQLCondition = utils_1.predicateToGraphQLCondition(condition, modelDefinition);
291
+ mutationEvent = utils_1.createMutationInstanceFromModelOperation(namespace.relationships, this.getModelDefinition(model), opType, model, element, graphQLCondition, MutationEventConstructor, this.modelInstanceCreator);
292
+ return [4 /*yield*/, this.outbox.enqueue(this.storage, mutationEvent)];
293
+ case 1:
294
+ _a.sent();
295
+ observer.next({
296
+ type: ControlMessage.SYNC_ENGINE_OUTBOX_MUTATION_ENQUEUED,
297
+ data: {
298
+ model: model,
299
+ element: element,
300
+ },
301
+ });
302
+ observer.next({
303
+ type: ControlMessage.SYNC_ENGINE_OUTBOX_STATUS,
304
+ data: {
305
+ isEmpty: false,
306
+ },
307
+ });
308
+ return [4 /*yield*/, startPromise];
309
+ case 2:
310
+ _a.sent();
311
+ if (this.online) {
312
+ this.mutationsProcessor.resume();
313
+ }
314
+ return [2 /*return*/];
315
+ }
266
316
  });
267
- return [4 /*yield*/, startPromise];
268
- case 2:
269
- _b.sent();
270
- if (this.online) {
271
- this.mutationsProcessor.resume();
272
- }
273
- return [2 /*return*/];
274
- }
317
+ }); }, 'storage event')];
275
318
  });
276
319
  });
277
320
  },
@@ -297,10 +340,7 @@ var SyncEngine = /** @class */ (function () {
297
340
  return [2 /*return*/];
298
341
  }
299
342
  });
300
- }); })();
301
- return function () {
302
- subscriptions.forEach(function (sub) { return sub.unsubscribe(); });
303
- };
343
+ }); }, 'sync start');
304
344
  });
305
345
  };
306
346
  SyncEngine.prototype.getModelsMetadataWithNextFullSync = function (currentTimeStamp) {
@@ -311,7 +351,7 @@ var SyncEngine = /** @class */ (function () {
311
351
  switch (_b.label) {
312
352
  case 0:
313
353
  _a = Map.bind;
314
- return [4 /*yield*/, this.getModelsMetadata()];
354
+ return [4 /*yield*/, this.runningProcesses.add(function () { return _this.getModelsMetadata(); }, 'sync/index getModelsMetadataWithNextFullSync')];
315
355
  case 1:
316
356
  modelLastSync = new (_a.apply(Map, [void 0, (_b.sent()).map(function (_a) {
317
357
  var namespace = _a.namespace, model = _a.model, lastSync = _a.lastSync, lastFullSync = _a.lastFullSync, fullSyncInterval = _a.fullSyncInterval, lastSyncPredicate = _a.lastSyncPredicate;
@@ -336,227 +376,261 @@ var SyncEngine = /** @class */ (function () {
336
376
  }
337
377
  return new zen_observable_ts_1.default(function (observer) {
338
378
  var syncQueriesSubscription;
339
- var waitTimeoutId;
340
- (function () { return tslib_1.__awaiter(_this, void 0, void 0, function () {
341
- var _loop_1, this_1;
342
- var _this = this;
343
- return tslib_1.__generator(this, function (_a) {
344
- switch (_a.label) {
345
- case 0:
346
- _loop_1 = function () {
347
- var count, modelLastSync, paginatingModels, newestFullSyncStartedAt, theInterval, start, duration, newestStartedAt, msNextFullSync;
348
- return tslib_1.__generator(this, function (_a) {
349
- switch (_a.label) {
350
- case 0:
351
- count = new WeakMap();
352
- return [4 /*yield*/, this_1.getModelsMetadataWithNextFullSync(Date.now())];
353
- case 1:
354
- modelLastSync = _a.sent();
355
- paginatingModels = new Set(modelLastSync.keys());
356
- return [4 /*yield*/, new Promise(function (resolve) {
357
- syncQueriesSubscription = _this.syncQueriesProcessor
358
- .start(modelLastSync)
359
- .subscribe({
360
- next: function (_a) {
361
- var namespace = _a.namespace, modelDefinition = _a.modelDefinition, items = _a.items, done = _a.done, startedAt = _a.startedAt, isFullSync = _a.isFullSync;
362
- return tslib_1.__awaiter(_this, void 0, void 0, function () {
363
- var modelConstructor, modelName, modelMetadata_1, lastFullSync, fullSyncInterval, counts;
364
- var _this = this;
365
- return tslib_1.__generator(this, function (_b) {
366
- switch (_b.label) {
367
- case 0:
368
- modelConstructor = this.userModelClasses[modelDefinition.name];
369
- if (!count.has(modelConstructor)) {
370
- count.set(modelConstructor, {
371
- new: 0,
372
- updated: 0,
373
- deleted: 0,
374
- });
375
- start = util_1.getNow();
376
- newestStartedAt =
377
- newestStartedAt === undefined
378
- ? startedAt
379
- : Math.max(newestStartedAt, startedAt);
380
- }
381
- /**
382
- * If there are mutations in the outbox for a given id, those need to be
383
- * merged individually. Otherwise, we can merge them in batches.
384
- */
385
- return [4 /*yield*/, this.storage.runExclusive(function (storage) { return tslib_1.__awaiter(_this, void 0, void 0, function () {
386
- var idsInOutbox, oneByOne, page, opTypeCount, oneByOne_1, oneByOne_1_1, item, opType, e_1_1, _a, _b, _c, counts;
387
- var e_1, _d;
388
- return tslib_1.__generator(this, function (_e) {
389
- switch (_e.label) {
390
- case 0: return [4 /*yield*/, this.outbox.getModelIds(storage)];
391
- case 1:
392
- idsInOutbox = _e.sent();
393
- oneByOne = [];
394
- page = items.filter(function (item) {
395
- if (!idsInOutbox.has(item.id)) {
396
- return true;
379
+ _this.runningProcesses.isOpen &&
380
+ _this.runningProcesses.add(function (onTerminate) { return tslib_1.__awaiter(_this, void 0, void 0, function () {
381
+ var terminated, _loop_1, this_1;
382
+ var _this = this;
383
+ return tslib_1.__generator(this, function (_a) {
384
+ switch (_a.label) {
385
+ case 0:
386
+ terminated = false;
387
+ _loop_1 = function () {
388
+ var count, modelLastSync, paginatingModels, newestFullSyncStartedAt, theInterval, start, duration, newestStartedAt, msNextFullSync;
389
+ return tslib_1.__generator(this, function (_a) {
390
+ switch (_a.label) {
391
+ case 0:
392
+ count = new WeakMap();
393
+ return [4 /*yield*/, this_1.getModelsMetadataWithNextFullSync(Date.now())];
394
+ case 1:
395
+ modelLastSync = _a.sent();
396
+ paginatingModels = new Set(modelLastSync.keys());
397
+ return [4 /*yield*/, new Promise(function (resolve, reject) {
398
+ if (!_this.runningProcesses.isOpen)
399
+ resolve();
400
+ onTerminate.then(function () { return resolve(); });
401
+ syncQueriesSubscription = _this.syncQueriesProcessor
402
+ .start(modelLastSync)
403
+ .subscribe({
404
+ next: function (_a) {
405
+ var namespace = _a.namespace, modelDefinition = _a.modelDefinition, items = _a.items, done = _a.done, startedAt = _a.startedAt, isFullSync = _a.isFullSync;
406
+ return tslib_1.__awaiter(_this, void 0, void 0, function () {
407
+ var modelConstructor, modelName, modelMetadata_1, lastFullSync, fullSyncInterval, counts;
408
+ var _this = this;
409
+ return tslib_1.__generator(this, function (_b) {
410
+ switch (_b.label) {
411
+ case 0:
412
+ modelConstructor = this.userModelClasses[modelDefinition.name];
413
+ if (!count.has(modelConstructor)) {
414
+ count.set(modelConstructor, {
415
+ new: 0,
416
+ updated: 0,
417
+ deleted: 0,
418
+ });
419
+ start = util_1.getNow();
420
+ newestStartedAt =
421
+ newestStartedAt === undefined
422
+ ? startedAt
423
+ : Math.max(newestStartedAt, startedAt);
424
+ }
425
+ /**
426
+ * If there are mutations in the outbox for a given id, those need to be
427
+ * merged individually. Otherwise, we can merge them in batches.
428
+ */
429
+ return [4 /*yield*/, this.storage.runExclusive(function (storage) { return tslib_1.__awaiter(_this, void 0, void 0, function () {
430
+ var idsInOutbox, oneByOne, page, opTypeCount, oneByOne_1, oneByOne_1_1, item, opType, e_1_1, _a, _b, _c, counts;
431
+ var e_1, _d;
432
+ return tslib_1.__generator(this, function (_e) {
433
+ switch (_e.label) {
434
+ case 0: return [4 /*yield*/, this.outbox.getModelIds(storage)];
435
+ case 1:
436
+ idsInOutbox = _e.sent();
437
+ oneByOne = [];
438
+ page = items.filter(function (item) {
439
+ var itemId = utils_1.getIdentifierValue(modelDefinition, item);
440
+ if (!idsInOutbox.has(itemId)) {
441
+ return true;
442
+ }
443
+ oneByOne.push(item);
444
+ return false;
445
+ });
446
+ opTypeCount = [];
447
+ _e.label = 2;
448
+ case 2:
449
+ _e.trys.push([2, 7, 8, 9]);
450
+ oneByOne_1 = tslib_1.__values(oneByOne), oneByOne_1_1 = oneByOne_1.next();
451
+ _e.label = 3;
452
+ case 3:
453
+ if (!!oneByOne_1_1.done) return [3 /*break*/, 6];
454
+ item = oneByOne_1_1.value;
455
+ return [4 /*yield*/, this.modelMerger.merge(storage, item, modelDefinition)];
456
+ case 4:
457
+ opType = _e.sent();
458
+ if (opType !== undefined) {
459
+ opTypeCount.push([item, opType]);
397
460
  }
398
- oneByOne.push(item);
399
- return false;
400
- });
401
- opTypeCount = [];
402
- _e.label = 2;
403
- case 2:
404
- _e.trys.push([2, 7, 8, 9]);
405
- oneByOne_1 = tslib_1.__values(oneByOne), oneByOne_1_1 = oneByOne_1.next();
406
- _e.label = 3;
407
- case 3:
408
- if (!!oneByOne_1_1.done) return [3 /*break*/, 6];
409
- item = oneByOne_1_1.value;
410
- return [4 /*yield*/, this.modelMerger.merge(storage, item)];
411
- case 4:
412
- opType = _e.sent();
413
- if (opType !== undefined) {
414
- opTypeCount.push([item, opType]);
415
- }
416
- _e.label = 5;
417
- case 5:
418
- oneByOne_1_1 = oneByOne_1.next();
419
- return [3 /*break*/, 3];
420
- case 6: return [3 /*break*/, 9];
421
- case 7:
422
- e_1_1 = _e.sent();
423
- e_1 = { error: e_1_1 };
424
- return [3 /*break*/, 9];
425
- case 8:
426
- try {
427
- if (oneByOne_1_1 && !oneByOne_1_1.done && (_d = oneByOne_1.return)) _d.call(oneByOne_1);
428
- }
429
- finally { if (e_1) throw e_1.error; }
430
- return [7 /*endfinally*/];
431
- case 9:
432
- _b = (_a = opTypeCount.push).apply;
433
- _c = [opTypeCount];
434
- return [4 /*yield*/, this.modelMerger.mergePage(storage, modelConstructor, page)];
435
- case 10:
436
- _b.apply(_a, _c.concat([tslib_1.__spread.apply(void 0, [(_e.sent())])]));
437
- counts = count.get(modelConstructor);
438
- opTypeCount.forEach(function (_a) {
439
- var _b = tslib_1.__read(_a, 2), opType = _b[1];
440
- switch (opType) {
441
- case types_1.OpType.INSERT:
442
- counts.new++;
443
- break;
444
- case types_1.OpType.UPDATE:
445
- counts.updated++;
446
- break;
447
- case types_1.OpType.DELETE:
448
- counts.deleted++;
449
- break;
450
- default:
451
- util_1.exhaustiveCheck(opType);
461
+ _e.label = 5;
462
+ case 5:
463
+ oneByOne_1_1 = oneByOne_1.next();
464
+ return [3 /*break*/, 3];
465
+ case 6: return [3 /*break*/, 9];
466
+ case 7:
467
+ e_1_1 = _e.sent();
468
+ e_1 = { error: e_1_1 };
469
+ return [3 /*break*/, 9];
470
+ case 8:
471
+ try {
472
+ if (oneByOne_1_1 && !oneByOne_1_1.done && (_d = oneByOne_1.return)) _d.call(oneByOne_1);
452
473
  }
453
- });
454
- return [2 /*return*/];
455
- }
456
- });
457
- }); })];
458
- case 1:
459
- /**
460
- * If there are mutations in the outbox for a given id, those need to be
461
- * merged individually. Otherwise, we can merge them in batches.
462
- */
463
- _b.sent();
464
- if (!done) return [3 /*break*/, 4];
465
- modelName = modelDefinition.name;
466
- return [4 /*yield*/, this.getModelMetadata(namespace, modelName)];
467
- case 2:
468
- modelMetadata_1 = _b.sent();
469
- lastFullSync = modelMetadata_1.lastFullSync, fullSyncInterval = modelMetadata_1.fullSyncInterval;
470
- theInterval = fullSyncInterval;
471
- newestFullSyncStartedAt =
472
- newestFullSyncStartedAt === undefined
473
- ? lastFullSync
474
- : Math.max(newestFullSyncStartedAt, isFullSync ? startedAt : lastFullSync);
475
- modelMetadata_1 = this.modelClasses
476
- .ModelMetadata.copyOf(modelMetadata_1, function (draft) {
477
- draft.lastSync = startedAt;
478
- draft.lastFullSync = isFullSync
479
- ? startedAt
480
- : modelMetadata_1.lastFullSync;
481
- });
482
- return [4 /*yield*/, this.storage.save(modelMetadata_1, undefined, ownSymbol)];
483
- case 3:
484
- _b.sent();
485
- counts = count.get(modelConstructor);
486
- this.modelSyncedStatus.set(modelConstructor, true);
487
- observer.next({
488
- type: ControlMessage.SYNC_ENGINE_MODEL_SYNCED,
489
- data: {
490
- model: modelConstructor,
491
- isFullSync: isFullSync,
492
- isDeltaSync: !isFullSync,
493
- counts: counts,
494
- },
495
- });
496
- paginatingModels.delete(modelDefinition);
497
- if (paginatingModels.size === 0) {
498
- duration = util_1.getNow() - start;
499
- resolve();
474
+ finally { if (e_1) throw e_1.error; }
475
+ return [7 /*endfinally*/];
476
+ case 9:
477
+ _b = (_a = opTypeCount.push).apply;
478
+ _c = [opTypeCount];
479
+ return [4 /*yield*/, this.modelMerger.mergePage(storage, modelConstructor, page, modelDefinition)];
480
+ case 10:
481
+ _b.apply(_a, _c.concat([tslib_1.__spread.apply(void 0, [(_e.sent())])]));
482
+ counts = count.get(modelConstructor);
483
+ opTypeCount.forEach(function (_a) {
484
+ var _b = tslib_1.__read(_a, 2), opType = _b[1];
485
+ switch (opType) {
486
+ case types_1.OpType.INSERT:
487
+ counts.new++;
488
+ break;
489
+ case types_1.OpType.UPDATE:
490
+ counts.updated++;
491
+ break;
492
+ case types_1.OpType.DELETE:
493
+ counts.deleted++;
494
+ break;
495
+ default:
496
+ util_1.exhaustiveCheck(opType);
497
+ }
498
+ });
499
+ return [2 /*return*/];
500
+ }
501
+ });
502
+ }); })];
503
+ case 1:
504
+ /**
505
+ * If there are mutations in the outbox for a given id, those need to be
506
+ * merged individually. Otherwise, we can merge them in batches.
507
+ */
508
+ _b.sent();
509
+ if (!done) return [3 /*break*/, 4];
510
+ modelName = modelDefinition.name;
511
+ return [4 /*yield*/, this.getModelMetadata(namespace, modelName)];
512
+ case 2:
513
+ modelMetadata_1 = _b.sent();
514
+ lastFullSync = modelMetadata_1.lastFullSync, fullSyncInterval = modelMetadata_1.fullSyncInterval;
515
+ theInterval = fullSyncInterval;
516
+ newestFullSyncStartedAt =
517
+ newestFullSyncStartedAt === undefined
518
+ ? lastFullSync
519
+ : Math.max(newestFullSyncStartedAt, isFullSync ? startedAt : lastFullSync);
520
+ modelMetadata_1 = this.modelClasses
521
+ .ModelMetadata.copyOf(modelMetadata_1, function (draft) {
522
+ draft.lastSync = startedAt;
523
+ draft.lastFullSync = isFullSync
524
+ ? startedAt
525
+ : modelMetadata_1.lastFullSync;
526
+ });
527
+ return [4 /*yield*/, this.storage.save(modelMetadata_1, undefined, ownSymbol)];
528
+ case 3:
529
+ _b.sent();
530
+ counts = count.get(modelConstructor);
531
+ this.modelSyncedStatus.set(modelConstructor, true);
500
532
  observer.next({
501
- type: ControlMessage.SYNC_ENGINE_SYNC_QUERIES_READY,
533
+ type: ControlMessage.SYNC_ENGINE_MODEL_SYNCED,
534
+ data: {
535
+ model: modelConstructor,
536
+ isFullSync: isFullSync,
537
+ isDeltaSync: !isFullSync,
538
+ counts: counts,
539
+ },
502
540
  });
503
- syncQueriesSubscription.unsubscribe();
504
- }
505
- _b.label = 4;
506
- case 4: return [2 /*return*/];
507
- }
541
+ paginatingModels.delete(modelDefinition);
542
+ if (paginatingModels.size === 0) {
543
+ duration = util_1.getNow() - start;
544
+ resolve();
545
+ observer.next({
546
+ type: ControlMessage.SYNC_ENGINE_SYNC_QUERIES_READY,
547
+ });
548
+ syncQueriesSubscription.unsubscribe();
549
+ }
550
+ _b.label = 4;
551
+ case 4: return [2 /*return*/];
552
+ }
553
+ });
508
554
  });
555
+ },
556
+ error: function (error) {
557
+ observer.error(error);
558
+ },
559
+ });
560
+ observer.next({
561
+ type: ControlMessage.SYNC_ENGINE_SYNC_QUERIES_STARTED,
562
+ data: {
563
+ models: Array.from(paginatingModels).map(function (_a) {
564
+ var name = _a.name;
565
+ return name;
566
+ }),
567
+ },
568
+ });
569
+ })];
570
+ case 2:
571
+ _a.sent();
572
+ msNextFullSync = newestFullSyncStartedAt +
573
+ theInterval -
574
+ (newestStartedAt + duration);
575
+ logger.debug("Next fullSync in " + msNextFullSync / 1000 + " seconds. (" + new Date(Date.now() + msNextFullSync) + ")");
576
+ // TODO: create `BackgroundProcessManager.sleep()` ... but, need to put
577
+ // a lot of thought into what that contract looks like to
578
+ // support possible use-cases:
579
+ //
580
+ // 1. non-cancelable
581
+ // 2. cancelable, unsleep on exit()
582
+ // 3. cancelable, throw Error on exit()
583
+ // 4. cancelable, callback first on exit()?
584
+ // 5. ... etc. ? ...
585
+ //
586
+ // TLDR; this is a lot of complexity here for a sleep(),
587
+ // but, it's not clear to me yet how to support an
588
+ // extensible, centralized cancelable `sleep()` elegantly.
589
+ return [4 /*yield*/, this_1.runningProcesses.add(function (onTerminate) { return tslib_1.__awaiter(_this, void 0, void 0, function () {
590
+ var sleepTimer, unsleep, sleep;
591
+ return tslib_1.__generator(this, function (_a) {
592
+ sleep = new Promise(function (_unsleep) {
593
+ unsleep = _unsleep;
594
+ sleepTimer = setTimeout(unsleep, msNextFullSync);
509
595
  });
510
- },
511
- error: function (error) {
512
- observer.error(error);
513
- },
514
- });
515
- observer.next({
516
- type: ControlMessage.SYNC_ENGINE_SYNC_QUERIES_STARTED,
517
- data: {
518
- models: Array.from(paginatingModels).map(function (_a) {
519
- var name = _a.name;
520
- return name;
521
- }),
522
- },
523
- });
524
- })];
525
- case 2:
526
- _a.sent();
527
- msNextFullSync = newestFullSyncStartedAt +
528
- theInterval -
529
- (newestStartedAt + duration);
530
- logger.debug("Next fullSync in " + msNextFullSync / 1000 + " seconds. (" + new Date(Date.now() + msNextFullSync) + ")");
531
- return [4 /*yield*/, new Promise(function (res) {
532
- waitTimeoutId = setTimeout(res, msNextFullSync);
533
- })];
534
- case 3:
535
- _a.sent();
536
- return [2 /*return*/];
537
- }
538
- });
539
- };
540
- this_1 = this;
541
- _a.label = 1;
542
- case 1:
543
- if (!!observer.closed) return [3 /*break*/, 3];
544
- return [5 /*yield**/, _loop_1()];
545
- case 2:
546
- _a.sent();
547
- return [3 /*break*/, 1];
548
- case 3: return [2 /*return*/];
549
- }
550
- });
551
- }); })();
552
- return function () {
553
- if (syncQueriesSubscription) {
554
- syncQueriesSubscription.unsubscribe();
555
- }
556
- if (waitTimeoutId) {
557
- clearTimeout(waitTimeoutId);
558
- }
559
- };
596
+ onTerminate.then(function () {
597
+ terminated = true;
598
+ unsleep();
599
+ });
600
+ return [2 /*return*/, sleep];
601
+ });
602
+ }); }, 'syncQueriesObservable sleep')];
603
+ case 3:
604
+ // TODO: create `BackgroundProcessManager.sleep()` ... but, need to put
605
+ // a lot of thought into what that contract looks like to
606
+ // support possible use-cases:
607
+ //
608
+ // 1. non-cancelable
609
+ // 2. cancelable, unsleep on exit()
610
+ // 3. cancelable, throw Error on exit()
611
+ // 4. cancelable, callback first on exit()?
612
+ // 5. ... etc. ? ...
613
+ //
614
+ // TLDR; this is a lot of complexity here for a sleep(),
615
+ // but, it's not clear to me yet how to support an
616
+ // extensible, centralized cancelable `sleep()` elegantly.
617
+ _a.sent();
618
+ return [2 /*return*/];
619
+ }
620
+ });
621
+ };
622
+ this_1 = this;
623
+ _a.label = 1;
624
+ case 1:
625
+ if (!(!observer.closed && !terminated)) return [3 /*break*/, 3];
626
+ return [5 /*yield**/, _loop_1()];
627
+ case 2:
628
+ _a.sent();
629
+ return [3 /*break*/, 1];
630
+ case 3: return [2 /*return*/];
631
+ }
632
+ });
633
+ }); }, 'syncQueriesObservable main');
560
634
  });
561
635
  };
562
636
  SyncEngine.prototype.disconnectionHandler = function () {
@@ -572,16 +646,67 @@ var SyncEngine = /** @class */ (function () {
572
646
  SyncEngine.prototype.unsubscribeConnectivity = function () {
573
647
  this.datastoreConnectivity.unsubscribe();
574
648
  };
649
+ /**
650
+ * Stops all subscription activities and resolves when all activies report
651
+ * that they're disconnected, done retrying, etc..
652
+ */
653
+ SyncEngine.prototype.stop = function () {
654
+ return tslib_1.__awaiter(this, void 0, void 0, function () {
655
+ return tslib_1.__generator(this, function (_a) {
656
+ switch (_a.label) {
657
+ case 0:
658
+ logger.debug('stopping sync engine');
659
+ /**
660
+ * Gracefully disconnecting subscribers first just prevents *more* work
661
+ * from entering the pipelines.
662
+ */
663
+ this.unsubscribeConnectivity();
664
+ /**
665
+ * aggressively shut down any lingering background processes.
666
+ * some of this might be semi-redundant with unsubscribing. however,
667
+ * unsubscribing doesn't allow us to wait for settling.
668
+ * (Whereas `stop()` does.)
669
+ */
670
+ return [4 /*yield*/, this.mutationsProcessor.stop()];
671
+ case 1:
672
+ /**
673
+ * aggressively shut down any lingering background processes.
674
+ * some of this might be semi-redundant with unsubscribing. however,
675
+ * unsubscribing doesn't allow us to wait for settling.
676
+ * (Whereas `stop()` does.)
677
+ */
678
+ _a.sent();
679
+ return [4 /*yield*/, this.subscriptionsProcessor.stop()];
680
+ case 2:
681
+ _a.sent();
682
+ return [4 /*yield*/, this.datastoreConnectivity.stop()];
683
+ case 3:
684
+ _a.sent();
685
+ return [4 /*yield*/, this.syncQueriesProcessor.stop()];
686
+ case 4:
687
+ _a.sent();
688
+ return [4 /*yield*/, this.runningProcesses.close()];
689
+ case 5:
690
+ _a.sent();
691
+ return [4 /*yield*/, this.runningProcesses.open()];
692
+ case 6:
693
+ _a.sent();
694
+ logger.debug('sync engine stopped and ready to restart');
695
+ return [2 /*return*/];
696
+ }
697
+ });
698
+ });
699
+ };
575
700
  SyncEngine.prototype.setupModels = function (params) {
576
701
  return tslib_1.__awaiter(this, void 0, void 0, function () {
577
- var fullSyncInterval, ModelMetadata, models, savedModel, promises, result, _a, _b, modelMetadata, modelName, e_2_1;
702
+ var fullSyncInterval, ModelMetadataConstructor, models, savedModel, promises, result, _a, _b, modelMetadata, modelName, e_2_1;
578
703
  var e_2, _c;
579
704
  var _this = this;
580
705
  return tslib_1.__generator(this, function (_d) {
581
706
  switch (_d.label) {
582
707
  case 0:
583
708
  fullSyncInterval = params.fullSyncInterval;
584
- ModelMetadata = this.modelClasses
709
+ ModelMetadataConstructor = this.modelClasses
585
710
  .ModelMetadata;
586
711
  models = [];
587
712
  Object.values(this.schema.namespaces).forEach(function (namespace) {
@@ -613,7 +738,7 @@ var SyncEngine = /** @class */ (function () {
613
738
  ? JSON.stringify(syncPredicate)
614
739
  : null;
615
740
  if (!(modelMetadata === undefined)) return [3 /*break*/, 3];
616
- return [4 /*yield*/, this.storage.save(this.modelInstanceCreator(ModelMetadata, {
741
+ return [4 /*yield*/, this.storage.save(this.modelInstanceCreator(ModelMetadataConstructor, {
617
742
  model: model.name,
618
743
  namespace: namespace,
619
744
  lastSync: null,
@@ -629,7 +754,7 @@ var SyncEngine = /** @class */ (function () {
629
754
  ? modelMetadata.lastSyncPredicate
630
755
  : null;
631
756
  syncPredicateUpdated_1 = prevSyncPredicate !== lastSyncPredicate;
632
- return [4 /*yield*/, this.storage.save(this.modelClasses.ModelMetadata.copyOf(modelMetadata, function (draft) {
757
+ return [4 /*yield*/, this.storage.save(ModelMetadataConstructor.copyOf(modelMetadata, function (draft) {
633
758
  draft.fullSyncInterval = fullSyncInterval;
634
759
  // perform a base sync if the syncPredicate changed in between calls to DataStore.start
635
760
  // ensures that the local store contains all the data specified by the syncExpression