melib/imap: always retry connection in watch()

memfd
Manos Pitsidianakis 2020-09-15 12:59:31 +03:00
parent 67c722958b
commit 0e2641f7ed
Signed by: Manos Pitsidianakis
GPG Key ID: 73627C2F690DF710
2 changed files with 44 additions and 40 deletions

View File

@ -444,7 +444,7 @@ impl MailBackend for ImapType {
}
fn watch(&self) -> ResultFuture<()> {
let conn = ImapConnection::new_connection(&self.server_conf, self.uid_store.clone());
let server_conf = self.server_conf.clone();
let main_conn = self.connection.clone();
let uid_store = self.uid_store.clone();
let has_idle: bool = match self.server_conf.protocol {
@ -462,24 +462,27 @@ impl MailBackend for ImapType {
};
Ok(Box::pin(async move {
debug!(has_idle);
let main_conn2 = main_conn.clone();
let timeout_dur = uid_store.timeout;
let kit = ImapWatchKit {
conn,
main_conn,
uid_store,
};
if let Err(err) = if has_idle {
idle(kit).await
while let Err(err) = if has_idle {
idle(ImapWatchKit {
conn: ImapConnection::new_connection(&server_conf, uid_store.clone()),
main_conn: main_conn.clone(),
uid_store: uid_store.clone(),
})
.await
} else {
poll_with_examine(kit).await
poll_with_examine(ImapWatchKit {
conn: ImapConnection::new_connection(&server_conf, uid_store.clone()),
main_conn: main_conn.clone(),
uid_store: uid_store.clone(),
})
.await
} {
let mut main_conn = timeout(timeout_dur, main_conn2.lock()).await?;
let mut main_conn_lck = timeout(uid_store.timeout, main_conn.lock()).await?;
if err.kind.is_network() {
main_conn.uid_store.is_online.lock().unwrap().1 = Err(err.clone());
uid_store.is_online.lock().unwrap().1 = Err(err.clone());
}
debug!("failure: {}", err.to_string());
match timeout(timeout_dur, main_conn.connect())
match timeout(uid_store.timeout, main_conn_lck.connect())
.await
.and_then(|res| res)
{
@ -488,10 +491,11 @@ impl MailBackend for ImapType {
}
Ok(()) => {
debug!("reconnect attempt succesful");
continue;
}
}
let account_hash = main_conn.uid_store.account_hash;
main_conn.add_refresh_event(RefreshEvent {
let account_hash = uid_store.account_hash;
main_conn_lck.add_refresh_event(RefreshEvent {
account_hash,
mailbox_hash: 0,
kind: RefreshEventKind::Failure(err.clone()),

View File

@ -113,30 +113,35 @@ pub async fn idle(kit: ImapWatchKit) -> Result<()> {
};
conn.send_command(b"IDLE").await?;
let mut blockn = ImapBlockingConnection::from(conn);
let mut beat = std::time::Instant::now();
let mut watch = std::time::Instant::now();
/* duration interval before IMAP timeouts */
const _35_MINS: std::time::Duration = std::time::Duration::from_secs(35 * 60);
/* duration interval to send heartbeat */
const _26_MINS: std::time::Duration = std::time::Duration::from_secs(26 * 60);
const _10_MINS: std::time::Duration = std::time::Duration::from_secs(10 * 60);
/* duration interval to check other mailboxes for changes */
const _5_MINS: std::time::Duration = std::time::Duration::from_secs(5 * 60);
while let Some(line) = timeout(Some(_35_MINS), blockn.as_stream()).await? {
let now = std::time::Instant::now();
if now.duration_since(beat) >= _26_MINS {
loop {
let line = match timeout(Some(_10_MINS), blockn.as_stream()).await {
Ok(Some(line)) => line,
Ok(None) => {
debug!("IDLE connection dropped: {:?}", &blockn.err());
blockn.conn.connect().await?;
let mut main_conn_lck = timeout(uid_store.timeout, main_conn.lock()).await?;
main_conn_lck.connect().await?;
continue;
}
Err(_) => {
/* Timeout */
blockn.conn.send_raw(b"DONE").await?;
blockn
.conn
.read_response(&mut response, RequiredResponses::empty())
.await?;
blockn.conn.send_command(b"IDLE").await?;
main_conn_lck.send_command(b"NOOP").await?;
main_conn_lck
.read_response(&mut response, RequiredResponses::empty())
.await?;
beat = now;
let mut main_conn_lck = timeout(uid_store.timeout, main_conn.lock()).await?;
main_conn_lck.connect().await?;
continue;
}
};
let now = std::time::Instant::now();
if now.duration_since(watch) >= _5_MINS {
/* Time to poll all inboxes */
let mut conn = timeout(uid_store.timeout, main_conn.lock()).await?;
@ -184,11 +189,6 @@ pub async fn idle(kit: ImapWatchKit) -> Result<()> {
blockn.conn.send_command(b"IDLE").await?;
}
}
debug!("IDLE connection dropped");
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(