From 45e572e82fffd3b7b95bb402cb82f0a912250f2f Mon Sep 17 00:00:00 2001 From: Michael Kirk Date: Wed, 3 Oct 2018 15:56:36 -0600 Subject: [PATCH] assert monotonic order for migration --- .../migrations/OWS110SortIdMigration.swift | 25 ++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/SignalMessaging/environment/migrations/OWS110SortIdMigration.swift b/SignalMessaging/environment/migrations/OWS110SortIdMigration.swift index ef35b5665..af4c2cddb 100644 --- a/SignalMessaging/environment/migrations/OWS110SortIdMigration.swift +++ b/SignalMessaging/environment/migrations/OWS110SortIdMigration.swift @@ -46,8 +46,27 @@ class OWS110SortIdMigration: OWSDatabaseMigration { let totalCount: UInt = legacySorting.numberOfItemsInAllGroups() var completedCount: UInt = 0 + + var seenGroups: Set = Set() legacySorting.enumerateGroups { group, _ in autoreleasepool { + // Sanity Check #1 + // Make sure our enumeration is monotonically increasing. + // Note: sortIds increase monotonically WRT timestampForLegacySorting, but only WRT the interaction's thread. + // + // e.g. When we migrate the **next** thread, we start with that thread's oldest interaction. So it's possible and expected + // that thread2's oldest interaction will have a smaller timestampForLegacySorting, but a greater sortId then an interaction + // in thread1. That's OK because we only sort messages with respect to the thread they belong in. We don't have any sort of + // "global sort" of messages across all threads. + var previousTimestampForLegacySorting: UInt64 = 0 + + // Sanity Check #2 + // Ensure we only process a DB View's group (i.e. threadId) once. + guard !seenGroups.contains(group) else { + owsFail("unexpectedly seeing a repeated group: \(group)") + } + seenGroups.insert(group) + legacySorting.enumerateKeysAndObjects(inGroup: group) { (_, _, object, _, _) in autoreleasepool { guard let interaction = object as? TSInteraction else { @@ -55,10 +74,14 @@ class OWS110SortIdMigration: OWSDatabaseMigration { return } + guard interaction.timestampForLegacySorting() >= previousTimestampForLegacySorting else { + owsFail("unexpected object ordering previousTimestampForLegacySorting: \(previousTimestampForLegacySorting) interaction.timestampForLegacySorting: \(interaction.timestampForLegacySorting)") + } + previousTimestampForLegacySorting = interaction.timestampForLegacySorting() + interaction.saveNextSortId(transaction: transaction) completedCount += 1 - if completedCount % 100 == 0 { // Legit usage of legacy sorting for migration to new sorting Logger.info("thread: \(interaction.uniqueThreadId), timestampForLegacySorting:\(interaction.timestampForLegacySorting()), sortId: \(interaction.sortId) totalCount: \(totalCount), completedcount: \(completedCount)")