Skip to content

Commit 3b2d3d6

Browse files
authored
fix(DataStore): ObserveQuery InitialQuery empty modelIds set (#1663)
1 parent c1afb1b commit 3b2d3d6

File tree

3 files changed

+45
-9
lines changed

3 files changed

+45
-9
lines changed

AmplifyPlugins/DataStore/AWSDataStoreCategoryPlugin/Subscribe/DataStoreObserveQueryOperation.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,7 @@ public class AWSDataStoreObserveQueryOperation<M: Model>: AsynchronousOperation,
195195
self.observeQueryStarted = false
196196
}
197197
self.log.verbose("Resetting state")
198-
self.currentItems.sortedModels.removeAll()
198+
self.currentItems.reset()
199199
self.itemsChangedSink = nil
200200
self.batchItemsChangedSink = nil
201201
}
@@ -249,7 +249,7 @@ public class AWSDataStoreObserveQueryOperation<M: Model>: AsynchronousOperation,
249249

250250
switch queryResult {
251251
case .success(let queriedModels):
252-
currentItems.sortedModels = queriedModels
252+
currentItems.set(sortedModels: queriedModels)
253253
sendSnapshot()
254254
case .failure(let error):
255255
self.passthroughPublisher.send(completion: .failure(error))

AmplifyPlugins/DataStore/AWSDataStoreCategoryPlugin/Subscribe/Support/SortedList.swift

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@
88
import Amplify
99

1010
class SortedList<ModelType: Model> {
11-
var sortedModels: [ModelType]
12-
var modelIds: Set<Model.Identifier>
11+
private(set) var sortedModels: [ModelType]
12+
private(set) var modelIds: Set<Model.Identifier>
1313
private let sortInput: [QuerySortDescriptor]?
1414
private let modelSchema: ModelSchema
1515

@@ -20,10 +20,19 @@ class SortedList<ModelType: Model> {
2020
self.modelSchema = modelSchema
2121
}
2222

23+
/// Sets the internal data structures to the list of models. `sortedModels` should already be sorted to efficiently
24+
/// update the internal instructures of `SortedList`. If `sortedModels` is not sorted, then the subsequent
25+
/// methods used on the data structure will have adverse consequences, for example adding a model assumes the list
26+
/// is already sorted (since it performs a binary search insertion).
27+
func set(sortedModels: [ModelType]) {
28+
self.sortedModels = sortedModels
29+
modelIds = Set(sortedModels.map { $0.id })
30+
}
31+
2332
/// Apply the incoming `model` to the sorted array based on the mutation type. This logic accounts for duplicate
2433
/// events since identical events may have different sources (local and remote). When the mutation type is delete,
25-
/// remove it if it exists in the array. When create/update and it has an sort order, then remove and add it back in the
26-
/// correct sort order. if there is no sort order, replace it.
34+
/// remove it if it exists in the array. When create/update and it has an sort order, then remove and add it back in
35+
/// the correct sort order. if there is no sort order, replace it.
2736
/// Return `true` if something occured (added, replaced, deleted), otherwise `false`
2837
@discardableResult func apply(model: ModelType, mutationType: MutationEvent.MutationType) -> Bool {
2938
if mutationType == MutationEvent.MutationType.delete {
@@ -87,6 +96,12 @@ class SortedList<ModelType: Model> {
8796
modelIds.insert(model.id)
8897
}
8998
}
99+
100+
/// Removes the models in the list
101+
func reset() {
102+
sortedModels.removeAll()
103+
modelIds.removeAll()
104+
}
90105
}
91106

92107
extension Array where Element: Model {

AmplifyPlugins/DataStore/AWSDataStoreCategoryPluginTests/Subscribe/Support/SortedListTests.swift

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,24 @@ import Combine
1616

1717
class SortedListTests: XCTestCase {
1818

19+
func testSortedListSetAndReset() {
20+
let posts = [createPost(id: "1", rating: 5.0),
21+
createPost(id: "2", rating: 5.0),
22+
createPost(id: "3", rating: 5.0),
23+
createPost(id: "4", rating: 5.0)]
24+
25+
let list = SortedList<Post>(sortInput: [QuerySortBy.ascending(Post.keys.rating).sortDescriptor],
26+
modelSchema: Post.schema)
27+
list.set(sortedModels: posts)
28+
29+
assertPosts(list.sortedModels, expectedIds: ["1", "2", "3", "4"])
30+
XCTAssertEqual(list.modelIds.count, 4)
31+
32+
list.reset()
33+
XCTAssertTrue(list.sortedModels.isEmpty)
34+
XCTAssertTrue(list.modelIds.isEmpty)
35+
}
36+
1937
func testSortedListSingleSort() {
2038
let posts = [createPost(id: "1"),
2139
createPost(id: "2"),
@@ -24,15 +42,18 @@ class SortedListTests: XCTestCase {
2442
let sortInput = [QuerySortBy.ascending(Post.keys.id).sortDescriptor]
2543
let list = SortedList<Post>(sortInput: sortInput,
2644
modelSchema: Post.schema)
27-
list.sortedModels = posts
45+
46+
list.set(sortedModels: posts)
2847

2948
// insert into the middle of the sorted list
3049
list.add(model: createPost(id: "3"), sortInputs: sortInput)
3150
assertPosts(list.sortedModels, expectedIds: ["1", "2", "3", "5", "6"])
51+
XCTAssertEqual(list.modelIds.count, 5)
3252

3353
// insert into the middle
3454
list.add(model: createPost(id: "4"), sortInputs: sortInput)
3555
assertPosts(list.sortedModels, expectedIds: ["1", "2", "3", "4", "5", "6"])
56+
XCTAssertEqual(list.modelIds.count, 6)
3657

3758
// insert at the beginning
3859
list.add(model: createPost(id: "0"), sortInputs: sortInput)
@@ -68,7 +89,7 @@ class SortedListTests: XCTestCase {
6889
QuerySortBy.ascending(Post.keys.id).sortDescriptor]
6990
let list = SortedList<Post>(sortInput: sortInput,
7091
modelSchema: Post.schema)
71-
list.sortedModels = posts
92+
list.set(sortedModels: posts)
7293

7394
// After id: "1", rating: 5.0
7495
list.add(model: createPost(id: "1", rating: 10.0), sortInputs: sortInput)
@@ -107,7 +128,7 @@ class SortedListTests: XCTestCase {
107128
let sortInput = [QuerySortBy.ascending(Post.keys.rating).sortDescriptor]
108129
let list = SortedList<Post>(sortInput: [QuerySortBy.ascending(Post.keys.rating).sortDescriptor],
109130
modelSchema: Post.schema)
110-
list.sortedModels = posts
131+
list.set(sortedModels: posts)
111132

112133
// Since this is a binary search, the first index where the predicate returns `nil` is the middle index
113134
list.add(model: createPost(id: "5", rating: 5.0), sortInputs: sortInput)

0 commit comments

Comments
 (0)