summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorManos Pitsidianakis <el13635@mail.ntua.gr>2020-09-14 19:32:43 +0300
committerManos Pitsidianakis <el13635@mail.ntua.gr>2020-09-14 19:32:43 +0300
commit17a4ccdcbc37977cf7c4c17b8180a922936ee2f5 (patch)
tree2d0549fb266783b652665937475e0f7faaf15756
parent670675edcc48480a8e250d9b2b06b69c837df51c (diff)
melib/imap: perform reconnect on IDLE failure
-rw-r--r--melib/src/backends/imap.rs11
-rw-r--r--melib/src/backends/imap/connection.rs12
-rw-r--r--melib/src/backends/imap/watch.rs6
-rw-r--r--melib/src/error.rs4
-rw-r--r--src/conf/accounts.rs34
5 files changed, 45 insertions, 22 deletions
diff --git a/melib/src/backends/imap.rs b/melib/src/backends/imap.rs
index f346d164..b69569aa 100644
--- a/melib/src/backends/imap.rs
+++ b/melib/src/backends/imap.rs
@@ -479,6 +479,17 @@ impl MailBackend for ImapType {
main_conn.uid_store.is_online.lock().unwrap().1 = Err(err.clone());
}
debug!("failure: {}", err.to_string());
+ match timeout(timeout_dur, main_conn.connect())
+ .await
+ .and_then(|res| res)
+ {
+ Err(err2) => {
+ debug!("reconnect attempt failed: {}", err2.to_string());
+ }
+ Ok(()) => {
+ debug!("reconnect attempt succesful");
+ }
+ }
let account_hash = main_conn.uid_store.account_hash;
main_conn.add_refresh_event(RefreshEvent {
account_hash,
diff --git a/melib/src/backends/imap/connection.rs b/melib/src/backends/imap/connection.rs
index 5c17a916..2f6a9ba4 100644
--- a/melib/src/backends/imap/connection.rs
+++ b/melib/src/backends/imap/connection.rs
@@ -984,7 +984,7 @@ pub struct ImapBlockingConnection {
result: Vec<u8>,
prev_res_length: usize,
pub conn: ImapConnection,
- err: Option<String>,
+ err: Option<MeliError>,
}
impl From<ImapConnection> for ImapBlockingConnection {
@@ -1004,8 +1004,8 @@ impl ImapBlockingConnection {
self.conn
}
- pub fn err(&self) -> Option<&str> {
- self.err.as_deref()
+ pub fn err(&mut self) -> Option<MeliError> {
+ self.err.take()
}
pub fn as_stream<'a>(&'a mut self) -> impl Future<Output = Option<Vec<u8>>> + 'a {
@@ -1056,10 +1056,10 @@ async fn read(
}
*prev_failure = None;
}
- Err(e) => {
+ Err(_err) => {
debug!(&conn.stream);
- debug!(&e);
- *err = Some(e.to_string());
+ debug!(&_err);
+ *err = Some(Into::<MeliError>::into(_err).set_kind(crate::error::ErrorKind::Network));
*break_flag = true;
*prev_failure = Some(Instant::now());
}
diff --git a/melib/src/backends/imap/watch.rs b/melib/src/backends/imap/watch.rs
index aaba948f..07cf061c 100644
--- a/melib/src/backends/imap/watch.rs
+++ b/melib/src/backends/imap/watch.rs
@@ -185,8 +185,10 @@ pub async fn idle(kit: ImapWatchKit) -> Result<()> {
}
}
debug!("IDLE connection dropped");
- let err: &str = blockn.err().unwrap_or("Unknown reason.");
- Err(MeliError::new(format!("IDLE connection dropped: {}", err)))
+ Err(blockn
+ .err()
+ .unwrap_or(MeliError::new("Unknown reason.").set_kind(crate::error::ErrorKind::Network))
+ .set_summary("IDLE connection dropped".to_string()))
}
pub async fn examine_updates(
diff --git a/melib/src/error.rs b/melib/src/error.rs
index 945f9252..045ee3fd 100644
--- a/melib/src/error.rs
+++ b/melib/src/error.rs
@@ -205,7 +205,9 @@ impl Error for MeliError {
impl From<io::Error> for MeliError {
#[inline]
fn from(kind: io::Error) -> MeliError {
- MeliError::new(kind.to_string()).set_source(Some(Arc::new(kind)))
+ MeliError::new(kind.to_string())
+ .set_summary(format!("{:?}", kind.kind()))
+ .set_source(Some(Arc::new(kind)))
}
}
diff --git a/src/conf/accounts.rs b/src/conf/accounts.rs
index 469b3c59..040f53dc 100644
--- a/src/conf/accounts.rs
+++ b/src/conf/accounts.rs
@@ -1355,24 +1355,19 @@ impl Account {
let mut timeout = false;
let mut drain: SmallVec<[std::time::Instant; 16]> = SmallVec::new();
const ONLINE_TIMEOUT: std::time::Duration = std::time::Duration::from_secs(30);
- for (_instant, j) in self
+ for (_instant, _) in self
.active_job_instants
.range(..std::time::Instant::now() - ONLINE_TIMEOUT)
{
- if self.active_jobs.contains_key(j) {
- debug!("timeout for {} {:?}", j, self.active_jobs[j]);
- let req = self.active_jobs.remove(j).unwrap();
- self.sender
- .send(ThreadEvent::UIEvent(UIEvent::StatusEvent(
- StatusEvent::JobCanceled(*j),
- )))
- .unwrap();
- timeout |= !req.is_watch();
- }
drain.push(*_instant);
}
- for j in drain {
- self.active_job_instants.remove(&j);
+ for inst in drain {
+ if let Some(j) = self.active_job_instants.remove(&inst) {
+ if let Some(req) = self.cancel_job(j) {
+ debug!("timeout for {} {:?}", j, &req);
+ timeout |= !req.is_watch();
+ }
+ }
}
if self.is_online.is_err()
&& self
@@ -2009,6 +2004,19 @@ impl Account {
)))
.unwrap();
}
+
+ pub fn cancel_job(&mut self, job_id: JobId) -> Option<JobRequest> {
+ if let Some(req) = self.active_jobs.remove(&job_id) {
+ self.sender
+ .send(ThreadEvent::UIEvent(UIEvent::StatusEvent(
+ StatusEvent::JobCanceled(job_id),
+ )))
+ .unwrap();
+ Some(req)
+ } else {
+ None
+ }
+ }
}
impl Index<&MailboxHash> for Account {