-
Notifications
You must be signed in to change notification settings - Fork 112
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Remove fatalError
in case of persistent store backup failure and add more logging to store migration
#2481
Remove fatalError
in case of persistent store backup failure and add more logging to store migration
#2481
Conversation
…st log to Sentry with error level.
You can trigger an installable build for these changes by visiting CircleCI here. |
You can trigger optional UI/connected tests for these changes by visiting CircleCI here. |
Generated by 🚫 dangerJS |
fatalError
in case of persistent store backup failurefatalError
in case of persistent store backup failure and add more logging to store migration
Hey! I'm moving this to 4.7 because 4.6 has been cut. If you need this to make it to 4.6, please feel free to ping me. |
@woocommerce/ios-developers @loremattei I was thinking about trying this for release 4.6, lemme know if you have other thoughts! @shiki I saw that you were also thinking about working on recovery from backup failure, does this align with your plan? I looked at more crash events on Sentry from release 4.5, and it seems like the crashes were mostly from model version 27 to 28 now (v28 was released in the same release 4.5). So it looks like one of these migration steps failed when migrating from model version 27 to 28: woocommerce-ios/Storage/Storage/CoreData/CoreDataIterativeMigrator.swift Lines 201 to 224 in 39e5c78
I added more logging for the error that occurred in this function, and I have a strong suspicion that it might be related to the file system access. This PR also removed |
Yup. You pretty much did it. 😅 I'll still take a look at what else we can do though. Perhaps maybe adding unit tests. Or I could work on #2370. I'll review this today. Thank you, Jaclyn. 🙇 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
✔️ Tested by making the first loadPersistentStores()
call fail. The app recovered successfully and app operations still seem to be intact.
@@ -48,34 +48,22 @@ public class CoreDataManager: StorageManagerType { | |||
|
|||
/// Backup the old Store | |||
/// | |||
var persistentStoreBackupError: Error? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not related to this line.
Regarding public lazy var persistentContainer: NSPersistentContainer = {
. This might be something we can look into in the future. From Apple docs:
If a property marked with the lazy modifier is accessed by multiple threads simultaneously and the property has not yet been initialized, there’s no guarantee that the property will be initialized only once.
🙈
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ugh yea I don't feel super good about having persistentContainer: NSPersistentContainer
as a public lazy var, since it could be first triggered by anywhere (like the Reviews data source before). maybe this could be part of the effort to untangle Core Data setup from the app setup? #2370
@@ -102,7 +102,16 @@ public struct CoreDataIterativeMigrator { | |||
debugMessages.append(migrationAttemptMessage) | |||
DDLogWarn(migrationAttemptMessage) | |||
|
|||
guard migrateStore(at: sourceStore, storeType: storeType, fromModel: modelFrom, toModel: modelTo, with: migrateWithModel) == true else { | |||
let (success, migrateStoreError) = migrateStore(at: sourceStore, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not related to this line.
I noticed that the errors we were getting are missing reasons for the failed migrations. For example:
It looks like we don't return any debugging messages for cases where we return false
. Example:
guard let sourceMetadata = try metadataForPersistentStore(storeType: storeType, at: sourceStore) else { | |
return (false, []) | |
} |
Do you think we should add messages for those?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking more closely, it looks like this will be handled by the do catch
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
there are many points of failure in this function CoreDataIterativeMigrator. iterativeMigrate
, and I think the most critical one is probably where it migrates the store in this call to migrateStore
. later in this file I updated to return the error for each point of failure (actual migration error, or backup error) and adding this error to debugMessages
below (L113)
@shiki thanks a lot for the review! I responded to your comments, lemme know if I missed anything. the release branch usually gets merged back to |
Merge it! |
hey @loremattei I just merged this PR to release 4.6 branch! if possible, it'd be great if the changes here in release 4.6 can be merged back to |
Part of #2371
Changes
Since we really see a flood of crashes on Sentry and mentions on App Store reviews, I think removing the
fatalError
when the app fails to back up the store (removing and copying the pre-existing store) would be a good first step. After checking the crash events from release 4.5, it seems like the crashes weren't only migrating from model version 26 to 27 but also from 27 to 28. Now that we know lots of users couldn't get past the backup step, I think it'd be great to know whether the retry of persistent store loading would work.fatalError
when the app couldn't remove or copy the pre-existing persistent store when it failed to migrate for the first time. The errors that occurred in the backup step are then recorded in the log event where the app either recovers from the retry or notCoreDataIterativeMigrator
on the migration step (including a similar backup step)It'd still be great to understand why the migration fails in the first place. We'll continue monitoring the logs in the upcoming crash events to know more about the model versions and migration process, and see if the app could recover from the retry.
Testing
I think just CI is sufficient, since we haven't got to reproduce the crash yet. Feel free to manually add a similar logging event, and run in WooCommerce Alpha target with "Release-Alpha" configuration to verify on Sentry. Here's an example of a similar Sentry event that I added.
Update release notes:
RELEASE-NOTES.txt
if necessary.