Skip to content

Commit

Permalink
fix(DataStore): created and deleted model on one device appears as cr…
Browse files Browse the repository at this point in the history
…eated on the other (aws-amplify#3553)
  • Loading branch information
MuniekMg committed Mar 6, 2024
1 parent 358699c commit e747e76
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -42,18 +42,35 @@ struct RemoteSyncReconciler {
/// - Returns: disposition of models to apply locally
static func getDispositions(_ remoteModels: [RemoteModel],
localMetadatas: [LocalMetadata]) -> [Disposition] {
guard !remoteModels.isEmpty else {
return []
}

guard !localMetadatas.isEmpty else {
return remoteModels.compactMap { getDisposition($0, localMetadata: nil) }

let remoteModelsGroupedById = remoteModels.reduce(into: [:]) { $0[$1.model.id] = ($0[$1.model.id] ?? []) + [$1] }
let localMetadatasGroupedById = localMetadatas.reduce(into: [:]) { $0[$1.modelId] = ($0[$1.modelId] ?? []) + [$1] }

var result: [Disposition] = []

for (modelId, remoteModels) in remoteModelsGroupedById {
let localMetadatas = localMetadatasGroupedById[modelId] ?? []

if remoteModels.isEmpty {
continue

} else if localMetadatas.isEmpty {
let isRemoved = remoteModels.contains(where: { $0.syncMetadata.deleted })

// Ignore all dispositions for model that doesn't exist locally and is deleted
guard isRemoved == false else { continue }

let dispositions = remoteModels.compactMap { getDisposition($0, localMetadata: nil) }
result.append(contentsOf: dispositions)

} else {
let metadataBymodelId = localMetadatas.reduce(into: [:]) { $0[$1.modelId] = $1 }
let dispositions = remoteModels.compactMap { getDisposition($0, localMetadata: metadataBymodelId[$0.model.identifier]) }
result.append(contentsOf: dispositions)
}
}

let metadataBymodelId = localMetadatas.reduce(into: [:]) { $0[$1.modelId] = $1 }
let dispositions = remoteModels.compactMap { getDisposition($0, localMetadata: metadataBymodelId[$0.model.identifier]) }

return dispositions

return result
}

/// Reconcile a remote model against local metadata
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,33 @@ class RemoteSyncReconcilerTests: XCTestCase {
}
waitForExpectations(timeout: 1)
}

func testGetDispositions_emptyLocal_singleModelAddedAndDeleted() {
let sameId = UUID().uuidString

let remoteModels = [
makeRemoteModel(modelId: sameId, deleted: false, version: 1),
makeRemoteModel(modelId: sameId, deleted: true, version: 2)
]

let dispositions = RemoteSyncReconciler.getDispositions(remoteModels, localMetadatas: [])

XCTAssertTrue(dispositions.isEmpty)
}

func testGetDispositions_emptyLocal_oneModelAdded_SecondModelAddedAndDeleted() {
let sameId = UUID().uuidString

let remoteModels = [
makeRemoteModel(deleted: false, version: 1),
makeRemoteModel(modelId: sameId, deleted: false, version: 1),
makeRemoteModel(modelId: sameId, deleted: true, version: 2)
]

let dispositions = RemoteSyncReconciler.getDispositions(remoteModels, localMetadatas: [])

XCTAssertTrue(dispositions.count == 1)
}

// MARK: - Utilities

Expand Down

0 comments on commit e747e76

Please sign in to comment.