react-native-code-push icon indicating copy to clipboard operation
react-native-code-push copied to clipboard

Android. Rollbacks when app started on background and then killled (before moving to foreground)

Open aamagda opened this issue 2 years ago • 3 comments

Steps to Reproduce

  1. Send new codepush bundle to AppCenter
  2. Launch app
  3. Wait for new codepush bundle downloaded
  4. Kill app (should not be in memory)
  5. Turn off device screen
  6. Execute adb shell am start -n com.your.package/.YourActivity (or send push-notification), wait for CodePush() initialized and initializeUpdateAfterRestart() executed
  7. Execute adb shell am kill com.your.package (emulating use-case of app killing by Android system)
  8. 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

aamagda avatar Jul 22 '22 13:07 aamagda

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 from ON_NEXT_RESUME to ON_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 for notifyAppReady 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 and notifyAppReady 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

aamagda avatar Jul 22 '22 13:07 aamagda

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

aamagda avatar Jul 22 '22 14:07 aamagda

Hi @aamagda, Does code push supports react native version 0.68.1. Because as per the documentation only these versions are mentioned

image

geekyoperand avatar Jul 26 '22 22:07 geekyoperand

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.

ghost avatar Oct 16 '22 09:10 ghost

Up

aamagda avatar Oct 20 '22 07:10 aamagda

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.

ghost avatar Dec 19 '22 09:12 ghost

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.

ghost avatar Jan 03 '23 18:01 ghost

Up

aamagda avatar Jan 03 '23 18:01 aamagda

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.

Minishlink avatar Oct 16 '23 13:10 Minishlink

up

aamagda avatar Feb 09 '24 19:02 aamagda