melib/imap: always retry connection in watch()
parent
67c722958b
commit
0e2641f7ed
|
@ -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()),
|
||||
|
|
|
@ -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? {
|
||||
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?;
|
||||
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(beat) >= _26_MINS {
|
||||
let mut main_conn_lck = timeout(uid_store.timeout, main_conn.lock()).await?;
|
||||
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;
|
||||
}
|
||||
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(
|
||||
|
|
Loading…
Reference in New Issue