diff --git a/Apps/MagnumOpus/ViewModels/MailViewModel.swift b/Apps/MagnumOpus/ViewModels/MailViewModel.swift index 7941d2c..a89b734 100644 --- a/Apps/MagnumOpus/ViewModels/MailViewModel.swift +++ b/Apps/MagnumOpus/ViewModels/MailViewModel.swift @@ -207,8 +207,10 @@ final class MailViewModel { try await coordinator.syncNow() syncState = coordinator.syncState } catch { - errorMessage = error.localizedDescription - syncState = .error(error.localizedDescription) + let desc = "\(type(of: error)): \(error.localizedDescription)" + print("[MailViewModel] syncNow failed: \(desc)") + errorMessage = desc + syncState = .error(desc) } } diff --git a/Packages/MagnumOpusCore/Sources/IMAPClient/IMAPResponseHandler.swift b/Packages/MagnumOpusCore/Sources/IMAPClient/IMAPResponseHandler.swift index 1602d39..33429c7 100644 --- a/Packages/MagnumOpusCore/Sources/IMAPClient/IMAPResponseHandler.swift +++ b/Packages/MagnumOpusCore/Sources/IMAPClient/IMAPResponseHandler.swift @@ -53,6 +53,15 @@ final class IMAPResponseHandler: ChannelInboundHandler, RemovableChannelHandler, } } + func channelInactive(context: ChannelHandlerContext) { + let error = IMAPError.notConnected + continuation?.resume(throwing: error) + continuation = nil + greetingContinuation?.resume(throwing: error) + greetingContinuation = nil + context.fireChannelInactive() + } + func errorCaught(context: ChannelHandlerContext, error: Error) { continuation?.resume(throwing: error) continuation = nil @@ -68,6 +77,11 @@ final class IMAPResponseHandler: ChannelInboundHandler, RemovableChannelHandler, } func sendCommand(tag: String, continuation cont: CheckedContinuation<[Response], Error>) { + // Resume any leaked continuation from a previous command to avoid + // "SWIFT TASK CONTINUATION MISUSE: leaked its continuation" + if let old = continuation { + old.resume(throwing: IMAPError.serverError("Previous command interrupted")) + } expectedTag = tag continuation = cont buffer = [] diff --git a/Packages/MagnumOpusCore/Sources/MailStore/MailStore.swift b/Packages/MagnumOpusCore/Sources/MailStore/MailStore.swift index d78744e..4affd2a 100644 --- a/Packages/MagnumOpusCore/Sources/MailStore/MailStore.swift +++ b/Packages/MagnumOpusCore/Sources/MailStore/MailStore.swift @@ -58,7 +58,8 @@ public final class MailStore: Sendable { public func insertMessages(_ messages: [MessageRecord]) throws { try dbWriter.write { db in for message in messages { - try message.save(db) + // INSERT OR IGNORE: skip if (mailboxId, uid) already exists from a prior sync + try message.insert(db, onConflict: .ignore) } } }