Skip to content

Commit bedfef5

Browse files
Merge branch 'charlesmchen/decryptDeduplicationByProcessing' into release/5.20.4
2 parents dbed8b5 + 73b019f commit bedfef5

File tree

6 files changed

+120
-122
lines changed

6 files changed

+120
-122
lines changed

NotificationServiceExtension/NSEEnvironment.swift

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -157,8 +157,6 @@ class NSEEnvironment: Dependencies {
157157
}
158158

159159
public static func verifyDBKeysAvailable() -> UNNotificationContent? {
160-
AssertIsOnMainThread()
161-
162160
guard !StorageCoordinator.hasGrdbFile || !GRDBDatabaseStorageAdapter.isKeyAccessible else { return nil }
163161

164162
Logger.info("Database password is not accessible, posting generic notification.")

SignalServiceKit/Resources/schema.sql

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1237,17 +1237,10 @@ CREATE
12371237
TABLE
12381238
IF NOT EXISTS "MessageDecryptDeduplication" (
12391239
"id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL
1240-
,"serviceTimestamp" INTEGER NOT NULL
12411240
,"serverGuid" TEXT NOT NULL
12421241
)
12431242
;
12441243

1245-
CREATE
1246-
INDEX "MessageDecryptDeduplication_serviceTimestamp"
1247-
ON "MessageDecryptDeduplication"("serviceTimestamp"
1248-
)
1249-
;
1250-
12511244
CREATE
12521245
INDEX "MessageDecryptDeduplication_serverGuid"
12531246
ON "MessageDecryptDeduplication"("serverGuid"

SignalServiceKit/src/Messages/MessageProcessor.swift

Lines changed: 27 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -473,11 +473,9 @@ class MessageDecryptDeduplicationRecord: Codable, FetchableRecord, PersistableRe
473473
static let databaseTableName = "MessageDecryptDeduplication"
474474

475475
var id: Int64?
476-
let serviceTimestamp: UInt64
477476
let serverGuid: String
478477

479-
init(serviceTimestamp: UInt64, serverGuid: String) {
480-
self.serviceTimestamp = serviceTimestamp
478+
init(serverGuid: String) {
481479
self.serverGuid = serverGuid
482480
}
483481

@@ -496,20 +494,26 @@ class MessageDecryptDeduplicationRecord: Codable, FetchableRecord, PersistableRe
496494
transaction: SDSAnyWriteTransaction,
497495
skipCull: Bool = false
498496
) -> Outcome {
499-
deduplicate(serviceTimestamp: encryptedEnvelope.serverTimestamp,
497+
deduplicate(envelopeTimestamp: encryptedEnvelope.timestamp,
498+
serviceTimestamp: encryptedEnvelope.serverTimestamp,
500499
serverGuid: encryptedEnvelope.serverGuid,
501500
transaction: transaction,
502501
skipCull: skipCull)
503502
}
504503

505504
public static func deduplicate(
505+
envelopeTimestamp: UInt64,
506506
serviceTimestamp: UInt64,
507507
serverGuid: String?,
508508
transaction: SDSAnyWriteTransaction,
509509
skipCull: Bool = false
510510
) -> Outcome {
511+
guard envelopeTimestamp > 0 else {
512+
owsFailDebug("Invalid envelopeTimestamp.")
513+
return .nonDuplicate
514+
}
511515
guard serviceTimestamp > 0 else {
512-
owsFailDebug("Missing serviceTimestamp.")
516+
owsFailDebug("Invalid serviceTimestamp.")
513517
return .nonDuplicate
514518
}
515519
guard let serverGuid = serverGuid?.nilIfEmpty else {
@@ -527,21 +531,20 @@ class MessageDecryptDeduplicationRecord: Codable, FetchableRecord, PersistableRe
527531
return try Bool.fetchOne(transaction.unwrapGrdbWrite.database, sql: sql, arguments: arguments) ?? false
528532
}()
529533
guard !isDuplicate else {
530-
Logger.warn("Discarding duplicate envelope with serviceTimestamp: \(serviceTimestamp), serverGuid: \(serverGuid)")
534+
Logger.warn("Discarding duplicate envelope with envelopeTimestamp: \(envelopeTimestamp), serviceTimestamp: \(serviceTimestamp), serverGuid: \(serverGuid)")
531535
return .duplicate
532536
}
533537

534538
// No existing record found. Create a new one and insert it.
535-
let record = MessageDecryptDeduplicationRecord(serviceTimestamp: serviceTimestamp,
536-
serverGuid: serverGuid)
539+
let record = MessageDecryptDeduplicationRecord(serverGuid: serverGuid)
537540
try record.insert(transaction.unwrapGrdbWrite.database)
538541

539542
if !skipCull, shouldCull() {
540-
cull(latestServiceTimestamp: serviceTimestamp, transaction: transaction)
543+
cull(transaction: transaction)
541544
}
542545

543546
if DebugFlags.internalLogging {
544-
Logger.info("Proceeding with serviceTimestamp: \(serviceTimestamp), serverGuid: \(serverGuid)")
547+
Logger.info("Proceeding with envelopeTimestamp: \(envelopeTimestamp), serviceTimestamp: \(serviceTimestamp), serverGuid: \(serverGuid)")
545548
}
546549
return .nonDuplicate
547550
} catch {
@@ -553,34 +556,23 @@ class MessageDecryptDeduplicationRecord: Codable, FetchableRecord, PersistableRe
553556
}
554557

555558
static let maxRecordCount: UInt = 1000
556-
static let maxRecordAgeMs: UInt64 = 5 * kMinuteInMs
557-
558-
private static func cull(latestServiceTimestamp: UInt64,
559-
transaction: SDSAnyWriteTransaction) {
560-
let count1 = recordCount(transaction: transaction)
561-
562-
// Client and service time might not match; use service timestamps for
563-
// all record bookkeeping.
564-
let recordExpirationTimestamp = latestServiceTimestamp - maxRecordAgeMs
565-
let sql = """
566-
DELETE FROM MessageDecryptDeduplication
567-
WHERE serviceTimestamp < ?;
568-
"""
569-
transaction.unwrapGrdbWrite.executeUpdate(sql: sql, arguments: [recordExpirationTimestamp])
570-
571-
let count2 = recordCount(transaction: transaction)
572-
if count1 != count2 {
573-
Logger.info("Culled by timestamp: \(count1) -> \(count2)")
574-
}
575559

576-
guard count2 > maxRecordCount else {
560+
static let cullCount = AtomicUInt(0)
561+
562+
private static func cull(transaction: SDSAnyWriteTransaction) {
563+
564+
cullCount.increment()
565+
566+
let oldCount = recordCount(transaction: transaction)
567+
568+
guard oldCount > maxRecordCount else {
577569
return
578570
}
579571

580572
do {
581573
// It is sufficient to cull by record count in batches.
582574
// The batch size must be larger than our cull frequency to bound total record count.
583-
let cullCount: Int = min(Int(cullFrequency) * 2, Int(count2) - Int(maxRecordCount))
575+
let cullCount: Int = min(Int(cullFrequency) * 2, Int(oldCount) - Int(maxRecordCount))
584576

585577
Logger.info("Culling \(cullCount) records.")
586578

@@ -592,11 +584,11 @@ class MessageDecryptDeduplicationRecord: Codable, FetchableRecord, PersistableRe
592584
try record.delete(transaction.unwrapGrdbWrite.database)
593585
}
594586

595-
let count3 = recordCount(transaction: transaction)
596-
if count2 != count3 {
597-
Logger.info("Culled by count: \(count2) -> \(count3)")
587+
let newCount = recordCount(transaction: transaction)
588+
if oldCount != newCount {
589+
Logger.info("Culled by count: \(oldCount) -> \(newCount)")
598590
}
599-
owsAssertDebug(count3 <= maxRecordCount)
591+
owsAssertDebug(newCount <= maxRecordCount)
600592
} catch {
601593
owsFailDebug("Error: \(error)")
602594
}

SignalServiceKit/src/Storage/Database/GRDBSchemaMigrator.swift

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ public class GRDBSchemaMigrator: NSObject {
113113
case updateMessageSendLogColumnTypes
114114
case addRecordTypeIndex
115115
case tunedConversationLoadIndices
116-
case messageDecryptDeduplication3
116+
case messageDecryptDeduplicationV5
117117

118118
// NOTE: Every time we add a migration id, consider
119119
// incrementing grdbSchemaVersionLatest.
@@ -1446,7 +1446,7 @@ public class GRDBSchemaMigrator: NSObject {
14461446
}
14471447
}
14481448

1449-
migrator.registerMigration(MigrationId.messageDecryptDeduplication3.rawValue) { db in
1449+
migrator.registerMigration(MigrationId.messageDecryptDeduplicationV5.rawValue) { db in
14501450
do {
14511451
if try db.tableExists("MessageDecryptDeduplication") {
14521452
try db.drop(table: "MessageDecryptDeduplication")
@@ -1455,18 +1455,10 @@ public class GRDBSchemaMigrator: NSObject {
14551455
try db.create(table: "MessageDecryptDeduplication") { table in
14561456
table.autoIncrementedPrimaryKey("id")
14571457
.notNull()
1458-
table.column("serviceTimestamp", .integer)
1459-
.notNull()
14601458
table.column("serverGuid", .text)
14611459
.notNull()
14621460
}
14631461

1464-
try db.create(
1465-
index: "MessageDecryptDeduplication_serviceTimestamp",
1466-
on: "MessageDecryptDeduplication",
1467-
columns: ["serviceTimestamp"]
1468-
)
1469-
14701462
try db.create(
14711463
index: "MessageDecryptDeduplication_serverGuid",
14721464
on: "MessageDecryptDeduplication",

SignalServiceKit/src/Util/Atomics.swift

Lines changed: 46 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,50 @@ public class AtomicUInt: NSObject {
110110

111111
// MARK: -
112112

113+
@objc
114+
public class AtomicUInt64: NSObject {
115+
private let value: AtomicValue<UInt64>
116+
117+
@objc @available(swift, obsoleted: 1.0)
118+
public required convenience init(_ value: UInt64) {
119+
self.init(value, lock: nil)
120+
}
121+
122+
public required init(_ value: UInt64 = 0, lock: AtomicLock? = nil) {
123+
self.value = AtomicValue(value, lock: lock)
124+
}
125+
126+
@objc
127+
public func get() -> UInt64 {
128+
value.get()
129+
}
130+
131+
@objc
132+
public func set(_ value: UInt64) {
133+
self.value.set(value)
134+
}
135+
136+
@discardableResult
137+
@objc
138+
public func increment() -> UInt64 {
139+
value.map { $0 + 1 }
140+
}
141+
142+
@discardableResult
143+
@objc
144+
public func decrementOrZero() -> UInt64 {
145+
value.map { max($0, 1) - 1 }
146+
}
147+
148+
@discardableResult
149+
@objc
150+
public func add(_ delta: UInt64) -> UInt64 {
151+
value.map { $0 + delta }
152+
}
153+
}
154+
155+
// MARK: -
156+
113157
public final class AtomicValue<T> {
114158
private let lock: AtomicLock
115159
private var value: T
@@ -307,7 +351,7 @@ public class AtomicArray<T> {
307351
public func pushTail(_ value: T) {
308352
append(value)
309353
}
310-
354+
311355
public var count: Int {
312356
lock.perform { values.count }
313357
}
@@ -374,7 +418,7 @@ public class AtomicDictionary<Key: Hashable, Value> {
374418
return result
375419
}
376420
}
377-
421+
378422
public var count: Int {
379423
lock.perform { values.count }
380424
}

0 commit comments

Comments
 (0)