From a2de00feb8d6603bfc30cbb90a4af87e22f92e78 Mon Sep 17 00:00:00 2001 From: nielsandriesse Date: Thu, 30 Apr 2020 09:06:05 +1000 Subject: [PATCH] Avoid nested write transaction --- .../Multi Device/MultiDeviceProtocol.swift | 1 + .../SessionManagementProtocol.swift | 31 ++++++++++++------- 2 files changed, 21 insertions(+), 11 deletions(-) diff --git a/SignalServiceKit/src/Loki/Protocol/Multi Device/MultiDeviceProtocol.swift b/SignalServiceKit/src/Loki/Protocol/Multi Device/MultiDeviceProtocol.swift index f2defa9d5..133835a54 100644 --- a/SignalServiceKit/src/Loki/Protocol/Multi Device/MultiDeviceProtocol.swift +++ b/SignalServiceKit/src/Loki/Protocol/Multi Device/MultiDeviceProtocol.swift @@ -176,6 +176,7 @@ public final class MultiDeviceProtocol : NSObject { let udManager = SSKEnvironment.shared.udManager let senderCertificate = udManager.getSenderCertificate() let (promise, seal) = Promise.pending() + // Dispatch async on the main queue to avoid nested write transactions DispatchQueue.main.async { var recipientUDAccess: OWSUDAccess? if let senderCertificate = senderCertificate { diff --git a/SignalServiceKit/src/Loki/Protocol/Session Management/SessionManagementProtocol.swift b/SignalServiceKit/src/Loki/Protocol/Session Management/SessionManagementProtocol.swift index 64231d678..4a722181d 100644 --- a/SignalServiceKit/src/Loki/Protocol/Session Management/SessionManagementProtocol.swift +++ b/SignalServiceKit/src/Loki/Protocol/Session Management/SessionManagementProtocol.swift @@ -91,8 +91,7 @@ public final class SessionManagementProtocol : NSObject { let devices = thread.sessionRestoreDevices // TODO: Rename this for device in devices { guard device.count != 0 else { continue } - let sessionResetMessageSend = getSessionResetMessageSend(for: device, in: transaction) - OWSDispatch.sendingQueue().async { + getSessionResetMessageSend(for: device, in: transaction).done(on: OWSDispatch.sendingQueue()) { sessionResetMessageSend in messageSender.sendMessage(sessionResetMessageSend) } } @@ -112,7 +111,11 @@ public final class SessionManagementProtocol : NSObject { } @objc(getSessionResetMessageSendForHexEncodedPublicKey:in:) - public static func getSessionResetMessageSend(for hexEncodedPublicKey: String, in transaction: YapDatabaseReadWriteTransaction) -> OWSMessageSend { + public static func objc_getSessionResetMessageSend(for hexEncodedPublicKey: String, in transaction: YapDatabaseReadWriteTransaction) -> AnyPromise { + return AnyPromise.from(getSessionResetMessageSend(for: hexEncodedPublicKey, in: transaction)) + } + + public static func getSessionResetMessageSend(for hexEncodedPublicKey: String, in transaction: YapDatabaseReadWriteTransaction) -> Promise { let thread = TSContactThread.getOrCreateThread(withContactId: hexEncodedPublicKey, transaction: transaction) let masterHexEncodedPublicKey = storage.getMasterHexEncodedPublicKey(for: hexEncodedPublicKey, in: transaction) let isSlaveDeviceThread = masterHexEncodedPublicKey != hexEncodedPublicKey @@ -122,16 +125,22 @@ public final class SessionManagementProtocol : NSObject { let recipient = SignalRecipient.getOrBuildUnsavedRecipient(forRecipientId: hexEncodedPublicKey, transaction: transaction) let udManager = SSKEnvironment.shared.udManager let senderCertificate = udManager.getSenderCertificate() - var recipientUDAccess: OWSUDAccess? - if let senderCertificate = senderCertificate { - recipientUDAccess = udManager.udAccess(forRecipientId: hexEncodedPublicKey, requireSyncAccess: true) - } - return OWSMessageSend(message: message, thread: thread, recipient: recipient, senderCertificate: senderCertificate, - udAccess: recipientUDAccess, localNumber: getUserHexEncodedPublicKey(), success: { + let (promise, seal) = Promise.pending() + // Dispatch async on the main queue to avoid nested write transactions + DispatchQueue.main.async { + var recipientUDAccess: OWSUDAccess? + if let senderCertificate = senderCertificate { + recipientUDAccess = udManager.udAccess(forRecipientId: hexEncodedPublicKey, requireSyncAccess: true) // Starts a new write transaction internally + } + let messageSend = OWSMessageSend(message: message, thread: thread, recipient: recipient, senderCertificate: senderCertificate, + udAccess: recipientUDAccess, localNumber: getUserHexEncodedPublicKey(), success: { - }, failure: { error in + }, failure: { error in - }) + }) + seal.fulfill(messageSend) + } + return promise } // MARK: - Receiving