aws-amplify / amplify-js

A declarative JavaScript library for application development using cloud services.
https://docs.amplify.aws/lib/q/platform/js
Apache License 2.0
9.42k stars 2.12k forks source link

Datastore not syncing when Safari IOS is in background #11068

Closed francoisgelinas1 closed 1 year ago

francoisgelinas1 commented 1 year ago

JavaScript Framework

Angular

Amplify APIs

DataStore

Amplify Categories

api

Environment information

``` System: OS: macOS 12.6.3 CPU: (8) x64 Intel(R) Core(TM) i7-6700HQ CPU @ 2.60GHz Memory: 421.68 MB / 16.00 GB Shell: 5.8.1 - /bin/zsh Binaries: Node: 16.19.1 - /usr/local/opt/node@16/bin/node Yarn: 1.22.19 - /usr/local/bin/yarn npm: 8.19.3 - /usr/local/opt/node@16/bin/npm Browsers: Chrome: 110.0.5481.177 Safari: 16.3 npmPackages: @angular-devkit/build-angular: ^15.1.6 => 15.1.6 @angular/animations: ^15.1.5 => 15.1.5 @angular/cdk: ^15.1.5 => 15.1.5 @angular/cli: ^15.1.6 => 15.1.6 @angular/common: ^15.1.5 => 15.1.5 @angular/compiler: ^15.1.5 => 15.1.5 @angular/compiler-cli: ^15.1.5 => 15.1.5 @angular/core: ^15.1.5 => 15.1.5 @angular/flex-layout: ^15.0.0-beta.42 => 15.0.0-beta.42 @angular/forms: ^15.1.5 => 15.1.5 @angular/material: ^15.1.5 => 15.1.5 @angular/material-moment-adapter: ^15.1.5 => 15.1.5 @angular/platform-browser: ^15.1.5 => 15.1.5 @angular/platform-browser-dynamic: ^15.1.5 => 15.1.5 @angular/router: ^15.1.5 => 15.1.5 @angular/service-worker: ^15.1.5 => 15.1.5 @aws-amplify/ui-angular: ^3.2.8 => 3.2.8 @stripe/stripe-js: ^1.26.0 => 1.47.0 @types/jasmine: ~4.3.1 => 4.3.1 @types/node: ^18.14.0 => 18.14.0 aws-amplify: ^5.0.18 => 5.0.18 jasmine-core: ~4.5.0 => 4.5.0 jspdf: ^2.5.0 => 2.5.1 karma: ~6.4.1 => 6.4.1 karma-chrome-launcher: ~3.1.0 => 3.1.1 karma-coverage: ~2.2.0 => 2.2.0 karma-coverage-coffee-example: 1.0.0 karma-jasmine: ~5.1.0 => 5.1.0 karma-jasmine-html-reporter: ~2.0.0 => 2.0.0 lodash: ^4.17.21 => 4.17.21 moment: ^2.29.1 => 2.29.4 ng-table-virtual-scroll: ^1.4.0 => 1.6.0 rxjs: ~7.8.0 => 7.8.0 (6.6.7) rxjs/ajax: undefined () rxjs/fetch: undefined () rxjs/internal-compatibility: undefined () rxjs/operators: undefined () rxjs/testing: undefined () rxjs/webSocket: undefined () tslib: ^2.3.0 => 2.5.0 (1.14.1, 2.4.1, 2.3.1) typescript: ~4.9.5 => 4.9.5 zone-mix: undefined () zone-node: undefined () zone-testing: undefined () zone.js: ~0.12.0 => 0.12.0 zone.js/async-test: undefined () zone.js/async-test.min: undefined () zone.js/fake-async-test: undefined () zone.js/fake-async-test.min: undefined () zone.js/jasmine-patch: undefined () zone.js/jasmine-patch.min: undefined () zone.js/long-stack-trace-zone: undefined () zone.js/long-stack-trace-zone.min: undefined () zone.js/mocha-patch: undefined () zone.js/mocha-patch.min: undefined () zone.js/proxy: undefined () zone.js/proxy.min: undefined () zone.js/sync-test: undefined () zone.js/sync-test.min: undefined () zone.js/task-tracking: undefined () zone.js/task-tracking.min: undefined () zone.js/webapis-media-query: undefined () zone.js/webapis-media-query.min: undefined () zone.js/webapis-notification: undefined () zone.js/webapis-notification.min: undefined () zone.js/webapis-rtc-peer-connection: undefined () zone.js/webapis-rtc-peer-connection.min: undefined () zone.js/webapis-shadydom: undefined () zone.js/webapis-shadydom.min: undefined () zone.js/wtf: undefined () zone.js/wtf.min: undefined () zone.js/zone-bluebird: undefined () zone.js/zone-bluebird.min: undefined () zone.js/zone-error: undefined () zone.js/zone-error.min: undefined () zone.js/zone-legacy: undefined () zone.js/zone-legacy.min: undefined () zone.js/zone-patch-canvas: undefined () zone.js/zone-patch-canvas.min: undefined () zone.js/zone-patch-cordova: undefined () zone.js/zone-patch-cordova.min: undefined () zone.js/zone-patch-electron: undefined () zone.js/zone-patch-electron.min: undefined () zone.js/zone-patch-fetch: undefined () zone.js/zone-patch-fetch.min: undefined () zone.js/zone-patch-jsonp: undefined () zone.js/zone-patch-jsonp.min: undefined () zone.js/zone-patch-message-port: undefined () zone.js/zone-patch-message-port.min: undefined () zone.js/zone-patch-promise-test: undefined () zone.js/zone-patch-promise-test.min: undefined () zone.js/zone-patch-resize-observer: undefined () zone.js/zone-patch-resize-observer.min: undefined () zone.js/zone-patch-rxjs: undefined () zone.js/zone-patch-rxjs-fake-async: undefined () zone.js/zone-patch-rxjs-fake-async.min: undefined () zone.js/zone-patch-rxjs.min: undefined () zone.js/zone-patch-socket-io: undefined () zone.js/zone-patch-socket-io.min: undefined () zone.js/zone-patch-user-media: undefined () zone.js/zone-patch-user-media.min: undefined () npmGlobalPackages: @angular/cli: 15.1.6 @aws-amplify/cli: 10.7.3 corepack: 0.16.0 http-server: 14.1.1 npm: 9.5.0 nx: 15.7.2 renamer: 4.0.0 ```

Describe the bug

When Safari IOS is in background, the websocket is closed and Datastore stops listening to changes. When you open Safari again, you get this error:

WebSocket connection to 'wss://anshee6pbze3lptwgjfeem7aw4.appsync-realtime-api.ca-central-1.amazonaws.com/graphql?header=[...]' failed: The operation couldn’t be completed. (kNWErrorDomainPOSIX error 53 - Software caused connection abort)

The Datastore was not synced during the time Safari was in background.

Expected behavior

Sync the datastore after websocket failed

Reproduction steps

  1. On IOS Safari, open an app with Datastore activated
  2. Go to home or another app for some time (more than couple seconds) and make some changes to the data on another device
  3. Go back to Safari
  4. See the error in console and notice that changes made are not synced

Screen Shot 2023-03-09 at 8 18 20 PM

Mobile Device

Iphone

Mobile Operating System

16.3.1

Mobile Browser

Safari

Mobile Browser Version

16.3

Additional information and screenshots

No response

dpilch commented 1 year ago

This appears to be an issue in Safari since iOS 15 (https://developer.apple.com/forums/thread/685403).

The behavior of Safari websockets changed with the introduction of experimental feature "NSURLSession WebSocket".

You can see a similar failure with this test page https://libwebsockets.org/testserver/. Follow the same reproduction steps by placing Safari in the background for a few seconds then see that the websocket disconnected.

It is possible to disable this experimental feature on a per device basis, and the websockets will function as expected.

  1. Open Settings app
  2. Select "Safari"
  3. Scroll to bottom and select "Advanced"
  4. Select "Experimental Features"
  5. Find "NSURLSession WebSocket" and disable.

That doesn't really help your users though (unless they all disable the feature), but it would help pin down the root cause. If you have the time could you confirm disabling this feature fixes the issue on your app?

We'll look to see if there is a fix on our end to bypass the bug.

francoisgelinas1 commented 1 year ago

Thank's for your response!

It fixed the problem after i disabled the feature and restarted the iPhone.

Even if there is a workaround, do you thing it would be possible to catch the error of the websocket and sync again the Datastore?

dpilch commented 1 year ago

Yes, some sort of reconnect logic on the error will probably be the fix.