Skip to content

Commit 84d3b9e

Browse files
manaswi223lawmicha
andauthored
fix(datastore): fix stop then start API call pattern (#2529)
* chore(datastore): add forceSync unit & Integ test * fix(datastore): address PR comments * remove changes to testConcurrentSave Co-authored-by: Michael Law <[email protected]>
1 parent 5a2c63d commit 84d3b9e

File tree

4 files changed

+120
-9
lines changed

4 files changed

+120
-9
lines changed

AmplifyPlugins/DataStore/Sources/AWSDataStorePlugin/AWSDataStorePlugin+DataStoreBaseBehavior.swift

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -419,14 +419,17 @@ extension AWSDataStorePlugin: DataStoreBaseBehavior {
419419
dispatchedModelSynced.set(false)
420420
}
421421
if storageEngine == nil {
422-
423-
completion(.successfulVoid)
422+
queue.async {
423+
completion(.successfulVoid)
424+
}
424425
return
425426
}
426427

427428
storageEngine.stopSync { result in
428429
self.storageEngine = nil
429-
completion(result)
430+
self.queue.async {
431+
completion(result)
432+
}
430433
}
431434
}
432435
}
@@ -451,12 +454,16 @@ extension AWSDataStorePlugin: DataStoreBaseBehavior {
451454
dispatchedModelSynced.set(false)
452455
}
453456
if storageEngine == nil {
454-
completion(.successfulVoid)
457+
queue.async {
458+
completion(.successfulVoid)
459+
}
455460
return
456461
}
457462
storageEngine.clear { result in
458463
self.storageEngine = nil
459-
completion(result)
464+
self.queue.async {
465+
completion(result)
466+
}
460467
}
461468
}
462469
}

AmplifyPlugins/DataStore/Sources/AWSDataStorePlugin/AWSDataStorePlugin.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ final public class AWSDataStorePlugin: DataStoreCategoryPlugin {
5454

5555
var storageEngine: StorageEngineBehavior!
5656
var storageEngineInitQueue = DispatchQueue(label: "AWSDataStorePlugin.storageEngineInitQueue")
57+
var queue = DispatchQueue(label: "AWSDataStorePlugin.queue", target: DispatchQueue.global())
5758
var storageEngineBehaviorFactory: StorageEngineBehaviorFactory
5859

5960
var iStorageEngineSink: Any?

AmplifyPlugins/DataStore/Tests/AWSDataStorePluginTests/Core/AWSDataStorePluginTests.swift

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,81 @@ class AWSDataStorePluginTests: XCTestCase {
9090
}
9191
await waitForExpectations(timeout: 1.0)
9292
}
93+
94+
func testStorageEngineStartsOnPluginStopStart() throws {
95+
let stopExpectation = expectation(description: "Stop plugin should be called")
96+
stopExpectation.isInverted = true
97+
let startExpectation = expectation(description: "Start Sync should be called")
98+
var currCount = 0
99+
let storageEngine = MockStorageEngineBehavior()
100+
101+
storageEngine.responders[.stopSync] = StopSyncResponder { _ in
102+
stopExpectation.fulfill()
103+
}
104+
105+
storageEngine.responders[.startSync] = StartSyncResponder { _ in
106+
currCount = self.expect(startExpectation, currCount, 1)
107+
}
108+
109+
let storageEngineBehaviorFactory: StorageEngineBehaviorFactory = {_, _, _, _, _, _ throws in
110+
return storageEngine
111+
}
112+
let dataStorePublisher = DataStorePublisher()
113+
let plugin = AWSDataStorePlugin(modelRegistration: TestModelRegistration(),
114+
storageEngineBehaviorFactory: storageEngineBehaviorFactory,
115+
dataStorePublisher: dataStorePublisher,
116+
validAPIPluginKey: "MockAPICategoryPlugin",
117+
validAuthPluginKey: "MockAuthCategoryPlugin")
118+
119+
do {
120+
try plugin.configure(using: nil)
121+
XCTAssertNil(plugin.storageEngine)
122+
123+
plugin.stop(completion: { _ in
124+
plugin.start(completion: { _ in })
125+
})
126+
} catch {
127+
XCTFail("DataStore configuration should not fail with nil configuration. \(error)")
128+
}
129+
waitForExpectations(timeout: 1.0)
130+
}
131+
132+
func testStorageEngineStartsOnPluginClearStart() throws {
133+
let clearExpectation = expectation(description: "Clear should be called")
134+
let startExpectation = expectation(description: "Start Sync should be called")
135+
var currCount = 0
136+
137+
let storageEngine = MockStorageEngineBehavior()
138+
storageEngine.responders[.clear] = ClearResponder { _ in
139+
currCount = self.expect(clearExpectation, currCount, 1)
140+
}
141+
142+
storageEngine.responders[.startSync] = StartSyncResponder { _ in
143+
currCount = self.expect(startExpectation, currCount, 2)
144+
}
145+
146+
let storageEngineBehaviorFactory: StorageEngineBehaviorFactory = {_, _, _, _, _, _ throws in
147+
return storageEngine
148+
}
149+
let dataStorePublisher = DataStorePublisher()
150+
let plugin = AWSDataStorePlugin(modelRegistration: TestModelRegistration(),
151+
storageEngineBehaviorFactory: storageEngineBehaviorFactory,
152+
dataStorePublisher: dataStorePublisher,
153+
validAPIPluginKey: "MockAPICategoryPlugin",
154+
validAuthPluginKey: "MockAuthCategoryPlugin")
155+
156+
do {
157+
try plugin.configure(using: nil)
158+
XCTAssertNil(plugin.storageEngine)
159+
160+
plugin.clear(completion: { _ in
161+
plugin.start(completion: { _ in })
162+
})
163+
} catch {
164+
XCTFail("DataStore configuration should not fail with nil configuration. \(error)")
165+
}
166+
waitForExpectations(timeout: 1.0)
167+
}
93168

94169
func testStorageEngineStartStopStart() throws {
95170
let startExpectation = expectation(description: "Start Sync should be called with start")

AmplifyPlugins/DataStore/Tests/DataStoreHostApp/AWSDataStorePluginIntegrationTests/DataStoreEndToEndTests.swift

Lines changed: 32 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -405,6 +405,21 @@ class DataStoreEndToEndTests: SyncEngineIntegrationTestBase {
405405
try await Amplify.DataStore.start()
406406
try await validateSavePost()
407407
}
408+
409+
/// Ensure DataStore.stop followed by DataStore.start is successful
410+
///
411+
/// - Given: DataStore has just configured, but not yet started
412+
/// - When:
413+
/// - DataStore.stop
414+
/// - Followed by DataStore.start in the completion of the stop
415+
/// - Then:
416+
/// - DataStore should be successfully started
417+
func testConfigureAmplifyThenStopStart() async throws {
418+
await setUp(withModels: TestModelRegistration())
419+
try startAmplify()
420+
try await Amplify.DataStore.stop()
421+
try await Amplify.DataStore.start()
422+
}
408423

409424
/// Ensure the DataStore is automatically started when querying for the first time
410425
///
@@ -449,6 +464,21 @@ class DataStoreEndToEndTests: SyncEngineIntegrationTestBase {
449464
try await validateSavePost()
450465
}
451466

467+
/// Ensure DataStore.clear followed by DataStore.start is successful
468+
///
469+
/// - Given: DataStore has just configured, but not yet started
470+
/// - When:
471+
/// - DataStore.clear
472+
/// - Followed by DataStore.start in the completion of the clear
473+
/// - Then:
474+
/// - DataStore should be successfully started
475+
func testConfigureAmplifyThenClearStart() async throws {
476+
await setUp(withModels: TestModelRegistration())
477+
try startAmplify()
478+
try await Amplify.DataStore.clear()
479+
try await Amplify.DataStore.start()
480+
}
481+
452482
/// Perform concurrent saves and observe the data successfuly synced from cloud. Then delete the items afterwards
453483
/// and ensure they have successfully synced from cloud
454484
///
@@ -461,7 +491,7 @@ class DataStoreEndToEndTests: SyncEngineIntegrationTestBase {
461491
/// - Ensure the expected mutation event with version 2 (synced from cloud) is received
462492
///
463493
func testConcurrentSave() async throws {
464-
await setUp(withModels: TestModelRegistration())
494+
await setUp(withModels: TestModelRegistration(), logLevel: .verbose)
465495
try await startAmplifyAndWaitForSync()
466496

467497
var posts = [Post]()
@@ -474,8 +504,6 @@ class DataStoreEndToEndTests: SyncEngineIntegrationTestBase {
474504
}
475505
let postsSyncedToCloud = expectation(description: "All posts saved and synced to cloud")
476506
postsSyncedToCloud.expectedFulfillmentCount = count
477-
478-
479507
log.debug("Created posts: [\(posts.map { $0.identifier })]")
480508

481509
let postsCopy = posts
@@ -507,7 +535,6 @@ class DataStoreEndToEndTests: SyncEngineIntegrationTestBase {
507535
_ = try await Amplify.DataStore.save(capturedPosts[index])
508536
}
509537
}
510-
511538
await waitForExpectations(timeout: 100)
512539

513540
let postsDeletedLocally = expectation(description: "All posts deleted locally")
@@ -548,6 +575,7 @@ class DataStoreEndToEndTests: SyncEngineIntegrationTestBase {
548575
try await Amplify.DataStore.delete(capturedPosts[index])
549576
}
550577
}
578+
551579
await waitForExpectations(timeout: 100)
552580
}
553581

0 commit comments

Comments
 (0)