Skip to content

Commit 29f0bab

Browse files
authored
fix: Data race in AWSModelReconciliationQueue (#790)
* chore: Enable thread sanitizer in tests * fix: Data race in AWSModelReconciliationQueue * fix: Data races in test code * chore: Enable threadSanitizer in AWSPluginsCore * chore: Enable threadSanitizer in API plugin * chore: Enable threadSanitizer in Auth plugin * chore: Enable threadSanitizer in Predictions plugin * chore: Enable threadSanitizer and code coverage in Storage plugin
1 parent b702827 commit 29f0bab

File tree

15 files changed

+44
-20
lines changed

15 files changed

+44
-20
lines changed

Amplify.xcodeproj/xcshareddata/xcschemes/AWSPluginsCore.xcscheme

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,8 @@
2626
buildConfiguration = "Debug"
2727
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
2828
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
29-
shouldUseLaunchSchemeArgsEnv = "YES">
29+
shouldUseLaunchSchemeArgsEnv = "YES"
30+
enableThreadSanitizer = "YES">
3031
<Testables>
3132
<TestableReference
3233
skipped = "NO">

AmplifyPlugins/API/APICategoryPlugin.xcodeproj/xcshareddata/xcschemes/AWSAPICategoryPlugin.xcscheme

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,8 @@
4040
buildConfiguration = "Debug"
4141
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
4242
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
43-
shouldUseLaunchSchemeArgsEnv = "YES">
43+
shouldUseLaunchSchemeArgsEnv = "YES"
44+
enableThreadSanitizer = "YES">
4445
<Testables>
4546
<TestableReference
4647
skipped = "NO">

AmplifyPlugins/API/APICategoryPlugin.xcodeproj/xcshareddata/xcschemes/GraphQLWithIAMIntegrationTests.xcscheme

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@
1010
buildConfiguration = "Debug"
1111
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
1212
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
13-
shouldUseLaunchSchemeArgsEnv = "YES">
13+
shouldUseLaunchSchemeArgsEnv = "YES"
14+
enableThreadSanitizer = "YES">
1415
<Testables>
1516
<TestableReference
1617
skipped = "NO">

AmplifyPlugins/API/APICategoryPlugin.xcodeproj/xcshareddata/xcschemes/GraphQLWithUserPoolIntegrationTests.xcscheme

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@
1010
buildConfiguration = "Debug"
1111
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
1212
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
13-
shouldUseLaunchSchemeArgsEnv = "YES">
13+
shouldUseLaunchSchemeArgsEnv = "YES"
14+
enableThreadSanitizer = "YES">
1415
<Testables>
1516
<TestableReference
1617
skipped = "NO">

AmplifyPlugins/API/APICategoryPlugin.xcodeproj/xcshareddata/xcschemes/RESTWithIAMIntegrationTests.xcscheme

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@
1010
buildConfiguration = "Debug"
1111
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
1212
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
13-
shouldUseLaunchSchemeArgsEnv = "YES">
13+
shouldUseLaunchSchemeArgsEnv = "YES"
14+
enableThreadSanitizer = "YES">
1415
<Testables>
1516
<TestableReference
1617
skipped = "NO">

AmplifyPlugins/API/APICategoryPlugin.xcodeproj/xcshareddata/xcschemes/RESTWithUserPoolIntegrationTests.xcscheme

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@
1010
buildConfiguration = "Debug"
1111
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
1212
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
13-
shouldUseLaunchSchemeArgsEnv = "YES">
13+
shouldUseLaunchSchemeArgsEnv = "YES"
14+
enableThreadSanitizer = "YES">
1415
<Testables>
1516
<TestableReference
1617
skipped = "NO">

AmplifyPlugins/Auth/AWSCognitoAuthPlugin.xcodeproj/xcshareddata/xcschemes/AWSCognitoAuthPlugin.xcscheme

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,8 @@
4040
buildConfiguration = "Debug"
4141
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
4242
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
43-
shouldUseLaunchSchemeArgsEnv = "YES">
43+
shouldUseLaunchSchemeArgsEnv = "YES"
44+
enableThreadSanitizer = "YES">
4445
<Testables>
4546
<TestableReference
4647
skipped = "NO">

AmplifyPlugins/DataStore/AWSDataStoreCategoryPlugin/Sync/SubscriptionSync/ReconcileAndLocalSave/AWSModelReconciliationQueue.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ final class AWSModelReconciliationQueue: ModelReconciliationQueue {
6464
private let modelName: String
6565

6666
private var incomingEventsSink: AnyCancellable?
67-
private var reconcileAndLocalSaveOperationSinks: Set<AnyCancellable?>
67+
private var reconcileAndLocalSaveOperationSinks: AtomicValue<Set<AnyCancellable?>>
6868

6969
private let modelReconciliationQueueSubject: PassthroughSubject<ModelReconciliationQueueEvent, DataStoreError>
7070
var publisher: AnyPublisher<ModelReconciliationQueueEvent, DataStoreError> {
@@ -98,7 +98,7 @@ final class AWSModelReconciliationQueue: ModelReconciliationQueue {
9898
let resolvedIncomingSubscriptionEvents = incomingSubscriptionEvents ??
9999
AWSIncomingSubscriptionEventPublisher(modelType: modelType, api: api, auth: auth)
100100
self.incomingSubscriptionEvents = resolvedIncomingSubscriptionEvents
101-
self.reconcileAndLocalSaveOperationSinks = Set<AnyCancellable?>()
101+
self.reconcileAndLocalSaveOperationSinks = AtomicValue(initialValue: Set<AnyCancellable?>())
102102
self.incomingEventsSink = resolvedIncomingSubscriptionEvents
103103
.publisher
104104
.sink(receiveCompletion: { [weak self] completion in
@@ -136,14 +136,14 @@ final class AWSModelReconciliationQueue: ModelReconciliationQueue {
136136
var reconcileAndLocalSaveOperationSink: AnyCancellable?
137137

138138
reconcileAndLocalSaveOperationSink = reconcileOp.publisher.sink(receiveCompletion: { completion in
139-
self.reconcileAndLocalSaveOperationSinks.remove(reconcileAndLocalSaveOperationSink)
139+
self.reconcileAndLocalSaveOperationSinks.with { $0.remove(reconcileAndLocalSaveOperationSink) }
140140
if case .failure = completion {
141141
self.modelReconciliationQueueSubject.send(completion: completion)
142142
}
143143
}, receiveValue: { mutationEvent in
144144
self.modelReconciliationQueueSubject.send(.mutationEvent(mutationEvent))
145145
})
146-
reconcileAndLocalSaveOperationSinks.insert(reconcileAndLocalSaveOperationSink)
146+
reconcileAndLocalSaveOperationSinks.with { $0.insert(reconcileAndLocalSaveOperationSink) }
147147
reconcileAndSaveQueue.addOperation(reconcileOp)
148148
}
149149

AmplifyPlugins/DataStore/AWSDataStoreCategoryPluginTests/TestSupport/Mocks/MockAWSIncomingEventReconciliationQueue.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ class MockAWSIncomingEventReconciliationQueue: IncomingEventReconciliationQueue
2424
return incomingEventSubject.eraseToAnyPublisher()
2525
}
2626

27-
static var lastInstance: MockAWSIncomingEventReconciliationQueue?
27+
static var lastInstance = AtomicValue<MockAWSIncomingEventReconciliationQueue?>(initialValue: nil)
2828
init(modelTypes: [Model.Type],
2929
api: APICategoryGraphQLBehavior,
3030
storageAdapter: StorageEngineAdapter,
@@ -34,7 +34,7 @@ class MockAWSIncomingEventReconciliationQueue: IncomingEventReconciliationQueue
3434
}
3535

3636
func updateLastInstance(instance: MockAWSIncomingEventReconciliationQueue) {
37-
MockAWSIncomingEventReconciliationQueue.lastInstance = instance
37+
MockAWSIncomingEventReconciliationQueue.lastInstance.set(instance)
3838
}
3939

4040
func start() {
@@ -50,11 +50,11 @@ class MockAWSIncomingEventReconciliationQueue: IncomingEventReconciliationQueue
5050
}
5151

5252
static func mockSendCompletion(completion: Subscribers.Completion<DataStoreError>) {
53-
lastInstance?.incomingEventSubject.send(completion: completion)
53+
lastInstance.get()?.incomingEventSubject.send(completion: completion)
5454
}
5555

5656
static func mockSend(event: IncomingEventReconciliationQueueEvent) {
57-
lastInstance?.incomingEventSubject.send(event)
57+
lastInstance.get()?.incomingEventSubject.send(event)
5858
}
5959

6060
func cancel() {

AmplifyPlugins/DataStore/DataStoreCategoryPlugin.xcodeproj/xcshareddata/xcschemes/AWSDataStoreCategoryPlugin.xcscheme

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,8 @@
2626
buildConfiguration = "Debug"
2727
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
2828
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
29-
shouldUseLaunchSchemeArgsEnv = "YES">
29+
shouldUseLaunchSchemeArgsEnv = "YES"
30+
enableThreadSanitizer = "YES">
3031
<Testables>
3132
<TestableReference
3233
skipped = "NO">

0 commit comments

Comments
 (0)