From 90b4b93e482e86d8e150bd20a347e5d9d7d572e9 Mon Sep 17 00:00:00 2001 From: Tony Li Date: Wed, 22 Mar 2023 22:11:02 +1300 Subject: [PATCH 1/2] Fix Core Data concurrency issues in `AccountService` --- WordPress/Classes/Services/AccountService.h | 2 +- WordPress/Classes/Services/AccountService.m | 27 +++++++++++++++------ WordPress/Classes/Services/BlogService.m | 2 +- 3 files changed, 22 insertions(+), 9 deletions(-) diff --git a/WordPress/Classes/Services/AccountService.h b/WordPress/Classes/Services/AccountService.h index a2f565c92610..ed391eb47118 100644 --- a/WordPress/Classes/Services/AccountService.h +++ b/WordPress/Classes/Services/AccountService.h @@ -94,7 +94,7 @@ extern NSNotificationName const WPAccountEmailAndDefaultBlogUpdatedNotification; Updates the default blog for the specified account. The default blog will be the one whose siteID matches the accounts primaryBlogID. */ -- (void)updateDefaultBlogIfNeeded:(WPAccount *)account; +- (void)updateDefaultBlogIfNeeded:(WPAccount *)account inContext:(NSManagedObjectContext *)context; /** Syncs the details for the account associated with the provided auth token, then diff --git a/WordPress/Classes/Services/AccountService.m b/WordPress/Classes/Services/AccountService.m index d830cafcdceb..2e5660c0b7c3 100644 --- a/WordPress/Classes/Services/AccountService.m +++ b/WordPress/Classes/Services/AccountService.m @@ -351,12 +351,14 @@ - (void)updateAccountWithID:(NSManagedObjectID *)objectID withUserDetails:(Remot // Make sure the account is saved before updating its default blog. [self.coreDataStack performAndSaveUsingBlock:^(NSManagedObjectContext *context) { WPAccount *account = [context existingObjectWithID:objectID error:nil]; - [self updateDefaultBlogIfNeeded:account]; + [self updateDefaultBlogIfNeeded:account inContext:context]; }]; } -- (void)updateDefaultBlogIfNeeded:(WPAccount *)account +- (void)updateDefaultBlogIfNeeded:(WPAccount *)account inContext:(NSManagedObjectContext *)context { + NSParameterAssert(account.managedObjectContext == context); + if (!account.primaryBlogID || [account.primaryBlogID intValue] == 0) { return; } @@ -375,17 +377,27 @@ - (void)updateDefaultBlogIfNeeded:(WPAccount *)account // Update app extensions if needed. if ([account isDefaultWordPressComAccount]) { - [self setupAppExtensionsWithDefaultAccount]; + [self setupAppExtensionsWithDefaultAccount:account inContext:context]; } } - (void)setupAppExtensionsWithDefaultAccount { - WPAccount * __block defaultAccount = nil; - [self.coreDataStack.mainContext performBlockAndWait:^{ - defaultAccount = [WPAccount lookupDefaultWordPressComAccountInContext:self.coreDataStack.mainContext]; + NSManagedObjectContext *context = self.coreDataStack.mainContext; + [context performBlockAndWait:^{ + WPAccount *account = [WPAccount lookupDefaultWordPressComAccountInContext:context]; + if (account == nil) { + return; + } + [self setupAppExtensionsWithDefaultAccount:account inContext:context]; }]; +} + +- (void)setupAppExtensionsWithDefaultAccount:(WPAccount *)defaultAccount inContext:(NSManagedObjectContext *)context +{ + NSParameterAssert(defaultAccount.managedObjectContext == context); + NSManagedObjectID *defaultAccountObjectID = defaultAccount.objectID; Blog *defaultBlog = [defaultAccount defaultBlog]; NSNumber *siteId = defaultBlog.dotComID; NSString *blogName = defaultBlog.settings.name; @@ -412,7 +424,7 @@ - (void)setupAppExtensionsWithDefaultAccount NSString *todayExtensionBlogName = [sharedDefaults objectForKey:AppConfigurationWidgetStatsToday.userDefaultsSiteNameKey]; NSString *todayExtensionBlogUrl = [sharedDefaults objectForKey:AppConfigurationWidgetStatsToday.userDefaultsSiteUrlKey]; - Blog *todayExtensionBlog = [Blog lookupWithID:todayExtensionSiteID in:self.coreDataStack.mainContext]; + Blog *todayExtensionBlog = [Blog lookupWithID:todayExtensionSiteID in:context]; NSTimeZone *timeZone = [todayExtensionBlog timeZone]; if (todayExtensionSiteID == NULL || todayExtensionBlog == nil) { @@ -423,6 +435,7 @@ - (void)setupAppExtensionsWithDefaultAccount } dispatch_async(dispatch_get_main_queue(), ^{ + WPAccount *defaultAccount = [self.coreDataStack.mainContext existingObjectWithID:defaultAccountObjectID error:nil]; TodayExtensionService *service = [TodayExtensionService new]; [service configureTodayWidgetWithSiteID:todayExtensionSiteID diff --git a/WordPress/Classes/Services/BlogService.m b/WordPress/Classes/Services/BlogService.m index 27e32ee30247..7a9d0f2dac77 100644 --- a/WordPress/Classes/Services/BlogService.m +++ b/WordPress/Classes/Services/BlogService.m @@ -447,7 +447,7 @@ - (void)mergeBlogs:(NSArray *)blogs withAccountID:(NSManagedObject // Ensure that the account has a default blog defined (if there is one). AccountService *service = [[AccountService alloc] initWithCoreDataStack:self.coreDataStack]; - [service updateDefaultBlogIfNeeded:account]; + [service updateDefaultBlogIfNeeded:account inContext:context]; } - (void)updateBlogWithRemoteBlog:(RemoteBlog *)remoteBlog account:(WPAccount *)account inContext:(NSManagedObjectContext *)context From aaa4ce6ac4fa24322bd079f56edee426d3007297 Mon Sep 17 00:00:00 2001 From: Tony Li Date: Fri, 24 Mar 2023 14:54:26 +1300 Subject: [PATCH 2/2] Update release notes --- RELEASE-NOTES.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RELEASE-NOTES.txt b/RELEASE-NOTES.txt index 8b92b5272978..75cfce4b8ab1 100644 --- a/RELEASE-NOTES.txt +++ b/RELEASE-NOTES.txt @@ -1,6 +1,6 @@ 22.1 ----- - +* [**] [internal] Refactor updating account related Core Data operations, which ususally happens during log in and out of the app. [#20394] 22.0 -----