From cd951ad3961a9f2b21bdacd36552054997834d55 Mon Sep 17 00:00:00 2001 From: Alexander Krotov Date: Sun, 8 Dec 2019 20:01:57 +0300 Subject: [PATCH] Improve IMAP idle timeout error handling Return proper cause and avoid matching on nested Result --- src/imap/idle.rs | 38 +++++++++++++++++++++----------------- 1 file changed, 21 insertions(+), 17 deletions(-) diff --git a/src/imap/idle.rs b/src/imap/idle.rs index f3cea2183..38b546434 100644 --- a/src/imap/idle.rs +++ b/src/imap/idle.rs @@ -19,7 +19,7 @@ pub enum Error { IdleProtocolFailed(#[cause] async_imap::error::Error), #[fail(display = "IMAP IDLE protocol timed out")] - IdleTimeout(String), + IdleTimeout(#[cause] async_std::future::TimeoutError), #[fail(display = "IMAP server does not have IDLE capability")] IdleAbilityMissing, @@ -97,22 +97,24 @@ impl Imap { // if we can't properly terminate the idle // protocol let's break the connection. let res = - async_std::future::timeout(Duration::from_secs(15), handle.done()); - match res.await { - Ok(Ok(session)) => { + async_std::future::timeout(Duration::from_secs(15), handle.done()) + .await + .map_err(|err| { + self.trigger_reconnect(); + Error::IdleTimeout(err) + })?; + + match res { + Ok(session) => { *self.session.lock().await = Some(Session::Secure(session)); } - Ok(Err(err)) => { + Err(err) => { // if we cannot terminate IDLE it probably // means that we waited long (with idle_wait) // but the network went away/changed self.trigger_reconnect(); return Err(Error::IdleProtocolFailed(err)); } - Err(err) => { - self.trigger_reconnect(); - return Err(Error::IdleTimeout(err.to_string())); - } } } IdleHandle::Insecure(mut handle) => { @@ -149,22 +151,24 @@ impl Imap { // if we can't properly terminate the idle // protocol let's break the connection. let res = - async_std::future::timeout(Duration::from_secs(15), handle.done()); - match res.await { - Ok(Ok(session)) => { + async_std::future::timeout(Duration::from_secs(15), handle.done()) + .await + .map_err(|err| { + self.trigger_reconnect(); + Error::IdleTimeout(err) + })?; + + match res { + Ok(session) => { *self.session.lock().await = Some(Session::Insecure(session)); } - Ok(Err(err)) => { + Err(err) => { // if we cannot terminate IDLE it probably // means that we waited long (with idle_wait) // but the network went away/changed self.trigger_reconnect(); return Err(Error::IdleProtocolFailed(err)); } - Err(err) => { - self.trigger_reconnect(); - return Err(Error::IdleTimeout(err.to_string())); - } } } }