Fix diffing profiles.

When profile updates are applied, we diff them to
avoid redundant saves and the resulting work (like
reloading all cells of the conversation).

The diff often failed spuriously because
OWSUserProfileBadgeInfo did not implement
`isEqual:` and instead relied on `NSObject`'s
default implementation using pointer equality.

This commit makes two changes:

1. Implement `-[OWSUserProfileBadgeInfo isEqual:]`
2. Force the ProfileBadge to be loaded prior to
   comparing snapshots so the comparison will be
   correct.

This significantly reduces the number of database
calls when opening a large chat. It may possibly
increase the amount of DB work needed for smaller
groups by loading the profile badge earlier.
This commit is contained in:
George Nachman 2022-01-31 14:47:26 -08:00
parent 3fee1e3913
commit d9947bdd33
2 changed files with 32 additions and 0 deletions

View File

@ -646,6 +646,12 @@ NSString *NSStringForUserProfileWriter(UserProfileWriter userProfileWriter)
[self
anyUpdateWithTransaction:transaction
block:^(OWSUserProfile *profile) {
// Load badges so they can be diffed.
[profile.profileBadgeInfo enumerateObjectsUsingBlock:^(OWSUserProfileBadgeInfo * _Nonnull badgeInfo,
NSUInteger idx,
BOOL * _Nonnull stop) {
(void)[badgeInfo fetchBadgeContentWithTransaction:transaction];
}];
NSArray *avatarKeys = @[ @"avatarFileName", @"avatarUrlPath" ];
// self might be the latest instance, so take a "before" snapshot
@ -665,6 +671,13 @@ NSString *NSStringForUserProfileWriter(UserProfileWriter userProfileWriter)
profile:profile
userProfileWriter:userProfileWriter];
// Load after updates in case anything changed.
[profile.profileBadgeInfo enumerateObjectsUsingBlock:^(OWSUserProfileBadgeInfo * _Nonnull badgeInfo,
NSUInteger idx,
BOOL * _Nonnull stop) {
(void)[badgeInfo fetchBadgeContentWithTransaction:transaction];
}];
profileKeyDidChange = ![NSObject isNullableObject:profileKeyBefore.keyData
equalTo:profile.profileKey.keyData];
BOOL givenNameDidChange = ![NSObject isNullableObject:givenNameBefore

View File

@ -54,6 +54,25 @@ public class OWSUserProfileBadgeInfo: NSObject, SDSSwiftSerializable {
}
return description
}
override public func isEqual(_ object: Any?) -> Bool {
guard let other = object as? OWSUserProfileBadgeInfo else {
return false
}
if badgeId != other.badgeId {
return false
}
if badge != other.badge {
return false
}
if expiration != other.expiration {
return false
}
if isVisible != other.isVisible {
return false
}
return true
}
}
@objc