store: remove callbacks on error

Unmark deleted messages and remove pending headers in the callback
function when an error in the backend occurs (e.g. due to connection
issues).

The message store marks messages that should be deleted. If the delete
operation in the backend fails, messages are never unmarked and will
remain rendered as empty lines in the message list. This also affects
the move and archive commands that rely on a copy and delete operation.

A similar issue occurs with the pending headers when the operation to
fetch them fails. In this case, messages will appear as loading
indefinitely in the message list and are never re-fetched because the
corresponding pending headers from the failed operations are still
present.

Fixes: https://todo.sr.ht/~rjarry/aerc/28
Signed-off-by: Koni Marti <koni.marti@gmail.com>
Acked-by: Robin Jarry <robin@jarry.cc>
This commit is contained in:
Koni Marti 2022-05-05 03:28:41 +02:00 committed by Robin Jarry
parent ad51cb3611
commit 5c5158b3c1

View file

@ -111,7 +111,15 @@ func (store *MessageStore) FetchHeaders(uids []uint32,
} }
} }
if len(toFetch) > 0 { if len(toFetch) > 0 {
store.worker.PostAction(&types.FetchMessageHeaders{Uids: toFetch}, nil) store.worker.PostAction(&types.FetchMessageHeaders{Uids: toFetch}, func(msg types.WorkerMessage) {
switch msg.(type) {
case *types.Error:
for _, uid := range toFetch {
delete(store.pendingHeaders, uid)
delete(store.headerCallbacks, uid)
}
}
})
} }
} }
@ -139,6 +147,7 @@ func (store *MessageStore) FetchFull(uids []uint32, cb func(*types.FullMessage))
switch msg.(type) { switch msg.(type) {
case *types.Error: case *types.Error:
for _, uid := range toFetch { for _, uid := range toFetch {
delete(store.pendingBodies, uid)
delete(store.bodyCallbacks, uid) delete(store.bodyCallbacks, uid)
} }
} }
@ -389,10 +398,25 @@ func (store *MessageStore) Delete(uids []uint32,
store.Deleted[uid] = nil store.Deleted[uid] = nil
} }
store.worker.PostAction(&types.DeleteMessages{Uids: uids}, cb) store.worker.PostAction(&types.DeleteMessages{Uids: uids},
func(msg types.WorkerMessage) {
switch msg.(type) {
case *types.Error:
store.revertDeleted(uids)
}
cb(msg)
})
store.update() store.update()
} }
func (store *MessageStore) revertDeleted(uids []uint32) {
for _, uid := range uids {
if _, ok := store.Deleted[uid]; ok {
delete(store.Deleted, uid)
}
}
}
func (store *MessageStore) Copy(uids []uint32, dest string, createDest bool, func (store *MessageStore) Copy(uids []uint32, dest string, createDest bool,
cb func(msg types.WorkerMessage)) { cb func(msg types.WorkerMessage)) {
@ -429,9 +453,10 @@ func (store *MessageStore) Move(uids []uint32, dest string, createDest bool,
}, func(msg types.WorkerMessage) { }, func(msg types.WorkerMessage) {
switch msg.(type) { switch msg.(type) {
case *types.Error: case *types.Error:
store.revertDeleted(uids)
cb(msg) cb(msg)
case *types.Done: case *types.Done:
store.worker.PostAction(&types.DeleteMessages{Uids: uids}, cb) store.Delete(uids, cb)
} }
}) })