diff --git a/src/imap/idle.rs b/src/imap/idle.rs index a435ae659..aedb6297d 100644 --- a/src/imap/idle.rs +++ b/src/imap/idle.rs @@ -50,7 +50,7 @@ impl Imap { &self, context: &Context, watch_folder: Option, - timeout: Duration, + until: SystemTime, ) -> Result<()> { task::block_on(async move { if !self.can_idle() { @@ -63,8 +63,18 @@ impl Imap { self.select_folder(context, watch_folder.clone()).await?; + let timeout = match until.duration_since(SystemTime::now()) { + Ok(timeout) => timeout, + Err(_) => { + info!(context, "idle called with negative timeout"); + return Ok(()); + } + }; + let timeout = min(timeout, Duration::from_secs(23 * 60)); + info!(context, "idle-timeout is {:?}", timeout); + let session = self.session.lock().await.take(); - let max_duration = Duration::from_secs(23 * 60); + if let Some(session) = session { match session.idle() { // BEWARE: If you change the Secure branch you @@ -73,8 +83,7 @@ impl Imap { if let Err(err) = handle.init().await { return Err(Error::IdleProtocolFailed(err)); } - let real_timeout = min(timeout, max_duration); - let (idle_wait, interrupt) = handle.wait_with_timeout(real_timeout); + let (idle_wait, interrupt) = handle.wait_with_timeout(timeout); *self.interrupt.lock().await = Some(interrupt); if self.skip_next_idle_wait.load(Ordering::SeqCst) { @@ -188,7 +197,7 @@ impl Imap { &self, context: &Context, watch_folder: Option, - timeout: Duration, + until: SystemTime, ) { // Idle using polling. This is also needed if we're not yet configured - // in this case, we're waiting for a configure job (and an interrupt). @@ -225,11 +234,7 @@ impl Imap { } info!(context, "fake_idle is connected"); - if SystemTime::now() - .duration_since(fake_idle_start_time) - .unwrap_or_default() - > timeout - { + if SystemTime::now() > until { info!(context, "fake_idle stopping as jobs need running"); break; } diff --git a/src/job.rs b/src/job.rs index ab3aa0c46..7389b2025 100644 --- a/src/job.rs +++ b/src/job.rs @@ -466,9 +466,7 @@ pub fn perform_sentbox_idle(context: &Context) { } pub fn interrupt_inbox_idle(context: &Context) { - info!(context, "interrupt_inbox_idle begin"); context.inbox_thread.read().unwrap().interrupt_idle(context); - info!(context, "interrupt_inbox_idle finish"); } pub fn interrupt_mvbox_idle(context: &Context) { @@ -555,17 +553,16 @@ pub(crate) fn get_next_wakeup_time(context: &Context, thread: Thread) -> Duratio ) .unwrap_or_default(); - let mut wakeup_time = Duration::new(10 * 60, 0); - let now = time(); if t > 0 { + let now = time(); if t > now { - wakeup_time = Duration::new((t - now) as u64, 0); + Duration::new((t - now) as u64, 0) } else { - wakeup_time = Duration::new(0, 0); + Duration::new(0, 0) } + } else { + Duration::new(30 * 60, 0) } - - wakeup_time } pub fn maybe_network(context: &Context) { diff --git a/src/job_thread.rs b/src/job_thread.rs index c10dabecc..34c639cb2 100644 --- a/src/job_thread.rs +++ b/src/job_thread.rs @@ -4,7 +4,7 @@ use crate::context::Context; use crate::error::{Error, Result}; use crate::imap::Imap; use crate::job::{get_next_wakeup_time, Thread}; -use std::time::Duration; +use std::time::{Duration, SystemTime}; #[derive(Debug)] pub struct JobThread { @@ -136,13 +136,12 @@ impl JobThread { pub fn idle(&self, context: &Context, use_network: bool) { // standard idle wait timeout let mut timeout = Duration::from_secs(23 * 60); - { let &(ref lock, ref cvar) = &*self.state.clone(); let mut state = lock.lock().unwrap(); - // if we are in the inbox (job) thread - // we check if a job is due. + // if we are in the inbox (job) thread we only want to wait + // until the next job is due. if self.folder_config_name == "configured_inbox_folder" { timeout = get_next_wakeup_time(context, Thread::Imap); if timeout <= Duration::from_millis(20) { @@ -175,6 +174,8 @@ impl JobThread { } } + let until = SystemTime::now() + timeout; + let prefix = format!("{}-IDLE", self.name); let do_fake_idle = match self.imap.connect_configured(context) { Ok(()) => { @@ -183,7 +184,7 @@ impl JobThread { } else { let watch_folder = self.get_watch_folder(context); info!(context, "{} started...", prefix); - let res = self.imap.idle(context, watch_folder, timeout); + let res = self.imap.idle(context, watch_folder, until); info!(context, "{} ended...", prefix); if let Err(err) = res { warn!(context, "{} failed: {} -> reconnecting", prefix, err); @@ -203,7 +204,7 @@ impl JobThread { }; if do_fake_idle { let watch_folder = self.get_watch_folder(context); - self.imap.fake_idle(context, watch_folder, timeout); + self.imap.fake_idle(context, watch_folder, until); } self.state.0.lock().unwrap().using_handle = false;