Skip to content

Commit b97317d

Browse files
authored
Fix saving tags performance (#24667)
1 parent 3cf9c72 commit b97317d

File tree

1 file changed

+51
-50
lines changed

1 file changed

+51
-50
lines changed

WordPress/Classes/Services/PostTagService.m

Lines changed: 51 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,8 @@ - (void)syncTagsForBlog:(Blog *)blog
2727
[self handleError:error forBlog:blog withFailure:failure];
2828
return;
2929
}
30-
31-
NSArray *tags = [self mergeTagsWithRemoteTags:remoteTags blog:blog];
30+
31+
NSArray *tags = [self saveRemoteTags:remoteTags toBlog:blog];
3232
[[ContextManager sharedInstance] saveContext:self.managedObjectContext];
3333

3434
if (success) {
@@ -58,10 +58,10 @@ - (void)syncTagsForBlog:(Blog *)blog
5858
[self handleError:error forBlog:blog withFailure:failure];
5959
return;
6060
}
61-
62-
NSArray *tags = [self mergeTagsWithRemoteTags:remoteTags blog:blog];
61+
62+
NSArray *tags = [self saveRemoteTags:remoteTags toBlog:blog];
6363
[[ContextManager sharedInstance] saveContext:self.managedObjectContext];
64-
64+
6565
if (success) {
6666
success(tags);
6767
}
@@ -80,9 +80,9 @@ - (void)getTopTagsForBlog:(Blog *)blog
8080
[remote getTagsWithPaging:paging
8181
success:^(NSArray <RemotePostTag *> *remoteTags) {
8282
[self.managedObjectContext performBlock:^{
83-
NSArray *tags = [remoteTags wp_map:^PostTag *(RemotePostTag *remoteTag) {
84-
return [self tagFromRemoteTag:remoteTag blog:blog];
85-
}];
83+
NSArray<PostTag *> *tags = [self saveRemoteTags:remoteTags toBlog:blog];
84+
[[ContextManager sharedInstance] saveContext:self.managedObjectContext];
85+
8686
if (success) {
8787
success(tags);
8888
}
@@ -107,7 +107,7 @@ - (void)searchTagsWithName:(NSString *)nameQuery
107107
return;
108108
}
109109

110-
NSArray *tags = [self mergeTagsWithRemoteTags:remoteTags blog:blog];
110+
NSArray *tags = [self saveRemoteTags:remoteTags toBlog:blog];
111111
[[ContextManager sharedInstance] saveContext:self.managedObjectContext];
112112

113113
if (success) {
@@ -169,55 +169,56 @@ - (void)saveTag:(PostTag*)tag
169169
return nil;
170170
}
171171

172-
- (nullable NSArray <PostTag *> *)mergeTagsWithRemoteTags:(NSArray<RemotePostTag *> *)remoteTags
173-
blog:(Blog *)blog
172+
- (NSArray<PostTag *> *)saveRemoteTags:(NSArray<RemotePostTag *> *)tags toBlog:(Blog *)blog
174173
{
175-
if (!remoteTags.count) {
176-
return nil;
177-
}
178-
179-
NSMutableArray *tags = [NSMutableArray arrayWithCapacity:remoteTags.count];
180-
for (RemotePostTag *remoteTag in remoteTags) {
181-
[tags addObject:[self tagFromRemoteTag:remoteTag blog:blog]];
174+
if (tags.count == 0) {
175+
return [NSArray array];
182176
}
183-
184-
return [NSArray arrayWithArray:tags];
185-
}
186177

187-
- (PostTag *)tagFromRemoteTag:(RemotePostTag *)remoteTag
188-
blog:(Blog *)blog
189-
{
190-
PostTag *tag = [self existingTagForRemoteTag:remoteTag blog:blog];
191-
if (!tag) {
192-
NSEntityDescription *entityDescription = [NSEntityDescription entityForName:[PostTag entityName]
193-
inManagedObjectContext:self.managedObjectContext];
194-
tag = [[PostTag alloc] initWithEntity:entityDescription insertIntoManagedObjectContext:self.managedObjectContext];
195-
tag.tagID = remoteTag.tagID;
196-
tag.tagDescription = remoteTag.tagDescription;
197-
tag.blog = blog;
178+
NSManagedObjectContext *context = blog.managedObjectContext;
179+
if (context == nil) {
180+
return [NSArray array];
198181
}
199-
200-
tag.name = remoteTag.name;
201-
tag.slug = remoteTag.slug;
202-
tag.tagDescription = remoteTag.tagDescription;
203-
tag.postCount = remoteTag.postCount;
204-
205-
return tag;
206-
}
207182

208-
- (nullable PostTag *)existingTagForRemoteTag:(RemotePostTag *)remoteTag
209-
blog:(Blog *)blog
210-
{
183+
NSArray<NSNumber *> *remoteTagIDs = [tags wp_map:^NSNumber *(RemotePostTag *remoteTag) {
184+
return remoteTag.tagID;
185+
}];
186+
211187
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:[PostTag entityName]];
212-
request.predicate = [NSPredicate predicateWithFormat:@"blog = %@ AND tagID = %@", blog, remoteTag.tagID];
188+
request.predicate = [NSPredicate predicateWithFormat:@"blog = %@ AND tagID IN %@", blog, remoteTagIDs];
189+
213190
NSError *error;
214-
NSArray *tags = [self.managedObjectContext executeFetchRequest:request error:&error];
191+
NSArray<PostTag *> *existingTags = [context executeFetchRequest:request error:&error];
215192
if (error) {
216-
DDLogError(@"Error when retrieving PostTag by tagID: %@", error);
217-
return nil;
193+
DDLogError(@"Error when retrieving PostTags by tagIDs: %@", error);
194+
return [NSArray array];
218195
}
219-
220-
return [tags firstObject];
196+
197+
NSMutableDictionary<NSNumber *, PostTag *> *existingTagsLookup = [NSMutableDictionary dictionaryWithCapacity:existingTags.count];
198+
for (PostTag *tag in existingTags) {
199+
existingTagsLookup[tag.tagID] = tag;
200+
}
201+
202+
NSMutableArray<PostTag *> *savedTags = [NSMutableArray array];
203+
for (RemotePostTag *remote in tags) {
204+
PostTag *tag = existingTagsLookup[remote.tagID];
205+
if (tag == nil) {
206+
NSEntityDescription *entityDescription = [NSEntityDescription entityForName:[PostTag entityName]
207+
inManagedObjectContext:context];
208+
tag = [[PostTag alloc] initWithEntity:entityDescription insertIntoManagedObjectContext:context];
209+
}
210+
211+
tag.tagID = remote.tagID;
212+
tag.name = remote.name;
213+
tag.slug = remote.slug;
214+
tag.tagDescription = remote.tagDescription;
215+
tag.postCount = remote.postCount;
216+
tag.blog = blog;
217+
218+
[savedTags addObject:tag];
219+
}
220+
221+
return savedTags;
221222
}
222223

223224
- (void)saveNewTag:(PostTag *)tag
@@ -229,7 +230,7 @@ - (void)saveNewTag:(PostTag *)tag
229230
NSObject<TaxonomyServiceRemote> *remote = [self remoteForBlog:blog];
230231
[remote createTag:remoteTag success:^(RemotePostTag * _Nonnull tag) {
231232
if (success) {
232-
PostTag *localTag = [self tagFromRemoteTag:tag blog:blog];
233+
PostTag *localTag = [[self saveRemoteTags:@[tag] toBlog:blog] firstObject];
233234
[[ContextManager sharedInstance] saveContextAndWait:self.managedObjectContext];
234235
success(localTag);
235236
}

0 commit comments

Comments
 (0)