aws-amplify/amplify-swift

WebSocket reconnection delay when app transitions from background to foreground

Opened this issue · 3 comments

Describe the bug

Our clients are experiencing issues with receiving delta changes when transitioning between background and foreground states.
Issue Details:
When the app moves to the background, the WebSocket connection disconnects as expected.
Upon returning to the foreground, the WebSocket reconnection is delayed, taking anywhere from 3 to 5 minutes, sometimes even longer. The reconnection time is inconsistent.
As a result, users are unable to receive the latest data (delta changes) in a timely manner, causing significant problems in real-time data sync.
Key Questions:
What is the expected reconnection time for WebSocket after moving from background to foreground?
What is the minimum duration users should expect to wait for receiving delta changes after resuming from the background?
Is there any configuration from that we can modify the time as per our need?

This delay is negatively impacting user experience in our production app, and we’re seeking guidance on how to resolve this issue.

Steps To Reproduce

Just moved the application to background to foreground.

Expected behavior

  1. The WebSocket connection should resume immediately when the app transitions from background to foreground.
  2. Delta changes should be reflected to users without delay, ensuring real-time data synchronization as soon as the app is active again.

Amplify Framework Version

2.37.0

Amplify Categories

DataStore

Dependency manager

Swift PM

Swift version

5.10

CLI version

12.6

Xcode version

15.3

Relevant log output

<details>
<summary>The application was brought to the foreground on 2024-09-16 18:29:16.658564+0530 . However, the WebSocket connection was not re-established immediately. The first successful connection message was logged at 2024-09-16 18:33:42.039403+0530.

This delay occurred for both:

[WebSocketClient]
[APIAppSyncRealTimeClient]

There was a gap of approximately 4 minutes and 26 seconds between the app being brought to the foreground and the WebSocket connection being re-established.</summary>


2024-09-16 18:29:16.658564+0530 INVFormsApp-mRounds[4508:1327673] [APIAppSyncRealTimeClient] [AppSyncRealTimeClient] Received subscription request id: 722FBAAA-589D-4651-A8C3-11C37C950539, query: {"query":"subscription OnCreateLocation {\n  onCreateLocation {\n    id\n    archivedAt\n    archivedBy\n    constField\n    createdAt\n    createdBy\n    description\n    image\n    isArchived\n    isUnit\n    locationId\n    model\n    name\n    parentId\n    plantsID\n    searchTerm\n    updatedAt\n    wasUnit\n    __typename\n  }\n}"}
2024-09-16 18:29:16.660026+0530 INVFormsApp-mRounds[4508:1327696] [APIAppSyncRealTimeSubscription] [AppSyncRealTimeSubscription-722FBAAA-589D-4651-A8C3-11C37C950539] Start subscribing
2024-09-16 18:29:16.663505+0530 INVFormsApp-mRounds[4508:1327168] [APIAppSyncRealTimeSubscription] [AppSyncRealTimeSubscription-D0B1C3F4-A902-4284-8BA2-3A1C30EE1B74] Start subscribing
2024-09-16 18:29:16.663606+0530 INVFormsApp-mRounds[4508:1327715] [APIAppSyncRealTimeSubscription] [AppSyncRealTimeSubscription-8C96C4C0-24CA-4982-AD16-EB336E5F098E] Start subscribing
*****SYNC onUpdate Subscription of Location connect state is connecting
*****SYNC onDelete Subscription of Location connect state is connecting
2024-09-16 18:29:16.663708+0530 INVFormsApp-mRounds[4508:1327168] [APIAppSyncRealTimeSubscription] [AppSyncRealTimeSubscription-E672A58E-D9E6-426D-ADCD-302260302F83] Start subscribing
2024-09-16 18:29:16.663778+0530 INVFormsApp-mRounds[4508:1327715] [APIAppSyncRealTimeSubscription] [AppSyncRealTimeSubscription-4E073E91-19B7-4B6C-9F8D-C20AB8875740] Start subscribing
*****SYNC onCreate Subscription of Assets connect state is connecting
*****SYNC onUpdate Subscription of Assets connect state is connecting
2024-09-16 18:29:16.663810+0530 INVFormsApp-mRounds[4508:1327809] [APIAppSyncRealTimeSubscription] [AppSyncRealTimeSubscription-C6F1C22D-DB60-4E16-AF9C-006A65808963] Start subscribing
*****SYNC onDelete Subscription of Assets connect state is connecting

2024-09-16 18:29:16.693187+0530 INVFormsApp-mRounds[4508:1327674] [connection] nw_read_request_report [C20] Receive failed with error "Software caused connection abort"
2024-09-16 18:29:16.694794+0530 INVFormsApp-mRounds[4508:1327813] [websocket] Read completed with an error Software caused connection abort
2024-09-16 18:29:16.695126+0530 INVFormsApp-mRounds[4508:1327673] [WebSocketClient] [WebSocketClient] read message failed with connection state NSURLSessionTaskState(rawValue: 2), error Error Domain=NSPOSIXErrorDomain Code=53 "Software caused connection abort" UserInfo={NSDescription=Software caused connection abort}
2024-09-16 18:29:16.695159+0530 INVFormsApp-mRounds[4508:1327673] [WebSocketClient] [WebSocketClient] WebSocket connection state is NSURLSessionTaskState(rawValue: 2). Failed to read websocket message
2024-09-16 18:29:16.695406+0530 INVFormsApp-mRounds[4508:1327813] Task <3E164117-104F-424B-8AC6-CAC979954A87>.<1> finished with error [53] Error Domain=NSPOSIXErrorDomain Code=53 "Software caused connection abort" UserInfo={NSDescription=Software caused connection abort, _NSURLErrorRelatedURLSessionTaskErrorKey=(
    "LocalWebSocketTask <3E164117-104F-424B-8AC6-CAC979954A87>.<1>"
), _NSURLErrorFailingURLSessionTaskErrorKey=LocalWebSocketTask <3E164117-104F-424B-8AC6-CAC979954A87>.<1>}
2024-09-16 18:29:16.695565+0530 INVFormsApp-mRounds[4508:1327673] [WebSocketClient] [WebSocketClient] URLSession didCompleteWithError: Error Domain=NSPOSIXErrorDomain Code=53 "Software caused connection abort" UserInfo={NSDescription=Software caused connection abort, _NSURLErrorRelatedURLSessionTaskErrorKey=(
    "LocalWebSocketTask <3E164117-104F-424B-8AC6-CAC979954A87>.<1>"
), _NSURLErrorFailingURLSessionTaskErrorKey=LocalWebSocketTask <3E164117-104F-424B-8AC6-CAC979954A87>.<1>})
2024-09-16 18:29:16.695677+0530 INVFormsApp-mRounds[4508:1327673] [APIAppSyncRealTimeClient] [AppSyncRealTimeClient] Received websocket event error(AWSPluginsCore.WebSocketClient.Error.connectionLost)
2024-09-16 18:29:16.695702+0530 INVFormsApp-mRounds[4508:1327673] [APIAppSyncRealTimeClient] [AppSyncRealTimeClient] WebSocket error event: connectionLost
2024-09-16 18:29:16.695801+0530 INVFormsApp-mRounds[4508:1327674] [connection] nw_flow_add_write_request [C20 3.231.232.142:443 failed parent-flow (satisfied (Path is satisfied), interface: en0[802.11], ipv4, dns)] cannot accept write requests
2024-09-16 18:29:16.695844+0530 INVFormsApp-mRounds[4508:1327674] [connection] nw_write_request_report [C20] Send failed with error "Socket is not connected"
2024-09-16 18:29:16.695968+0530 INVFormsApp-mRounds[4508:1327715] [APIRetryableGraphQLSubscriptionOperation<MutationSync<AnyModel>>] Failed with subscription request: APIError: WebSocketClient connection aborted
Recovery suggestion: WebSocketClient connection aborted
Caused by:
Error Domain=NSURLErrorDomain Code=-1005 "(null)"
2024-09-16 18:29:16.695969+0530 INVFormsApp-mRounds[4508:1327810] [APIRetryableGraphQLSubscriptionOperation<MutationSync<AnyModel>>] Failed with subscription request: APIError: WebSocketClient connection aborted
Recovery suggestion: WebSocketClient connection aborted
Caused by:
Error2024-09-16 18:29:16.696014+0530 INVFormsApp-mRounds[4508:1327715] [DataStoreIncomingAsyncSubscriptionEventPublisher] [InitializeSubscription.1] API.subscribe failed for `IssuesLogHistory` error: WebSocketClient connection aborted
 Domain=NSURLErrorDomain Code=-1005 "(null)"
2024-09-16 18:29:16.696044+0530 INVFormsApp-mRounds[4508:1327168] [APIRetryableGraphQLSubscriptionOperation<MutationSync<AnyModel>>] Failed with subscription request: APIError: WebSocketClient connection aborted
Recovery suggestion: WebSocketClient connection aborted
Caused by:
Error Domain=NSURLErrorDomain Code=-1005 "(null)"
2024-09-16 18:29:16.696075+0530 INVFormsApp-mRounds[4508:1327811] [APIRetryableGraphQLSubscriptionOperation<MutationSync<AnyModel>>] Failed with subscription request: APIError: WebSocketClient connection aborted
Recovery suggestion: WebSocketClient connection aborted
Caused by:
Error Domain=NSURLErrorDomain Code=-1005 "(null)"
2024-09-16 18:29:16.697171+0530 INVFormsApp-mRounds[4508:1327810] [DataStoreIncomingAsyncSubscriptionEventPublisher] [InitializeSubscription.1] API.subscribe failed for `AdhocRoundDetails` error: WebSocketClient connection aborted
2024-09-16 18:29:16.697281+0530 INVFormsApp-mRounds[4508:1327168] [DataStoreIncomingAsyncSubscriptionEventPublisher] [InitializeSubscription.1] API.subscribe failed for `IssuesList` error: WebSocketClient connection aborted
2024-09-16 18:29:16.697278+0530 INVFormsApp-mRounds[4508:1327811] [DataStoreIncomingAsyncSubscriptionEventPublisher] [InitializeSubscription.1] API.subscribe failed for `ActionsLogHistory` error: WebSocketClient connection aborted
2024-09-16 18:29:16.696243+0530 INVFormsApp-mRounds[4508:1327814] [APIRetryableGraphQLSubscriptionOperation<MutationSync<AnyModel>>] Failed with subscription request: APIError: WebSocketClient connection aborted
Recovery suggestion: WebSocketClient connection aborted
Caused by:
Error Domain=NSURLErrorDomain Code=-1005 "(null)"
2024-09-16 18:29:16.697361+0530 INVFormsApp-mRounds[4508:1327811] [APIRetryableGr2024-09-16 18:29:16.697362+0530 INVFormsApp-mRounds[4508:1327168] [APIRetryableGraphQLSubscriptionOperation<MutationSync<AnyModel>>] Failed with subscription request: APIError: WebSocketClient connection aborted
Recovery suggestion: WebSocketClient connection aborted
Caused by:
Error Domain=NSURLErrorDomain Code=-1005 "(null)"
aphQLSubscriptionOperation<MutationSync<AnyModel>>] Failed with subscription request: APIError: WebSocketClient connection aborted
Recovery suggestion: WebSocketClient connection aborted
Caused by:
Error Domain=NSURLErrorDomain Code=-1005 "(null)"
2024-09-16 18:29:16.697251+0530 INVFormsApp-mRounds[4508:1327715] [APIRetryableGraphQLSubscriptionOperation<MutationSync<AnyModel>>] Failed with subscription request: APIError: WebSocketClient connection aborted
Recovery suggestion: WebSocketClient connection aborted
Caused by:
Error Domain=NSURLErrorDomain Code=-1005 "(null)"
2024-09-16 18:29:16.696340+0530 INVFormsApp-mRounds[4508:1327809] [APIRetryableGraphQLSubscriptionOperati2024-09-16 18:29:16.697469+0530 INVFormsApp-mRounds[4508:1327810] [APIRetryableGraphQLSubscriptionOperation<MutationSync<AnyModel>>] Failed with subscription request: APIError: WebSocketClient connection aborted
Recovery suggestion: WebSocketClient connection aborted
Caused by:
Error Domain=NSURLErrorDomain Code=-1005 "(null)"
2024-09-16 18:29:16.697480+0530 INVFormsApp-mRounds[4508:1327715] [DataStoreIncomingAsyncSubscriptionEventPublisher] [InitializeSubscription.1] API.subscribe failed for `RoundDetails` error: WebSocketClient connection aborted
on<MutationSync<AnyModel>>] Failed with subscription request: APIError: WebSocketClient connection aborted
Recovery suggestion: WebSocketClient connection aborted
Caused by:
Error Domain=NSURLErrorDomain Code=-1005 "(null)"
2024-09-16 18:29:16.697436+0530 INVFormsApp-mRounds[4508:1327168] [DataStoreIncomingAsyncSubscriptionEventPublisher] [InitializeSubscription.1] API.subscribe failed for `ActionsLogHistory` error: WebSocketClient connection aborted
2024-09-16 18:29:16.697502+0530 INVFormsApp-mRounds[4508:1327810] [DataStoreIncomingAsyncSubscriptionEventPublisher] [InitializeSubscription.1] API.subscribe failed for `Users` error: WebSocketClient connection aborted
2024-09-16 18:29:16.697388+0530 INVFormsApp-mRounds[4508:1327814] [DataStoreIncomingAsyncSubscriptionEventPublisher] [InitializeSubscription.1] API.subscribe failed for `UserDevices` error: WebSocketClient connection aborted
2024-09-16 18:29:16.697445+0530 INVFormsApp-mRounds[4508:1327811] [DataStoreIncomingAsyncSubscriptionEventPublisher] [InitializeSubscription.1] API.subscribe failed for `RoundDetails` error: WebSocketClient connection aborted
2024-09-16 18:29:16.697555+0530 INVFormsApp-mRounds[4508:1327715] [APIRetryableGraphQLSubscriptionOperation<MutationSync<AnyModel>>] Failed with subscription request: APIError: WebSocketClient connection aborted
Recovery suggestion: WebSocketClient connection aborted
Caused by:
Error Domain=NSURLErrorDomain Code=-1005 "(null)"
2024-09-16 18:29:16.2024-09-16 18:29:16.698201+0530 INVFormsApp-mRounds[4508:1327811] [APIRetryableGraphQLSubscriptionOperation<MutationSync<AnyModel>>] Failed with subscription request: APIError: WebSocketClient connection aborted
Recovery suggestion: WebSocketClient connection aborted
Caused by:
Error Domain=NSURLErrorDomain Code=-1005 "(null)"
698161+0530 INVFormsApp-mRounds[4508:1327715] [DataStoreIncomingAsyncSubscriptionEventPublisher] [InitializeSubscription.1] API.subscribe failed for `AdhocRoundDetails` error: WebSocketClient connection aborted
2024-09-16 18:29:16.698229+0530 INVFormsApp-mRounds[4508:1327811] [DataStoreIncomingAsyncSubscriptionEventPublisher] [InitializeSubscription.1] API.subscribe failed for `Plants` error: WebSocketClient connection aborted
2024-09-16 18:29:16.697556+0530 INVFormsApp-mRounds[4508:1327809] [DataStoreIncomingAsyncSubscriptionEventPublisher] [InitializeSubscription.1] API.subscribe failed for `ActionsLogHistory` error: WebSocketClient connection aborted
2024-09-16 18:29:16.698248+0530 INVFormsApp-mRounds[4508:1327810] [APIRetryableGraphQLSubscriptionOperation<MutationSync<AnyModel>>] Failed with subscription request: APIError: WebSocketClient connection aborted
Recovery suggestion: WebSocketClient connection aborted
Caused by:
Error Domain=NSURLErrorDomain Code=-1005 "(null)"
2024-09-16 18:29:16.6976262024-09-16 18:29:16.698361+0530 INVFormsApp-mRounds[4508:1327811] [APIRetryableGraphQLSubscriptionOperation<MutationSync<AnyModel>>] Failed with subscription request: APIError: WebSocketClient connection aborted
Recovery suggestion: WebSocketClient connection aborted
Caused by:
Error Domain=NSURLErrorDomain Code=-1005 "(null)"
2024-09-16 18:29:16.698368+0530 INVFormsApp-mRounds[4508:1327715] [APIRetryableGraphQLSubscriptionOperation<MutationSync<AnyModel>>] Failed with subscription request: APIError: WebSocketClient connection aborted
Recovery suggestion: WebSocketClient connection aborted
Caused by:
Error Domain=NSURLErrorDomain Code=-1005 "(null)"
2024-09-16 18:29:16.698294+0530 INVFormsApp-mRounds[4508:1327810] [DataStoreIncomingAsyncSubscriptionEventPublisher] [InitializeSubscription.1] API.subscribe failed for `IssuesList` error: WebSocketClient connection aborted

2024-09-16 18:33:42.039403+0530 INVFormsApp-mRounds[4508:1329741] [WebSocketClient] [WebSocketClient] Websocket connected
2024-09-16 18:33:42.040074+0530 INVFormsApp-mRounds[4508:1329741] [APIAppSyncRealTimeClient] [AppSyncRealTimeClient] Received websocket event connected
2024-09-16 18:33:42.040334+0530 INVFormsApp-mRounds[4508:1329741] [APIAppSyncRealTimeClient] [AppSyncRealTimeClient] WebSocket connected
```

Is this a regression?

Yes

Regression additional context

No response

Platforms

iOS

OS Version

iOS 16.7.10

Device

iPhone X

Specific to simulators

No response

Additional context

No response

Thanks for your report, @Innovation2012. Someone from the team will take a look at this as soon as they can. Until then, can you provide the code snippet for initializing the DataStore?

Hi @vincetran
Thanks for replying and here is the sample DataStore initialing code below:

            let amplifyModels = AmplifyModels()
            let dataStorePlugin = **self.prepareAmplifyAWSDatastore**(models: amplifyModels)
            awsdataStorePlugin = dataStorePlugin
            let apiStorePlugin = **self.prepareAmplifyAPI**(models: amplifyModels)
            let authPlugin = **self.prepareAWSCognitoAuth**()
            self.awsAPIStorePlugin = apiStorePlugin
            try Amplify.add(plugin: apiStorePlugin)
            try Amplify.add(plugin: dataStorePlugin)
            try Amplify.add(plugin: authPlugin)
            try Amplify.add(plugin: AWSS3StoragePlugin())
            let amplifyConfiguration = try AmplifyConfiguration(configurationFile: fileURL)
            try Amplify.configure(amplifyConfiguration)
            Amplify.Logging.logLevel = .verbose
            **self.intiateDataSync**(completion: completion)


func **prepareAmplifyAWSDatastore**(models: AmplifyModels) -> AWSDataStorePlugin {
        let configuration: DataStoreConfiguration = .custom(
            errorHandler: { storeError in
                dlog("Amplify Store Error \(storeError)")
            },
            syncInterval: TimeInterval(INVCloudRequestManagerUtility.shared.appConfigurationModel.syncInterval),
            syncMaxRecords: INVCloudRequestManagerUtility.shared.appConfigurationModel.syncMaxRecords == 0 ? DataStoreConfiguration.defaultSyncMaxRecords : UInt(INVCloudRequestManagerUtility.shared.appConfigurationModel.syncMaxRecords), syncPageSize: INVCloudRequestManagerUtility.shared.appConfigurationModel.syncPageSize,
            syncExpressions: INVAmplifyDataModelHandler.shared.getSyncExpressions())
        let dataStorePlugin = AWSDataStorePlugin(modelRegistration: models, configuration: configuration)
        return dataStorePlugin
    }

func **prepareAmplifyAPI**(models: AmplifyModels) -> AWSAPIPlugin {
        let apiStorePlugin = AWSAPIPlugin(modelRegistration: models, sessionFactory: nil, apiAuthProviderFactory: nil)
        return apiStorePlugin
    }


func **prepareAWSCognitoAuth**() -> AWSCognitoAuthPlugin {
        let authPlugin = AWSCognitoAuthPlugin()
        awsCognitoAuthPlugin = authPlugin
        return authPlugin
    }

func **intiateDataSync**(completion: CloudCompletion? = nil) {
        Task {
            do {
                try await Amplify.DataStore.start()
                completion?(.success(()))
            } catch {
                completion?(.failure(error.prepareNSError()))
            }
        }
    }



@Innovation2012 Thanks for providing the sample code. We'll work on reproducing the issue.