Refactor Imap.delete_msg() error handling

Mutable UID reference is removed. Instead, ImapActionResult is
returned immediately.

If message has changed and UID does not correspond to expected
message, ImapActionResult::Failed is returned. Temprorary IMAP errors
result in ImapActionResult::RetryLater.

On the job side, ImapActionResult::RetryLater does not result in
immediate job retry anymore. Instead, job is retried with a backoff.
This commit is contained in:
Alexander Krotov
2020-02-24 00:29:46 +03:00
parent c1c769ceb0
commit 98bd64621a
2 changed files with 16 additions and 11 deletions

View File

@@ -994,10 +994,10 @@ impl Imap {
context: &Context, context: &Context,
message_id: &str, message_id: &str,
folder: &str, folder: &str,
uid: &mut u32, uid: u32,
) -> ImapActionResult { ) -> ImapActionResult {
task::block_on(async move { task::block_on(async move {
if let Some(imapresult) = self.prepare_imap_operation_on_msg(context, folder, *uid) { if let Some(imapresult) = self.prepare_imap_operation_on_msg(context, folder, uid) {
return imapresult; return imapresult;
} }
// we are connected, and the folder is selected // we are connected, and the folder is selected
@@ -1034,7 +1034,7 @@ impl Imap {
remote_message_id, remote_message_id,
message_id, message_id,
); );
*uid = 0; return ImapActionResult::Failed;
} }
} }
Err(err) => { Err(err) => {
@@ -1042,18 +1042,18 @@ impl Imap {
context, context,
"Cannot delete {} on IMAP: {}", display_imap_id, err "Cannot delete {} on IMAP: {}", display_imap_id, err
); );
*uid = 0; return ImapActionResult::RetryLater;
} }
} }
} }
// mark the message for deletion // mark the message for deletion
if !self.add_flag_finalized(context, *uid, "\\Deleted").await { if !self.add_flag_finalized(context, uid, "\\Deleted").await {
warn!( warn!(
context, context,
"Cannot mark message {} as \"Deleted\".", display_imap_id "Cannot mark message {} as \"Deleted\".", display_imap_id
); );
ImapActionResult::Failed ImapActionResult::RetryLater
} else { } else {
emit_event!( emit_event!(
context, context,

View File

@@ -449,7 +449,7 @@ impl Job {
fn DeleteMsgOnImap(&mut self, context: &Context) -> Status { fn DeleteMsgOnImap(&mut self, context: &Context) -> Status {
let imap_inbox = &context.inbox_thread.read().unwrap().imap; let imap_inbox = &context.inbox_thread.read().unwrap().imap;
let mut msg = job_try!(Message::load_from_db(context, MsgId::new(self.foreign_id))); let msg = job_try!(Message::load_from_db(context, MsgId::new(self.foreign_id)));
if !msg.rfc724_mid.is_empty() { if !msg.rfc724_mid.is_empty() {
if message::rfc724_mid_cnt(context, &msg.rfc724_mid) > 1 { if message::rfc724_mid_cnt(context, &msg.rfc724_mid) > 1 {
@@ -462,10 +462,15 @@ impl Job {
we delete the message from the server */ we delete the message from the server */
let mid = msg.rfc724_mid; let mid = msg.rfc724_mid;
let server_folder = msg.server_folder.as_ref().unwrap(); let server_folder = msg.server_folder.as_ref().unwrap();
let res = imap_inbox.delete_msg(context, &mid, server_folder, &mut msg.server_uid); let res = imap_inbox.delete_msg(context, &mid, server_folder, msg.server_uid);
if res == ImapActionResult::RetryLater { match res {
// XXX RetryLater is converted to RetryNow here ImapActionResult::RetryLater => {
return Status::RetryNow; return Status::RetryLater;
}
ImapActionResult::AlreadyDone | ImapActionResult::Success => {}
ImapActionResult::Failed => {
return Status::Finished(Err(format_err!("Message deletion failed")));
}
} }
} }
Message::delete_from_db(context, msg.id); Message::delete_from_db(context, msg.id);