Retry failed sends with their send_id until the server confirms them

This commit is contained in:
Ian Gulliver
2026-10-20 15:47:29 -07:00
parent 8fec4b9040
commit d096d604c9
9 changed files with 111 additions and 14 deletions
+32 -13
View File
@@ -521,23 +521,42 @@ struct ComposerView: View {
let sent = drafts.startSend(draftKey, value, imgs.count)
let sendID = UUID().uuidString
let cancel = chat.team ? { true } : chat.builder.showPending(value, imgs, sendID)
let sessionId = m.live?.id
Task {
do {
let ids = try await uploadImages(store.api, imgs)
try await chat.send(sessionId: m.live?.id, text: value, images: ids, model: m.selected != m.current ? m.selected : nil, firstModel: m.selected, sendID: sendID)
modelChoices[m.modelKey] = nil
pick = nil
drafts.endSend(sent, true)
} catch {
guard cancel() else {
log.notice("send failed after the server confirmed it: \(errorText(error), privacy: .public)")
var ids: [String]? = nil
var uploaded = false
while true {
do {
if !uploaded {
ids = try await uploadImages(store.api, imgs)
uploaded = true
}
try await chat.send(sessionId: sessionId, text: value, images: ids, model: m.selected != m.current ? m.selected : nil, firstModel: m.selected, sendID: sendID)
modelChoices[m.modelKey] = nil
pick = nil
drafts.endSend(sent, true)
return
} catch {
let refused = (rootError(error) as? ApiError).map { $0.status < 500 } ?? false
if chat.team || refused {
guard cancel() else {
log.notice("send failed after the server confirmed it: \(errorText(error), privacy: .public)")
drafts.endSend(sent, true)
return
}
drafts.endSend(sent, false)
text = drafts.composerText(draftKey)
images.restore(draftKey, imgs)
overlays.showAlert(errorText(error))
return
}
guard chat.builder.unconfirmed(sendID) else {
drafts.endSend(sent, true)
return
}
log.notice("send failed, retrying: \(errorText(error), privacy: .public)")
try? await Task.sleep(for: .seconds(2))
}
drafts.endSend(sent, false)
text = drafts.composerText(draftKey)
images.restore(draftKey, imgs)
overlays.showAlert(errorText(error))
}
}
}
+4
View File
@@ -275,6 +275,10 @@ final class TranscriptBuilder {
}
}
func unconfirmed(_ sendID: String) -> Bool {
local.items.contains { $0.sendID == sendID }
}
func withdrawn(_ inputId: Int) {
queued.removeAll { $0.inputId == inputId }
}