aws-amplify / amplify-ios

@@ -34,8 +34,8 @@
Loading
34 34
            case (.notifyingDropped, .notified):
35 35
                return .finished
36 36
37 -
            case (.executing, .applied(let savedModel, let existsLocally)):
38 -
                return .notifying(savedModel, existsLocally)
37 +
            case (.executing, .applied(let savedModel, let mutationType)):
38 +
                return .notifying(savedModel, mutationType)
39 39
40 40
            case (.notifying, .notified):
41 41
                return .finished

@@ -15,9 +15,8 @@
Loading
15 15
    typealias SavedModel = ReconcileAndLocalSaveOperation.AppliedModel
16 16
17 17
    enum Disposition {
18 -
        case applyRemoteModel(RemoteModel)
18 +
        case applyRemoteModel(RemoteModel, MutationEvent.MutationType)
19 19
        case dropRemoteModel(String)
20 -
        case error(DataStoreError)
21 20
    }
22 21
23 22
    static func reconcile(remoteModel: RemoteModel,
@@ -29,13 +28,21 @@
Loading
29 28
        }
30 29
31 30
        guard let localMetadata = localMetadata else {
32 -
            return .applyRemoteModel(remoteModel)
31 +
            if remoteModel.syncMetadata.deleted {
32 +
                return .dropRemoteModel(remoteModel.model.modelName)
33 +
            } else {
34 +
                return .applyRemoteModel(remoteModel, .create)
35 +
            }
33 36
        }
34 37
35 38
        // Technically, we should never receive a subscription for a version we already have, but we'll be defensive
36 39
        // and make this check include the current version
37 40
        if remoteModel.syncMetadata.version >= localMetadata.version {
38 -
            return .applyRemoteModel(remoteModel)
41 +
            if remoteModel.syncMetadata.deleted {
42 +
                return .applyRemoteModel(remoteModel, .delete)
43 +
            } else {
44 +
                return .applyRemoteModel(remoteModel, .update)
45 +
            }
39 46
        }
40 47
41 48
        return .dropRemoteModel(remoteModel.model.modelName)

@@ -100,8 +100,8 @@
Loading
100 100
        case .notifyingDropped(let modelName):
101 101
            notifyDropped(modelName: modelName)
102 102
103 -
        case .notifying(let savedModel, let existsLocally):
104 -
            notify(savedModel: savedModel, existsLocally: existsLocally)
103 +
        case .notifying(let savedModel, let mutationType):
104 +
            notify(savedModel: savedModel, mutationType: mutationType)
105 105
106 106
        case .inError(let error):
107 107
            // Maybe we have to notify the Hub?
@@ -189,12 +189,10 @@
Loading
189 189
    /// - dropped
190 190
    func execute(disposition: RemoteSyncReconciler.Disposition) {
191 191
        switch disposition {
192 -
        case .applyRemoteModel(let remoteModel):
193 -
            apply(remoteModel: remoteModel)
192 +
        case .applyRemoteModel(let remoteModel, let mutationType):
193 +
            apply(remoteModel: remoteModel, mutationType: mutationType)
194 194
        case .dropRemoteModel(let modelName):
195 195
            stateMachine.notify(action: .dropped(modelName: modelName))
196 -
        case .error(let dataStoreError):
197 -
            stateMachine.notify(action: .errored(dataStoreError))
198 196
        }
199 197
    }
200 198
@@ -202,7 +200,7 @@
Loading
202 200
    /// delete methods, which eventually notify with:
203 201
    /// - applied
204 202
    /// - errored
205 -
    private func apply(remoteModel: RemoteModel) {
203 +
    private func apply(remoteModel: RemoteModel, mutationType: MutationEvent.MutationType) {
206 204
        if log.logLevel == .verbose {
207 205
            log.verbose("\(#function): remoteModel")
208 206
        }
@@ -218,15 +216,17 @@
Loading
218 216
        }
219 217
220 218
        // TODO: Wrap this in a transaction
221 -
        if remoteModel.syncMetadata.deleted {
219 +
        if mutationType == .delete {
222 220
            saveDeleteMutation(storageAdapter: storageAdapter, remoteModel: remoteModel)
223 221
        } else {
224 -
            saveCreateOrUpdateMutation(storageAdapter: storageAdapter, remoteModel: remoteModel)
222 +
            saveCreateOrUpdateMutation(storageAdapter: storageAdapter,
223 +
                                       remoteModel: remoteModel,
224 +
                                       mutationType: mutationType)
225 225
        }
226 -
227 226
    }
228 227
229 -
    private func saveDeleteMutation(storageAdapter: StorageEngineAdapter, remoteModel: RemoteModel) {
228 +
    private func saveDeleteMutation(storageAdapter: StorageEngineAdapter,
229 +
                                    remoteModel: RemoteModel) {
230 230
        log.verbose(#function)
231 231
232 232
        guard let modelType = ModelRegistry.modelType(from: modelSchema.name) else {
@@ -247,12 +247,16 @@
Loading
247 247
                let errorAction = Action.errored(dataStoreError)
248 248
                self.stateMachine.notify(action: errorAction)
249 249
            case .success:
250 -
                self.saveMetadata(storageAdapter: storageAdapter, inProcessModel: remoteModel)
250 +
                self.saveMetadata(storageAdapter: storageAdapter,
251 +
                                  inProcessModel: remoteModel,
252 +
                                  mutationType: .delete)
251 253
            }
252 254
        }
253 255
    }
254 256
255 -
    private func saveCreateOrUpdateMutation(storageAdapter: StorageEngineAdapter, remoteModel: RemoteModel) {
257 +
    private func saveCreateOrUpdateMutation(storageAdapter: StorageEngineAdapter,
258 +
                                            remoteModel: RemoteModel,
259 +
                                            mutationType: MutationEvent.MutationType) {
256 260
        log.verbose(#function)
257 261
        storageAdapter.save(untypedModel: remoteModel.model.instance) { response in
258 262
            if self.log.logLevel == .debug {
@@ -271,25 +275,18 @@
Loading
271 275
                    return
272 276
                }
273 277
                let inProcessModel = MutationSync(model: anyModel, syncMetadata: remoteModel.syncMetadata)
274 -
                self.saveMetadata(storageAdapter: storageAdapter, inProcessModel: inProcessModel)
278 +
                self.saveMetadata(storageAdapter: storageAdapter,
279 +
                                  inProcessModel: inProcessModel,
280 +
                                  mutationType: mutationType)
275 281
            }
276 282
        }
277 283
    }
278 284
279 285
    private func saveMetadata(storageAdapter: StorageEngineAdapter,
280 -
                              inProcessModel: AppliedModel) {
286 +
                              inProcessModel: AppliedModel,
287 +
                              mutationType: MutationEvent.MutationType) {
281 288
        log.verbose(#function)
282 289
283 -
        /// Do a local metadata query before saving to check if the `AppliedModel` is of `create` or
284 -
        /// `update` MutationType from the perspective of the local store
285 -
        let existsLocally: Bool
286 -
        do {
287 -
            let localMetadata = try storageAdapter.queryMutationSyncMetadata(for: remoteModel.model.id)
288 -
            existsLocally = localMetadata != nil
289 -
        } catch {
290 -
            log.error("Failed to query for sync metadata")
291 -
            return
292 -
        }
293 290
        storageAdapter.save(remoteModel.syncMetadata, condition: nil) { result in
294 291
            if self.log.logLevel == .debug {
295 292
                self.log.debug("save metadata: \(self.stopwatch.lap())s")
@@ -300,7 +297,7 @@
Loading
300 297
                self.stateMachine.notify(action: errorAction)
301 298
            case .success(let syncMetadata):
302 299
                let appliedModel = MutationSync(model: inProcessModel.model, syncMetadata: syncMetadata)
303 -
                self.stateMachine.notify(action: .applied(appliedModel, existsLocally: existsLocally))
300 +
                self.stateMachine.notify(action: .applied(appliedModel, mutationType: mutationType))
304 301
            }
305 302
        }
306 303
    }
@@ -313,23 +310,14 @@
Loading
313 310
    /// Responder method for `notifying`. Notify actions:
314 311
    /// - notified
315 312
    func notify(savedModel: AppliedModel,
316 -
                existsLocally: Bool) {
313 +
                mutationType: MutationEvent.MutationType) {
317 314
        log.verbose(#function)
318 315
319 316
        guard !isCancelled else {
320 317
            log.verbose("\(#function) - cancelled, aborting")
321 318
            return
322 319
        }
323 -
324 -
        let mutationType: MutationEvent.MutationType
325 320
        let version = savedModel.syncMetadata.version
326 -
        if savedModel.syncMetadata.deleted {
327 -
            mutationType = .delete
328 -
        } else if !existsLocally {
329 -
            mutationType = .create
330 -
        } else {
331 -
            mutationType = .update
332 -
        }
333 321
334 322
        // TODO: Dispatch/notify error if we can't erase to any model? Would imply an error in JSON decoding,
335 323
        // which shouldn't be possible this late in the process. Possibly notify global conflict/error handler?
Files Coverage
Amplify 48.55%
AmplifyPlugins 63.68%
Project Totals (653 files) 59.98%
Notifications are pending CI completion. Periodically Codecov will check the CI state, when complete notifications will be submitted. Push notifications now.
27287
Analytics_plugin_unit_test
27286
Storage_plugin_unit_test
27279
Predictions_plugin_unit_test
27285
AWSPluginsCore
27284
DataStore_plugin_unit_test
27280
API_plugin_unit_test
27283
Predictions_plugin_unit_test
26986
Auth_plugin_unit_test
26979
Analytics_plugin_unit_test
26978
AWSPluginsCore
26985
Predictions_plugin_unit_test
26982
Predictions_plugin_unit_test
26984
API_plugin_unit_test
26980
DataStore_plugin_unit_test
27281
Auth_plugin_unit_test
26983
Storage_plugin_unit_test

No yaml found.

Create your codecov.yml to customize your Codecov experience

Sunburst
The inner-most circle is the entire project, moving away from the center are folders then, finally, a single file. The size and color of each slice is representing the number of statements and the coverage, respectively.
Icicle
The top section represents the entire project. Proceeding with folders and finally individual files. The size and color of each slice is representing the number of statements and the coverage, respectively.
Grid
Each block represents a single file in the project. The size and color of each block is represented by the number of statements and the coverage, respectively.
Loading