react-native-code-push
react-native-code-push copied to clipboard
Android. Rollbacks when app started on background and then killled (before moving to foreground)
Steps to Reproduce
- Send new codepush bundle to AppCenter
- Launch app
- Wait for new codepush bundle downloaded
- Kill app (should not be in memory)
- Turn off device screen
- Execute
adb shell am start -n com.your.package/.YourActivity
(or send push-notification), wait for CodePush() initialized and initializeUpdateAfterRestart() executed - Execute
adb shell am kill com.your.package
(emulating use-case of app killing by Android system) - Launch app
Expected Behavior
Pending codepush NOT marked as isLoading=true when app started on background.
Actual Behavior
Pending codepush marked as isLoading=true
when app started on background and rollback occured on next app launch (step8).
Reproducible Demo
- You can reproduce this on any app integrated with codepush
Environment
- react-native-code-push version: 7.0.1
- react-native version: 0.65.1
- iOS/Android/Windows version: any Android versions
- Does this reproduce on a debug build or release build? any build type
- Does this reproduce on a simulator, or only on a physical device? any devices/emulators
More about our history with rollbacks problem analysis and fixing.
At some point(about 2 years ago) rollbacks number start increase rapidly on Android (~15%)
We have made several attempts to solve problems:
- updating to the latest versions of the code-push library
- changing
InstallMode
fromON_NEXT_RESUME
toON_NEXT_RESTART
None of this helped.
The main problem was that we did not understand who had rollbacks, so that we could analyze the logs and crash reports for specific users.
We decided to add custom analytics of codePush stages. As result, we noticed that users often have retrays and more of them have succeeded installs after the nth retray. At the same time, we still have not seen anything about these users in the logs and crash reports.
We decided to add more logs and collect data from different stages of the application on the native and JS side. As soon as a rollback occurs, we send the collected data with an assumption about the reason:
-
RollbackByNativeCrash
-
RollbackByJSError
-
RollbackByJSUnhPromiseRej
-
RollbackByForceQuitSupposeSlowNative
-
RollbackByForceQuitSupposeSlowJS
-
RollbackByUnknown
As result, we received data that the bulk of rollbacks are in the RollbackByUnknown
category.
This made us happy, because we cut off options with native crashes and errors on the JS side.
From the logs, it was clear that we reached the JS started
stage (at index.ts) and notifyAppReady
was not called.
We have made an assumption:
- If app is launched in the background, then there is a chance that the system will kill app before the user launched it and
notifyAppReady
is not called -> rollback - An example of such cases: app is thrown out of memory -> push notification received -> new bundle is marked as
isLoading
and waiting fornotifyAppReady
from the JS side -> kill app process -> launch app again
This assumption was confirmed, the number of rollbacks began to decrease (~15% -> ~5%)
What we have done:
- Check background/foreground state at app start moment
- If it is background, then skip step
mSettingsManager.savePendingUpdate(pendingUpdate.getString(CodePushConstants.PENDING_UPDATE_HASH_KEY), true);
in the CodePush.initializeUpdateAfterRestart() method
Then we have made another assumption:
- If app moved to the background at the
JS Started
stage and the App component did not have time to initialize/render, then there is a chance that the system will kill app andnotifyAppReady
will not be called -> rollback - An example of such cases: launch app -> turn-off screen, or block app by another app(for example, by an incoming call) -> kill app process
This assumption was confirmed, the number of rollbacks began to decrease (~5% -> ~1%)
What we have done:
- Check background/foreground state at
JS Started
moment - if it is background, then reset the
isLoading
state
Our workarounds implementation (with custom logs) https://gist.github.com/aamagda/6061b867da8298a5787e81e621fe2f5a
UPD Logger implementation https://github.com/EruditorGroup/react-native-code-push/pull/2
Hi @aamagda, Does code push supports react native version 0.68.1. Because as per the documentation only these versions are mentioned
This issue has been automatically marked as stale because it has not had any activity for 60 days. It will be closed if no further activity occurs within 15 days of this comment.
Up
This issue has been automatically marked as stale because it has not had any activity for 60 days. It will be closed if no further activity occurs within 15 days of this comment.
This issue will now be closed because it hasn't had any activity for 15 days after stale. Please feel free to open a new issue if you still have a question/issue or suggestion.
Up
This issue has been automatically marked as stale because it has not had any activity for 60 days. It will be closed if no further activity occurs within 15 days of this comment.
This issue has been automatically marked as stale because it has not had any activity for 60 days. It will be closed if no further activity occurs within 15 days of this comment.
Thanks @aamagda for looking into this. To add some data about the possible impacts of this bug, here is the data of two different apps in production:
- app A: on Android 60k active, 20k rollbacks (on iOS 162k active, 10 rollbacks)
- app B: on Android 5k active, 2k rollbacks (on iOS 13k active, 39 rollbacks)
How does your workaround works in the cases mentioned here? @MikhailSuendukov talked about valid rollbacks like unsuccessful downloads or invalid js bundles, although I wonder if it should really "rollback" since there is no installation done - the bundle is simply corrupted and should be discarded/retried.
up