Fixed a few more bugs

• Fixed an issue where the message status wouldn't update to the failed state if the MessageSendJob timed-out
• Fixed an issue where network issues could result in a backlog of TypingIndicator messages that failed to send (don't bother retrying them)
• Fixed an issue where concurrent jobs might not retry correctly if other jobs don't complete or the retry was triggered from the wrong queue
• Fixed an issue where the input view could disappear in some cases
pull/960/head
Morgan Pretty 2 months ago
parent 352f6d7337
commit 8d99f64f56

@ -472,6 +472,11 @@ final class ConversationVC: BaseVC, LibSessionRespondingViewController, Conversa
)?.becomeFirstResponder()
}
}
else if !self.isFirstResponder && hasLoadedInitialThreadData {
// After we have loaded the initial data if the user starts and cancels the interactive pop
// gesture the input view will disappear
self.becomeFirstResponder()
}
recoverInputView { [weak self] in
// Flag that the initial layout has been completed (the flag blocks and unblocks a number

@ -265,8 +265,7 @@ public class UserNotificationActionHandler: NSObject {
case .finished: break
case .failure(let error):
completionHandler()
owsFailDebug("error: \(error)")
Logger.error("error: \(error)")
OWSLogger.error("Failed to handle notification response: \(error)")
}
},
receiveValue: { _ in completionHandler() }
@ -282,14 +281,14 @@ public class UserNotificationActionHandler: NSObject {
switch response.actionIdentifier {
case UNNotificationDefaultActionIdentifier:
Logger.debug("default action")
OWSLogger.debug("Notification response: default action")
return actionHandler.showThread(userInfo: userInfo)
.setFailureType(to: Error.self)
.eraseToAnyPublisher()
case UNNotificationDismissActionIdentifier:
// TODO - mark as read?
Logger.debug("dismissed notification")
OWSLogger.debug("Notification response: dismissed notification")
return Just(())
.setFailureType(to: Error.self)
.eraseToAnyPublisher()

@ -195,22 +195,41 @@ public enum MessageSendJob: JobExecutor {
case MessageSenderError.sendJobTimeout:
SNLog("[MessageSendJob] Couldn't send message due to error: \(error) (paths: \(OnionRequestAPI.paths.prettifiedDescription)).")
// In this case the `MessageSender` process gets cancelled so we need to
// call `handleFailedMessageSend` to update the statuses correctly
dependencies.storage.write(using: dependencies) { db in
MessageSender.handleFailedMessageSend(
db,
message: details.message,
destination: details.destination,
with: .other(error),
interactionId: job.interactionId,
using: dependencies
)
}
default:
SNLog("[MessageSendJob] Couldn't send message due to error: \(error)")
}
// Actual error handling
switch error {
case let senderError as MessageSenderError where !senderError.isRetryable:
switch (error, details.message) {
case (let senderError as MessageSenderError, _) where !senderError.isRetryable:
failure(job, error, true, dependencies)
case SnodeAPIError.rateLimited:
case (SnodeAPIError.rateLimited, _):
failure(job, error, true, dependencies)
case SnodeAPIError.clockOutOfSync:
case (SnodeAPIError.clockOutOfSync, _):
SNLog("[MessageSendJob] \(originalSentTimestamp != nil ? "Permanently Failing" : "Failing") to send \(type(of: details.message)) due to clock out of sync issue.")
failure(job, error, (originalSentTimestamp != nil), dependencies)
// Don't bother retrying (it can just send a new one later but allowing retries
// can result in a large number of `MessageSendJobs` backing up)
case (_, is TypingIndicator):
SNLog("[MessageSendJob] Failed to send \(type(of: details.message)).")
failure(job, error, true, dependencies)
default:
SNLog("[MessageSendJob] Failed to send \(type(of: details.message)).")

@ -1057,9 +1057,15 @@ public final class MessageSender {
interactionId: Int64?,
using dependencies: Dependencies
) -> Error {
// If the message was a reaction then we don't want to do anything to the original
// interaciton (which the 'interactionId' is pointing to
guard (message as? VisibleMessage)?.reaction == nil else { return error }
// Only 'VisibleMessage' messages can show a status so don't bother updating
// the other cases (if the VisibleMessage was a reaction then we also don't
// want to do anything as the `interactionId` points to the original message
// which has it's own status)
switch message {
case let message as VisibleMessage where message.reaction != nil: return error
case is VisibleMessage: break
default: return error
}
// Check if we need to mark any "sending" recipients as "failed"
//

@ -961,7 +961,7 @@ public final class JobQueue: Hashable {
repeats: false,
using: dependencies,
block: { [weak queue] _ in
queue?.start(using: dependencies)
queue?.start(forceWhenAlreadyRunning: (queue?.executionType == .concurrent), using: dependencies)
}
)
return trigger
@ -1306,7 +1306,7 @@ public final class JobQueue: Hashable {
// on the main thread (if it is on the main thread then swap to a different thread)
guard DispatchQueue.with(key: queueKey, matches: queueContext, using: dependencies) else {
internalQueue.async(using: dependencies) { [weak self] in
self?.start(using: dependencies)
self?.start(forceWhenAlreadyRunning: forceWhenAlreadyRunning, using: dependencies)
}
return
}
@ -1582,8 +1582,8 @@ public final class JobQueue: Hashable {
return
}
// Only schedule a trigger if this queue has actually completed
guard executionType != .concurrent || currentlyRunningJobIds.wrappedValue.isEmpty else { return }
// Only schedule a trigger if the queue is concurrent, or it has actually completed
guard executionType == .concurrent || currentlyRunningJobIds.wrappedValue.isEmpty else { return }
// Setup a trigger
SNLog("[JobRunner] Stopping \(queueContext) until next job in \(ceilSecondsUntilNextJob) second\(ceilSecondsUntilNextJob == 1 ? "" : "s")")

Loading…
Cancel
Save