diff --git a/Sources/AWSAppSyncApolloExtensions/Websocket/AppSyncWebSocketClient.swift b/Sources/AWSAppSyncApolloExtensions/Websocket/AppSyncWebSocketClient.swift index fc6aebb..1265bb6 100644 --- a/Sources/AWSAppSyncApolloExtensions/Websocket/AppSyncWebSocketClient.swift +++ b/Sources/AWSAppSyncApolloExtensions/Websocket/AppSyncWebSocketClient.swift @@ -17,10 +17,24 @@ public class AppSyncWebSocketClient: NSObject, ApolloWebSocket.WebSocketClient, // MARK: - ApolloWebSocket.WebSocketClient - public var request: URLRequest public var delegate: ApolloWebSocket.WebSocketClientDelegate? public var callbackQueue: DispatchQueue + private let requestLock = NSLock() + private var _request: URLRequest + public var request: URLRequest { + get { + requestLock.lock() + defer { requestLock.unlock() } + return _request + } + set { + requestLock.lock() + defer { requestLock.unlock() } + _request = newValue + } + } + // MARK: - Public public var publisher: AnyPublisher { @@ -71,7 +85,7 @@ public class AppSyncWebSocketClient: NSObject, ApolloWebSocket.WebSocketClient, callbackQueue: DispatchQueue, authorizer: AppSyncAuthorizer ) { - self.request = URLRequest(url: appSyncRealTimeEndpoint(endpointURL)) + self._request = URLRequest(url: appSyncRealTimeEndpoint(endpointURL)) self.delegate = delegate self.callbackQueue = callbackQueue self.authorizer = authorizer diff --git a/Tests/AWSAppSyncApolloExtensionsTests/Websocket/AppSyncWebSocketClientTests.swift b/Tests/AWSAppSyncApolloExtensionsTests/Websocket/AppSyncWebSocketClientTests.swift index 75cc9a5..13a374b 100644 --- a/Tests/AWSAppSyncApolloExtensionsTests/Websocket/AppSyncWebSocketClientTests.swift +++ b/Tests/AWSAppSyncApolloExtensionsTests/Websocket/AppSyncWebSocketClientTests.swift @@ -119,6 +119,37 @@ final class AppSyncWebSocketClientTests: XCTestCase { await fulfillment(of: [messageReceivedExpectation], timeout: 5) } + func testConcurrentURLRequestAccess() async { + let endpoint = URL(string: "https://abc.appsync-api.us-east-1.amazonaws.com/graphql")! + + let websocket = AppSyncWebSocketClient( + endpointURL: endpoint, + authorizer: APIKeyAuthorizer(apiKey: "apiKey")) + + let raceConditionExpectation = expectation(description: "Race condition test") + raceConditionExpectation.expectedFulfillmentCount = 2 + + let iterations = 1000 + + // Thread 1: Continuous reading + DispatchQueue.global(qos: .userInitiated).async { + for _ in 0..