melib/imap: perform reconnect on IDLE failure
parent
670675edcc
commit
17a4ccdcbc
|
@ -479,6 +479,17 @@ impl MailBackend for ImapType {
|
||||||
main_conn.uid_store.is_online.lock().unwrap().1 = Err(err.clone());
|
main_conn.uid_store.is_online.lock().unwrap().1 = Err(err.clone());
|
||||||
}
|
}
|
||||||
debug!("failure: {}", err.to_string());
|
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;
|
let account_hash = main_conn.uid_store.account_hash;
|
||||||
main_conn.add_refresh_event(RefreshEvent {
|
main_conn.add_refresh_event(RefreshEvent {
|
||||||
account_hash,
|
account_hash,
|
||||||
|
|
|
@ -984,7 +984,7 @@ pub struct ImapBlockingConnection {
|
||||||
result: Vec<u8>,
|
result: Vec<u8>,
|
||||||
prev_res_length: usize,
|
prev_res_length: usize,
|
||||||
pub conn: ImapConnection,
|
pub conn: ImapConnection,
|
||||||
err: Option<String>,
|
err: Option<MeliError>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<ImapConnection> for ImapBlockingConnection {
|
impl From<ImapConnection> for ImapBlockingConnection {
|
||||||
|
@ -1004,8 +1004,8 @@ impl ImapBlockingConnection {
|
||||||
self.conn
|
self.conn
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn err(&self) -> Option<&str> {
|
pub fn err(&mut self) -> Option<MeliError> {
|
||||||
self.err.as_deref()
|
self.err.take()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn as_stream<'a>(&'a mut self) -> impl Future<Output = Option<Vec<u8>>> + 'a {
|
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;
|
*prev_failure = None;
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(_err) => {
|
||||||
debug!(&conn.stream);
|
debug!(&conn.stream);
|
||||||
debug!(&e);
|
debug!(&_err);
|
||||||
*err = Some(e.to_string());
|
*err = Some(Into::<MeliError>::into(_err).set_kind(crate::error::ErrorKind::Network));
|
||||||
*break_flag = true;
|
*break_flag = true;
|
||||||
*prev_failure = Some(Instant::now());
|
*prev_failure = Some(Instant::now());
|
||||||
}
|
}
|
||||||
|
|
|
@ -185,8 +185,10 @@ pub async fn idle(kit: ImapWatchKit) -> Result<()> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
debug!("IDLE connection dropped");
|
debug!("IDLE connection dropped");
|
||||||
let err: &str = blockn.err().unwrap_or("Unknown reason.");
|
Err(blockn
|
||||||
Err(MeliError::new(format!("IDLE connection dropped: {}", err)))
|
.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(
|
pub async fn examine_updates(
|
||||||
|
|
|
@ -205,7 +205,9 @@ impl Error for MeliError {
|
||||||
impl From<io::Error> for MeliError {
|
impl From<io::Error> for MeliError {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn from(kind: io::Error) -> MeliError {
|
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)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1355,24 +1355,19 @@ impl Account {
|
||||||
let mut timeout = false;
|
let mut timeout = false;
|
||||||
let mut drain: SmallVec<[std::time::Instant; 16]> = SmallVec::new();
|
let mut drain: SmallVec<[std::time::Instant; 16]> = SmallVec::new();
|
||||||
const ONLINE_TIMEOUT: std::time::Duration = std::time::Duration::from_secs(30);
|
const ONLINE_TIMEOUT: std::time::Duration = std::time::Duration::from_secs(30);
|
||||||
for (_instant, j) in self
|
for (_instant, _) in self
|
||||||
.active_job_instants
|
.active_job_instants
|
||||||
.range(..std::time::Instant::now() - ONLINE_TIMEOUT)
|
.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);
|
drain.push(*_instant);
|
||||||
}
|
}
|
||||||
for j in drain {
|
for inst in drain {
|
||||||
self.active_job_instants.remove(&j);
|
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()
|
if self.is_online.is_err()
|
||||||
&& self
|
&& self
|
||||||
|
@ -2009,6 +2004,19 @@ impl Account {
|
||||||
)))
|
)))
|
||||||
.unwrap();
|
.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 {
|
impl Index<&MailboxHash> for Account {
|
||||||
|
|
Loading…
Reference in New Issue