From bd40aacd538ba7bcb4e851d4a87f7e8ad14861f7 Mon Sep 17 00:00:00 2001 From: Matthew Chen Date: Thu, 13 Dec 2018 15:57:56 -0500 Subject: [PATCH] Purge dynamic interactions from database. --- Signal.xcodeproj/project.pbxproj | 4 ++ .../OWS114RemoveDynamicInteractions.swift | 65 +++++++++++++++++++ .../migrations/OWSDatabaseMigrationRunner.m | 1 + SignalMessaging/utils/ThreadUtil.m | 33 ++-------- 4 files changed, 74 insertions(+), 29 deletions(-) create mode 100644 SignalMessaging/environment/migrations/OWS114RemoveDynamicInteractions.swift diff --git a/Signal.xcodeproj/project.pbxproj b/Signal.xcodeproj/project.pbxproj index 9246570e0..0d5a7ce78 100644 --- a/Signal.xcodeproj/project.pbxproj +++ b/Signal.xcodeproj/project.pbxproj @@ -241,6 +241,7 @@ 34BEDB1621C80BCA007B0EAE /* OWSAnyTouchGestureRecognizer.h in Headers */ = {isa = PBXBuildFile; fileRef = 34BEDB1421C80BC9007B0EAE /* OWSAnyTouchGestureRecognizer.h */; settings = {ATTRIBUTES = (Public, ); }; }; 34BEDB1721C80BCA007B0EAE /* OWSAnyTouchGestureRecognizer.m in Sources */ = {isa = PBXBuildFile; fileRef = 34BEDB1521C80BCA007B0EAE /* OWSAnyTouchGestureRecognizer.m */; }; 34BEDB1921C82AC5007B0EAE /* ImageEditorGestureRecognizer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34BEDB1821C82AC5007B0EAE /* ImageEditorGestureRecognizer.swift */; }; + 34BEDB0B21C2FA3D007B0EAE /* OWS114RemoveDynamicInteractions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34BEDB0A21C2FA3D007B0EAE /* OWS114RemoveDynamicInteractions.swift */; }; 34C3C78D20409F320000134C /* Opening.m4r in Resources */ = {isa = PBXBuildFile; fileRef = 34C3C78C20409F320000134C /* Opening.m4r */; }; 34C3C78F2040A4F70000134C /* sonarping.mp3 in Resources */ = {isa = PBXBuildFile; fileRef = 34C3C78E2040A4F70000134C /* sonarping.mp3 */; }; 34C3C7922040B0DD0000134C /* OWSAudioPlayer.h in Headers */ = {isa = PBXBuildFile; fileRef = 34C3C7902040B0DC0000134C /* OWSAudioPlayer.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -917,6 +918,7 @@ 34BEDB1421C80BC9007B0EAE /* OWSAnyTouchGestureRecognizer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWSAnyTouchGestureRecognizer.h; sourceTree = ""; }; 34BEDB1521C80BCA007B0EAE /* OWSAnyTouchGestureRecognizer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OWSAnyTouchGestureRecognizer.m; sourceTree = ""; }; 34BEDB1821C82AC5007B0EAE /* ImageEditorGestureRecognizer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ImageEditorGestureRecognizer.swift; sourceTree = ""; }; + 34BEDB0A21C2FA3D007B0EAE /* OWS114RemoveDynamicInteractions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OWS114RemoveDynamicInteractions.swift; sourceTree = ""; }; 34C3C78C20409F320000134C /* Opening.m4r */ = {isa = PBXFileReference; lastKnownFileType = file; path = Opening.m4r; sourceTree = ""; }; 34C3C78E2040A4F70000134C /* sonarping.mp3 */ = {isa = PBXFileReference; lastKnownFileType = audio.mp3; name = sonarping.mp3; path = Signal/AudioFiles/sonarping.mp3; sourceTree = SOURCE_ROOT; }; 34C3C7902040B0DC0000134C /* OWSAudioPlayer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWSAudioPlayer.h; sourceTree = ""; }; @@ -1677,6 +1679,7 @@ 349EA07B2162AEA700F7B17F /* OWS111UDAttributesMigration.swift */, 34B6A908218B8824007C4606 /* OWS112TypingIndicatorsMigration.swift */, 4C7537882193779700DF5E37 /* OWS113MultiAttachmentMediaMessages.swift */, + 34BEDB0A21C2FA3D007B0EAE /* OWS114RemoveDynamicInteractions.swift */, 346129931FD1E30000532771 /* OWSDatabaseMigration.h */, 346129941FD1E30000532771 /* OWSDatabaseMigration.m */, 346129E51FD5C0C600532771 /* OWSDatabaseMigrationRunner.h */, @@ -3373,6 +3376,7 @@ 346129E31FD5C0BE00532771 /* VersionMigrations.m in Sources */, 4C7537892193779700DF5E37 /* OWS113MultiAttachmentMediaMessages.swift in Sources */, 34AC0A16211B39EA00997B47 /* OWSNavigationBar.swift in Sources */, + 34BEDB0B21C2FA3D007B0EAE /* OWS114RemoveDynamicInteractions.swift in Sources */, 34AC0A1A211B39EA00997B47 /* CommonStrings.swift in Sources */, 34AC0A19211B39EA00997B47 /* OWSAlerts.swift in Sources */, 451F8A351FD710DE005CB9DA /* Searcher.swift in Sources */, diff --git a/SignalMessaging/environment/migrations/OWS114RemoveDynamicInteractions.swift b/SignalMessaging/environment/migrations/OWS114RemoveDynamicInteractions.swift new file mode 100644 index 000000000..857215bd8 --- /dev/null +++ b/SignalMessaging/environment/migrations/OWS114RemoveDynamicInteractions.swift @@ -0,0 +1,65 @@ +// +// Copyright (c) 2018 Open Whisper Systems. All rights reserved. +// + +import Foundation +import SignalServiceKit + +@objc +public class OWS114RemoveDynamicInteractions: OWSDatabaseMigration { + + // MARK: - Dependencies + + // MARK: - + + // Increment a similar constant for each migration. + @objc + class func migrationId() -> String { + return "114" + } + + override public func runUp(completion: @escaping OWSDatabaseMigrationCompletion) { + Logger.debug("") + BenchAsync(title: "\(self.logTag)") { (benchCompletion) in + self.doMigrationAsync(completion: { + benchCompletion() + completion() + }) + } + } + + private func doMigrationAsync(completion : @escaping OWSDatabaseMigrationCompletion) { + DispatchQueue.global().async { + self.dbReadWriteConnection().readWrite { transaction in + guard let dbView = TSDatabaseView.threadSpecialMessagesDatabaseView(transaction) as? YapDatabaseViewTransaction else { + owsFailDebug("Couldn't load db view.") + return + } + + var interactionsToDelete = [TSInteraction]() + let groupIds = dbView.allGroups() + for groupId in groupIds { + dbView.enumerateKeysAndObjects(inGroup: groupId) { (_: String, _: String, object: Any, _: UInt, _: UnsafeMutablePointer) in + guard let interaction = object as? TSInteraction else { + owsFailDebug("Invalid database entity: \(type(of: object)).") + return + } + guard interaction.isDynamicInteraction() else { + return + } + interactionsToDelete.append(interaction) + } + } + + for interaction in interactionsToDelete { + Logger.debug("Cleaning up interaction: \(type(of: interaction)).") + interaction.remove(with: transaction) + } + + self.save(with: transaction) + } + + completion() + } + } +} diff --git a/SignalMessaging/environment/migrations/OWSDatabaseMigrationRunner.m b/SignalMessaging/environment/migrations/OWSDatabaseMigrationRunner.m index 2b1f6c7e6..479532818 100644 --- a/SignalMessaging/environment/migrations/OWSDatabaseMigrationRunner.m +++ b/SignalMessaging/environment/migrations/OWSDatabaseMigrationRunner.m @@ -35,6 +35,7 @@ NS_ASSUME_NONNULL_BEGIN [[OWS111UDAttributesMigration alloc] init], [[OWS112TypingIndicatorsMigration alloc] init], [[OWS113MultiAttachmentMediaMessages alloc] init], + [[OWS114RemoveDynamicInteractions alloc] init], ]; } diff --git a/SignalMessaging/utils/ThreadUtil.m b/SignalMessaging/utils/ThreadUtil.m index 2e6694f3d..622c4a46d 100644 --- a/SignalMessaging/utils/ThreadUtil.m +++ b/SignalMessaging/utils/ThreadUtil.m @@ -343,37 +343,17 @@ NS_ASSUME_NONNULL_BEGIN ThreadDynamicInteractions *result = [ThreadDynamicInteractions new]; - [dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) { + [dbConnection readWithBlock:^(YapDatabaseReadTransaction *transaction) { // Find any "dynamic" interactions and safety number changes. // // We use different views for performance reasons. NSMutableArray *blockingSafetyNumberChanges = [NSMutableArray new]; NSMutableArray *nonBlockingSafetyNumberChanges = [NSMutableArray new]; - // We want to delete legacy and duplicate interactions. - NSMutableArray *interactionsToDelete = [NSMutableArray new]; [[TSDatabaseView threadSpecialMessagesDatabaseView:transaction] enumerateKeysAndObjectsInGroup:thread.uniqueId usingBlock:^( NSString *collection, NSString *key, id object, NSUInteger index, BOOL *stop) { - if ([object isKindOfClass:[OWSUnknownContactBlockOfferMessage class]]) { - // Delete this legacy interactions, which has been superseded by - // the OWSContactOffersInteraction. - [interactionsToDelete addObject:object]; - } else if ([object isKindOfClass:[OWSAddToContactsOfferMessage class]]) { - // Delete this legacy interactions, which has been superseded by - // the OWSContactOffersInteraction. - [interactionsToDelete addObject:object]; - } else if ([object isKindOfClass:[OWSAddToProfileWhitelistOfferMessage class]]) { - // Delete this legacy interactions, which has been superseded by - // the OWSContactOffersInteraction. - [interactionsToDelete addObject:object]; - } else if ([object isKindOfClass:[TSUnreadIndicatorInteraction class]]) { - // Remove obsolete unread indicator interactions. - [interactionsToDelete addObject:object]; - } else if ([object isKindOfClass:[OWSContactOffersInteraction class]]) { - // Remove obsolete contact offers. - [interactionsToDelete addObject:object]; - } else if ([object isKindOfClass:[TSInvalidIdentityKeyErrorMessage class]]) { + if ([object isKindOfClass:[TSInvalidIdentityKeyErrorMessage class]]) { [blockingSafetyNumberChanges addObject:object]; } else if ([object isKindOfClass:[TSErrorMessage class]]) { TSErrorMessage *errorMessage = (TSErrorMessage *)object; @@ -385,11 +365,6 @@ NS_ASSUME_NONNULL_BEGIN } }]; - for (TSInteraction *interaction in interactionsToDelete) { - OWSLogDebug(@"Cleaning up interaction: %@", [interaction class]); - [interaction removeWithTransaction:transaction]; - } - // Determine if there are "unread" messages in this conversation. // If we've been passed a firstUnseenInteractionTimestampParameter, // just use that value in order to preserve continuity of the @@ -430,7 +405,7 @@ NS_ASSUME_NONNULL_BEGIN + (void)ensureUnreadIndicator:(ThreadDynamicInteractions *)dynamicInteractions thread:(TSThread *)thread - transaction:(YapDatabaseReadWriteTransaction *)transaction + transaction:(YapDatabaseReadTransaction *)transaction maxRangeSize:(int)maxRangeSize blockingSafetyNumberChanges:(NSArray *)blockingSafetyNumberChanges nonBlockingSafetyNumberChanges:(NSArray *)nonBlockingSafetyNumberChanges @@ -556,7 +531,7 @@ NS_ASSUME_NONNULL_BEGIN } + (nullable NSNumber *)focusMessagePositionForThread:(TSThread *)thread - transaction:(YapDatabaseReadWriteTransaction *)transaction + transaction:(YapDatabaseReadTransaction *)transaction focusMessageId:(NSString *)focusMessageId { OWSAssertDebug(thread);