Handle slave device message send failures

pull/176/head
nielsandriesse 5 years ago
parent 739cb1b6ab
commit fbdab8ccb0

@ -41,7 +41,21 @@ public final class MultiDeviceProtocol : NSObject {
return !(message is DeviceLinkMessage) && !message.thread.isGroupThread()
}
private static func sendMessage(_ messageSend: OWSMessageSend, to destination: MultiDeviceDestination, in transaction: YapDatabaseReadTransaction) {
private static func copy(_ messageSend: OWSMessageSend, for destination: MultiDeviceDestination, with seal: Resolver<TSContactThread>) -> OWSMessageSend {
var recipient: SignalRecipient!
storage.dbReadConnection.read { transaction in
recipient = SignalRecipient.getOrBuildUnsavedRecipient(forRecipientId: destination.hexEncodedPublicKey, transaction: transaction)
}
// TODO: Apparently it's okay that the thread, sender certificate, etc. don't get changed?
return OWSMessageSend(message: messageSend.message, thread: messageSend.thread, recipient: recipient,
senderCertificate: messageSend.senderCertificate, udAccess: messageSend.udAccess, localNumber: messageSend.localNumber, success: {
seal.fulfill(messageSend.thread as! TSContactThread)
}, failure: { error in
seal.reject(error)
})
}
private static func sendMessage(_ messageSend: OWSMessageSend, to destination: MultiDeviceDestination, in transaction: YapDatabaseReadTransaction) -> Promise<Void> {
let (promise, seal) = Promise<TSContactThread>.pending()
let message = messageSend.message
let messageSender = SSKEnvironment.shared.messageSender
@ -50,7 +64,7 @@ public final class MultiDeviceProtocol : NSObject {
let shouldSendAutoGeneratedFR = !thread.isContactFriend && !(message is FriendRequestMessage)
&& !(message is SessionRequestMessage) && !isSessionResetMessage && !(message is TypingIndicatorMessage)
if !shouldSendAutoGeneratedFR {
let messageSendCopy = messageSend.copy(with: destination)
let messageSendCopy = copy(messageSend, for: destination, with: seal)
messageSender.sendMessage(messageSendCopy)
} else {
DispatchQueue.main.async {
@ -76,6 +90,7 @@ public final class MultiDeviceProtocol : NSObject {
}
}
}
return promise.map { _ in }
}
@objc(sendMessageToDestinationAndLinkedDevices:in:)
@ -92,16 +107,31 @@ public final class MultiDeviceProtocol : NSObject {
print("[Loki] Sending \(type(of: message)) message using multi device routing.")
let recipientID = messageSend.recipient.recipientId()
getMultiDeviceDestinations(for: recipientID, in: transaction).done(on: OWSDispatch.sendingQueue()) { destinations in
var promises: [Promise<Void>] = []
let masterDestination = destinations.first { $0.isMaster }
if let masterDestination = masterDestination {
storage.dbReadConnection.read { transaction in
sendMessage(messageSend, to: masterDestination, in: transaction)
promises.append(sendMessage(messageSend, to: masterDestination, in: transaction))
}
}
let slaveDestinations = destinations.filter { !$0.isMaster }
slaveDestinations.forEach { slaveDestination in
storage.dbReadConnection.read { transaction in
sendMessage(messageSend, to: slaveDestination, in: transaction)
promises.append(sendMessage(messageSend, to: slaveDestination, in: transaction))
}
}
when(resolved: promises).done(on: OWSDispatch.sendingQueue()) { results in
let errors = results.compactMap { result -> Error? in
if case Result.rejected(let error) = result {
return error
} else {
return nil
}
}
if errors.isEmpty {
messageSend.success()
} else {
messageSend.failure(errors.first!)
}
}
}.catch(on: OWSDispatch.sendingQueue()) { error in

@ -93,14 +93,4 @@ public class OWSMessageSend: NSObject {
// We "fail over" to non-UD sends after auth errors sending via UD.
disableUD()
}
public func copy(with destination: MultiDeviceProtocol.MultiDeviceDestination) -> OWSMessageSend {
var recipient: SignalRecipient!
OWSPrimaryStorage.shared().dbReadConnection.read { transaction in
recipient = SignalRecipient.getOrBuildUnsavedRecipient(forRecipientId: destination.hexEncodedPublicKey, transaction: transaction)
}
let success = destination.isMaster ? self.success : { }
let failure = destination.isMaster ? self.failure : { _ in }
return OWSMessageSend(message: message, thread: thread, recipient: recipient, senderCertificate: senderCertificate, udAccess: udAccess, localNumber: localNumber, success: success, failure: failure)
}
}

Loading…
Cancel
Save