ably-js
ably-js copied to clipboard
React Native warns about setTimeout with long durations when using Ably on Android
Problem Statement:
When subscribing to a channel, React Native warns about setTimeout
with long durations when using Ably on Android. React Native will warn about any durations longer than 1 minute (60000 ms).
Setting a timer for a long period of time, i.e. multiple minutes, is a performance and
correctness issue on Android as it keeps the timer module awake, and timers can only
be called when the app is in the foreground.
See https://github.com/facebook/react-native/issues/12981 for more info.
(Saw setTimeout with duration 90000ms)
Reproduceable Example:
- Clone the reproducable example repo: https://github.com/kj800x/ReactNativeAblyReproducableExample
-
git clone https://github.com/kj800x/ReactNativeAblyReproducableExample
-
cd ReactNativeAblyReproducableExample
-
- Install dependencies:
-
npm i
-
react-native link
-
- Copy
secrets.example.json
tosecrets.json
and insert an api key. - Start android emulator
- Install the new app to the emulator
-
react-native run-android
-
- Observe that running the app causes warnings to appear when subscribing to the channel (on startup).
Related:
https://github.com/facebook/react-native/issues/12981
Presumably the suspend timeout (120s) and the comet recv timeout (90s).
Really the warning is a red herring, and making changes to avoid it won't actually change the things the warning is worried about: even if we remove the >60s timers there'll at least one <60s one active at all times anyway (when disconnected, the disconnected/suspendedRetryTimer; when connected, the the transport idleTimer).
I don't think the correctness issue it's warning about (timers not getting called when the app is backgrounded) is an issue for ably-js. We don't care about the timer for its own sake, only insofar as it controls the connection & network traffic; and the same mechanism that stops timers firing when an app is backgrounded also stops websocket traffic. So the connection will naturally die if backgrounded for more than ~15s anyway, by the server for not responding to pings, so when next foregrounded (and the timers belatedly fire) it'll disconnect and reconnect. If within the resume period it'll resume, if not it won't. If you need a websocket kept alive even when the app is backgrounded, only way to do that (on android) to put it in a backgound service, AFAIK. (Alternatively, use our mobile push notifications bridge as a fallback when the app is backgrounded)
If you want to suppress the warning, see https://stackoverflow.com/a/48778011