fix sync: INSERT OR IGNORE for duplicate messages, fix leaked IMAP continuations
- insertMessages uses INSERT OR IGNORE on (mailboxId, uid) conflict instead of crashing on UNIQUE constraint when messages are re-fetched after restart - IMAPResponseHandler.sendCommand resumes any leaked previous continuation before registering a new one, preventing DuplicateCommandTag errors - add channelInactive handler to resume pending continuations on connection drop - add error type to sync failure log for better diagnostics Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -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 = []
|
||||
|
||||
Reference in New Issue
Block a user