diff --git a/Signal/test/PerformanceTests/ThreadFinderPerformanceTest.swift b/Signal/test/PerformanceTests/ThreadFinderPerformanceTest.swift index a24ce37e87..9de3365906 100644 --- a/Signal/test/PerformanceTests/ThreadFinderPerformanceTest.swift +++ b/Signal/test/PerformanceTests/ThreadFinderPerformanceTest.swift @@ -75,7 +75,7 @@ class ThreadFinderPerformanceTest: PerformanceBaseTest { // Note that we enumerate _twice_ (archived & non-archived) let readCount = 10 - write { transaction in + read { transaction in self.startMeasuring() for _ in 0.. self.lastInteractionSortId; - if (needsToMarkAsVisible || needsToClearArchived || needsToUpdateLastInteractionSortId) { + BOOL needsToUpdateLastInteractionRowId = messageSortId > self.lastInteractionRowId; + if (needsToMarkAsVisible || needsToClearArchived || needsToUpdateLastInteractionRowId) { [self anyUpdateWithTransaction:transaction block:^(TSThread *thread) { thread.shouldThreadBeVisible = YES; - thread.lastInteractionSortId = MAX(thread.lastInteractionSortId, messageSortId); + thread.lastInteractionRowId = MAX(thread.lastInteractionRowId, messageSortId); if (thread.isArchived && wasMessageInserted) { // No longer archived. thread.isArchived = NO; @@ -474,6 +484,40 @@ isArchivedByLegacyTimestampForSorting:(BOOL)isArchivedByLegacyTimestampForSortin } } +- (void)updateWithRemovedMessage:(TSInteraction *)message transaction:(SDSAnyWriteTransaction *)transaction +{ + OWSAssertDebug(message != nil); + OWSAssertDebug(transaction != nil); + + if (![self.class shouldInteractionAppearInInbox:message]) { + return; + } + + int64_t messageSortId = 0; + if (transaction.transitional_yapWriteTransaction) { + messageSortId = message.sortId; + } else { + if (message.grdbId == nil) { + OWSFailDebug(@"Missing messageSortId."); + } else if (message.grdbId.unsignedLongLongValue == 0) { + OWSFailDebug(@"Invalid messageSortId."); + } else { + messageSortId = message.grdbId.longLongValue; + } + } + BOOL needsToUpdateLastInteractionRowId = messageSortId == self.lastInteractionRowId; + if (needsToUpdateLastInteractionRowId) { + [self anyUpdateWithTransaction:transaction + block:^(TSThread *thread) { + TSInteraction *_Nullable latestInteraction = + [thread lastInteractionForInboxWithTransaction:transaction]; + thread.lastInteractionRowId = latestInteraction ? latestInteraction.sortId : 0; + }]; + } else { + [self.databaseStorage touchThread:self transaction:transaction]; + } +} + - (void)softDeleteThreadWithTransaction:(SDSAnyWriteTransaction *)transaction { [self removeAllThreadInteractionsWithTransaction:transaction]; diff --git a/SignalServiceKit/src/Contacts/Threads/TSContactThread+SDS.swift b/SignalServiceKit/src/Contacts/Threads/TSContactThread+SDS.swift index d253878e02..9e6b0f1497 100644 --- a/SignalServiceKit/src/Contacts/Threads/TSContactThread+SDS.swift +++ b/SignalServiceKit/src/Contacts/Threads/TSContactThread+SDS.swift @@ -66,7 +66,7 @@ class TSContactThreadSerializer: SDSSerializer { let creationDate: Double? = archiveOptionalDate(model.creationDate) let isArchived: Bool = model.isArchived let isArchivedByLegacyTimestampForSorting: Bool = model.isArchivedByLegacyTimestampForSorting - let lastInteractionSortId: Int64 = model.lastInteractionSortId + let lastInteractionRowId: Int64 = model.lastInteractionRowId let lastMessageDate: Double? = archiveOptionalDate(model.lastMessageDate) let messageDraft: String? = model.messageDraft let mutedUntilDate: Double? = archiveOptionalDate(model.mutedUntilDate) @@ -79,6 +79,6 @@ class TSContactThreadSerializer: SDSSerializer { let groupModel: Data? = nil let hasDismissedOffers: Bool? = model.hasDismissedOffers - return ThreadRecord(delegate: model, id: id, recordType: recordType, uniqueId: uniqueId, archivalDate: archivalDate, conversationColorName: conversationColorName, creationDate: creationDate, isArchived: isArchived, isArchivedByLegacyTimestampForSorting: isArchivedByLegacyTimestampForSorting, lastInteractionSortId: lastInteractionSortId, lastMessageDate: lastMessageDate, messageDraft: messageDraft, mutedUntilDate: mutedUntilDate, shouldThreadBeVisible: shouldThreadBeVisible, contactPhoneNumber: contactPhoneNumber, contactThreadSchemaVersion: contactThreadSchemaVersion, contactUUID: contactUUID, groupModel: groupModel, hasDismissedOffers: hasDismissedOffers) + return ThreadRecord(delegate: model, id: id, recordType: recordType, uniqueId: uniqueId, archivalDate: archivalDate, conversationColorName: conversationColorName, creationDate: creationDate, isArchived: isArchived, isArchivedByLegacyTimestampForSorting: isArchivedByLegacyTimestampForSorting, lastInteractionRowId: lastInteractionRowId, lastMessageDate: lastMessageDate, messageDraft: messageDraft, mutedUntilDate: mutedUntilDate, shouldThreadBeVisible: shouldThreadBeVisible, contactPhoneNumber: contactPhoneNumber, contactThreadSchemaVersion: contactThreadSchemaVersion, contactUUID: contactUUID, groupModel: groupModel, hasDismissedOffers: hasDismissedOffers) } } diff --git a/SignalServiceKit/src/Contacts/Threads/TSContactThread.h b/SignalServiceKit/src/Contacts/Threads/TSContactThread.h index 2b1fbef72e..704aa5f4c8 100644 --- a/SignalServiceKit/src/Contacts/Threads/TSContactThread.h +++ b/SignalServiceKit/src/Contacts/Threads/TSContactThread.h @@ -23,7 +23,7 @@ NS_ASSUME_NONNULL_BEGIN creationDate:(nullable NSDate *)creationDate isArchived:(BOOL)isArchived isArchivedByLegacyTimestampForSorting:(BOOL)isArchivedByLegacyTimestampForSorting - lastInteractionSortId:(int64_t)lastInteractionSortId + lastInteractionRowId:(int64_t)lastInteractionRowId lastMessageDate:(nullable NSDate *)lastMessageDate messageDraft:(nullable NSString *)messageDraft mutedUntilDate:(nullable NSDate *)mutedUntilDate @@ -33,7 +33,7 @@ isArchivedByLegacyTimestampForSorting:(BOOL)isArchivedByLegacyTimestampForSortin contactThreadSchemaVersion:(NSUInteger)contactThreadSchemaVersion contactUUID:(nullable NSString *)contactUUID hasDismissedOffers:(BOOL)hasDismissedOffers -NS_SWIFT_NAME(init(grdbId:uniqueId:archivalDate:conversationColorName:creationDate:isArchived:isArchivedByLegacyTimestampForSorting:lastInteractionSortId:lastMessageDate:messageDraft:mutedUntilDate:rowId:shouldThreadBeVisible:contactPhoneNumber:contactThreadSchemaVersion:contactUUID:hasDismissedOffers:)); +NS_SWIFT_NAME(init(grdbId:uniqueId:archivalDate:conversationColorName:creationDate:isArchived:isArchivedByLegacyTimestampForSorting:lastInteractionRowId:lastMessageDate:messageDraft:mutedUntilDate:rowId:shouldThreadBeVisible:contactPhoneNumber:contactThreadSchemaVersion:contactUUID:hasDismissedOffers:)); // clang-format on diff --git a/SignalServiceKit/src/Contacts/Threads/TSContactThread.m b/SignalServiceKit/src/Contacts/Threads/TSContactThread.m index b79f023827..4b57f55368 100644 --- a/SignalServiceKit/src/Contacts/Threads/TSContactThread.m +++ b/SignalServiceKit/src/Contacts/Threads/TSContactThread.m @@ -56,7 +56,7 @@ NSUInteger const TSContactThreadSchemaVersion = 1; creationDate:(nullable NSDate *)creationDate isArchived:(BOOL)isArchived isArchivedByLegacyTimestampForSorting:(BOOL)isArchivedByLegacyTimestampForSorting - lastInteractionSortId:(int64_t)lastInteractionSortId + lastInteractionRowId:(int64_t)lastInteractionRowId lastMessageDate:(nullable NSDate *)lastMessageDate messageDraft:(nullable NSString *)messageDraft mutedUntilDate:(nullable NSDate *)mutedUntilDate @@ -74,7 +74,7 @@ isArchivedByLegacyTimestampForSorting:(BOOL)isArchivedByLegacyTimestampForSortin creationDate:creationDate isArchived:isArchived isArchivedByLegacyTimestampForSorting:isArchivedByLegacyTimestampForSorting - lastInteractionSortId:lastInteractionSortId + lastInteractionRowId:lastInteractionRowId lastMessageDate:lastMessageDate messageDraft:messageDraft mutedUntilDate:mutedUntilDate diff --git a/SignalServiceKit/src/Contacts/Threads/TSGroupThread+SDS.swift b/SignalServiceKit/src/Contacts/Threads/TSGroupThread+SDS.swift index 68cb6b4f57..617f03e70b 100644 --- a/SignalServiceKit/src/Contacts/Threads/TSGroupThread+SDS.swift +++ b/SignalServiceKit/src/Contacts/Threads/TSGroupThread+SDS.swift @@ -66,7 +66,7 @@ class TSGroupThreadSerializer: SDSSerializer { let creationDate: Double? = archiveOptionalDate(model.creationDate) let isArchived: Bool = model.isArchived let isArchivedByLegacyTimestampForSorting: Bool = model.isArchivedByLegacyTimestampForSorting - let lastInteractionSortId: Int64 = model.lastInteractionSortId + let lastInteractionRowId: Int64 = model.lastInteractionRowId let lastMessageDate: Double? = archiveOptionalDate(model.lastMessageDate) let messageDraft: String? = model.messageDraft let mutedUntilDate: Double? = archiveOptionalDate(model.mutedUntilDate) @@ -79,6 +79,6 @@ class TSGroupThreadSerializer: SDSSerializer { let groupModel: Data? = optionalArchive(model.groupModel) let hasDismissedOffers: Bool? = nil - return ThreadRecord(delegate: model, id: id, recordType: recordType, uniqueId: uniqueId, archivalDate: archivalDate, conversationColorName: conversationColorName, creationDate: creationDate, isArchived: isArchived, isArchivedByLegacyTimestampForSorting: isArchivedByLegacyTimestampForSorting, lastInteractionSortId: lastInteractionSortId, lastMessageDate: lastMessageDate, messageDraft: messageDraft, mutedUntilDate: mutedUntilDate, shouldThreadBeVisible: shouldThreadBeVisible, contactPhoneNumber: contactPhoneNumber, contactThreadSchemaVersion: contactThreadSchemaVersion, contactUUID: contactUUID, groupModel: groupModel, hasDismissedOffers: hasDismissedOffers) + return ThreadRecord(delegate: model, id: id, recordType: recordType, uniqueId: uniqueId, archivalDate: archivalDate, conversationColorName: conversationColorName, creationDate: creationDate, isArchived: isArchived, isArchivedByLegacyTimestampForSorting: isArchivedByLegacyTimestampForSorting, lastInteractionRowId: lastInteractionRowId, lastMessageDate: lastMessageDate, messageDraft: messageDraft, mutedUntilDate: mutedUntilDate, shouldThreadBeVisible: shouldThreadBeVisible, contactPhoneNumber: contactPhoneNumber, contactThreadSchemaVersion: contactThreadSchemaVersion, contactUUID: contactUUID, groupModel: groupModel, hasDismissedOffers: hasDismissedOffers) } } diff --git a/SignalServiceKit/src/Contacts/Threads/TSGroupThread.h b/SignalServiceKit/src/Contacts/Threads/TSGroupThread.h index 49641da704..c84f11d43b 100644 --- a/SignalServiceKit/src/Contacts/Threads/TSGroupThread.h +++ b/SignalServiceKit/src/Contacts/Threads/TSGroupThread.h @@ -29,14 +29,14 @@ extern NSString *const TSGroupThread_NotificationKey_UniqueId; creationDate:(nullable NSDate *)creationDate isArchived:(BOOL)isArchived isArchivedByLegacyTimestampForSorting:(BOOL)isArchivedByLegacyTimestampForSorting - lastInteractionSortId:(int64_t)lastInteractionSortId + lastInteractionRowId:(int64_t)lastInteractionRowId lastMessageDate:(nullable NSDate *)lastMessageDate messageDraft:(nullable NSString *)messageDraft mutedUntilDate:(nullable NSDate *)mutedUntilDate rowId:(int64_t)rowId shouldThreadBeVisible:(BOOL)shouldThreadBeVisible groupModel:(TSGroupModel *)groupModel -NS_SWIFT_NAME(init(grdbId:uniqueId:archivalDate:conversationColorName:creationDate:isArchived:isArchivedByLegacyTimestampForSorting:lastInteractionSortId:lastMessageDate:messageDraft:mutedUntilDate:rowId:shouldThreadBeVisible:groupModel:)); +NS_SWIFT_NAME(init(grdbId:uniqueId:archivalDate:conversationColorName:creationDate:isArchived:isArchivedByLegacyTimestampForSorting:lastInteractionRowId:lastMessageDate:messageDraft:mutedUntilDate:rowId:shouldThreadBeVisible:groupModel:)); // clang-format on diff --git a/SignalServiceKit/src/Contacts/Threads/TSGroupThread.m b/SignalServiceKit/src/Contacts/Threads/TSGroupThread.m index 089a8699c4..eb307ea68c 100644 --- a/SignalServiceKit/src/Contacts/Threads/TSGroupThread.m +++ b/SignalServiceKit/src/Contacts/Threads/TSGroupThread.m @@ -30,7 +30,7 @@ NSString *const TSGroupThread_NotificationKey_UniqueId = @"TSGroupThread_Notific creationDate:(nullable NSDate *)creationDate isArchived:(BOOL)isArchived isArchivedByLegacyTimestampForSorting:(BOOL)isArchivedByLegacyTimestampForSorting - lastInteractionSortId:(int64_t)lastInteractionSortId + lastInteractionRowId:(int64_t)lastInteractionRowId lastMessageDate:(nullable NSDate *)lastMessageDate messageDraft:(nullable NSString *)messageDraft mutedUntilDate:(nullable NSDate *)mutedUntilDate @@ -45,7 +45,7 @@ isArchivedByLegacyTimestampForSorting:(BOOL)isArchivedByLegacyTimestampForSortin creationDate:creationDate isArchived:isArchived isArchivedByLegacyTimestampForSorting:isArchivedByLegacyTimestampForSorting - lastInteractionSortId:lastInteractionSortId + lastInteractionRowId:lastInteractionRowId lastMessageDate:lastMessageDate messageDraft:messageDraft mutedUntilDate:mutedUntilDate diff --git a/SignalServiceKit/src/Messages/Interactions/TSInteraction.m b/SignalServiceKit/src/Messages/Interactions/TSInteraction.m index b77576c478..ed2eed93d2 100644 --- a/SignalServiceKit/src/Messages/Interactions/TSInteraction.m +++ b/SignalServiceKit/src/Messages/Interactions/TSInteraction.m @@ -294,30 +294,24 @@ NSString *NSStringFromOWSInteractionType(OWSInteractionType value) { [super anyDidInsertWithTransaction:transaction]; - [self updateLastMessageWithTransaction:transaction wasMessageInserted:YES]; + TSThread *fetchedThread = [self threadWithTransaction:transaction]; + [fetchedThread updateWithInsertedMessage:self transaction:transaction]; } - (void)anyDidUpdateWithTransaction:(SDSAnyWriteTransaction *)transaction { [super anyDidUpdateWithTransaction:transaction]; - [self updateLastMessageWithTransaction:transaction wasMessageInserted:NO]; -} - -- (void)updateLastMessageWithTransaction:(SDSAnyWriteTransaction *)transaction - wasMessageInserted:(BOOL)wasMessageInserted -{ TSThread *fetchedThread = [self threadWithTransaction:transaction]; - - [fetchedThread updateWithLastMessage:self wasMessageInserted:wasMessageInserted transaction:transaction]; + [fetchedThread updateWithUpdatedMessage:self transaction:transaction]; } - (void)anyDidRemoveWithTransaction:(SDSAnyWriteTransaction *)transaction { [super anyDidRemoveWithTransaction:transaction]; - TSThread *thread = [self threadWithTransaction:transaction]; - [self.databaseStorage touchThread:thread transaction:transaction]; + TSThread *fetchedThread = [self threadWithTransaction:transaction]; + [fetchedThread updateWithRemovedMessage:self transaction:transaction]; } #pragma mark - diff --git a/SignalServiceKit/src/Storage/Database/GRDBDatabaseStorageAdapter.swift b/SignalServiceKit/src/Storage/Database/GRDBDatabaseStorageAdapter.swift index 568e065488..c4e4de8c14 100644 --- a/SignalServiceKit/src/Storage/Database/GRDBDatabaseStorageAdapter.swift +++ b/SignalServiceKit/src/Storage/Database/GRDBDatabaseStorageAdapter.swift @@ -214,7 +214,7 @@ public class GRDBDatabaseStorageAdapter: NSObject { columns: [ ThreadRecord.columnName(.shouldThreadBeVisible), ThreadRecord.columnName(.isArchived), - ThreadRecord.columnName(.lastInteractionSortId) + ThreadRecord.columnName(.lastInteractionRowId) ] ) diff --git a/SignalServiceKit/src/Storage/Database/Records/ThreadFinder.swift b/SignalServiceKit/src/Storage/Database/Records/ThreadFinder.swift index aa59fbbf9f..5494d900e9 100644 --- a/SignalServiceKit/src/Storage/Database/Records/ThreadFinder.swift +++ b/SignalServiceKit/src/Storage/Database/Records/ThreadFinder.swift @@ -105,7 +105,7 @@ struct GRDBThreadFinder: ThreadFinder { FROM \(ThreadRecord.databaseTableName) WHERE \(threadColumn: .shouldThreadBeVisible) = 1 AND \(threadColumn: .isArchived) = ? - ORDER BY \(threadColumn: .lastInteractionSortId) DESC + ORDER BY \(threadColumn: .lastInteractionRowId) DESC """ let arguments: StatementArguments = [isArchived]