From 0405c945e26692565e5dca83308bc8216c1f349b Mon Sep 17 00:00:00 2001 From: holger krekel Date: Tue, 12 Nov 2019 13:27:38 +0100 Subject: [PATCH] shortcut fetch/idle on mvbox/sentbox if we don't know the folder and prevent busy-looping --- src/imap.rs | 38 +++++++++++++++++++++++++------------- src/job_thread.rs | 32 ++++++++++++++++++++------------ 2 files changed, 45 insertions(+), 25 deletions(-) diff --git a/src/imap.rs b/src/imap.rs index 7859d2299..f1cbab6c0 100644 --- a/src/imap.rs +++ b/src/imap.rs @@ -746,10 +746,13 @@ impl Imap { pub fn idle(&self, context: &Context) { task::block_on(async move { if self.config.read().await.selected_folder.is_none() { + // this probably means that we are in teardown + // in any case we can't perform any idling return; } + if !self.config.read().await.can_idle { - self.fake_idle(context).await; + self.fake_idle(context, true).await; return; } @@ -765,7 +768,7 @@ impl Imap { "idle select_folder failed {:?}", watch_folder.as_ref() ); - self.fake_idle(context).await; + self.fake_idle(context, true).await; return; } } @@ -836,7 +839,7 @@ impl Imap { }); } - async fn fake_idle(&self, context: &Context) { + pub(crate) async fn fake_idle(&self, context: &Context, use_network: bool) { // Idle using timeouts. This is also needed if we're not yet configured - // in this case, we're waiting for a configure job let fake_idle_start_time = SystemTime::now(); @@ -846,13 +849,20 @@ impl Imap { task::block_on(async move { let interrupt = stop_token::StopSource::new(); - // TODO: More flexible interval - let interval = async_std::stream::interval(Duration::from_secs(10)); + // we use 1000 minutes if we are told to not try network + // which can happen because the watch_folder is not defined + // but clients are still calling us in a loop. + // if we are to use network, we check every minute if there + // is new mail -- TODO: make this more flexible + let secs = if use_network { 60 } else { 60000 }; + let interval = async_std::stream::interval(Duration::from_secs(secs)); let mut interrupt_interval = interrupt.stop_token().stop_stream(interval); *self.interrupt.lock().await = Some(interrupt); while let Some(_) = interrupt_interval.next().await { - // check if we want to finish fake-idling. + if !use_network { + continue; + } if !self.is_connected().await { // try to connect with proper login params // (setup_handle_if_needed might not know about them if we @@ -1154,13 +1164,6 @@ impl Imap { .list_folders(session, context) .await .expect("no folders found"); - let delimiter = self.config.read().await.imap_delimiter; - let fallback_folder = format!("INBOX{}DeltaChat", delimiter); - - let mut mvbox_folder = folders - .iter() - .find(|folder| folder.name() == "DeltaChat" || folder.name() == fallback_folder) - .map(|n| n.name().to_string()); let sentbox_folder = folders @@ -1169,6 +1172,15 @@ impl Imap { FolderMeaning::SentObjects => true, _ => false, }); + info!(context, "sentbox folder is {:?}", sentbox_folder); + + let delimiter = self.config.read().await.imap_delimiter; + let fallback_folder = format!("INBOX{}DeltaChat", delimiter); + + let mut mvbox_folder = folders + .iter() + .find(|folder| folder.name() == "DeltaChat" || folder.name() == fallback_folder) + .map(|n| n.name().to_string()); if mvbox_folder.is_none() && 0 != (flags as usize & DC_CREATE_MVBOX) { info!(context, "Creating MVBOX-folder \"DeltaChat\"...",); diff --git a/src/job_thread.rs b/src/job_thread.rs index 8204a98e0..21362fb5b 100644 --- a/src/job_thread.rs +++ b/src/job_thread.rs @@ -110,9 +110,14 @@ impl JobThread { if async_std::task::block_on(async move { self.imap.is_connected().await }) { return true; } + let watch_folder_name = match context.sql.get_raw_config(context, self.folder_config_name) { + Some(name) => name, + None => { + return false; + } + }; - let mut ret_connected = dc_connect_to_configured_imap(context, &self.imap) != 0; - + let ret_connected = dc_connect_to_configured_imap(context, &self.imap) != 0; if ret_connected { if context .sql @@ -123,12 +128,7 @@ impl JobThread { self.imap.configure_folders(context, 0x1); } - if let Some(mvbox_name) = context.sql.get_raw_config(context, self.folder_config_name) { - self.imap.set_watch_folder(mvbox_name); - } else { - self.imap.disconnect(context); - ret_connected = false; - } + self.imap.set_watch_folder(watch_folder_name); } ret_connected @@ -170,10 +170,18 @@ impl JobThread { } } - self.connect_to_imap(context); - info!(context, "{}-IDLE started...", self.name,); - self.imap.idle(context); - info!(context, "{}-IDLE ended.", self.name); + if self.connect_to_imap(context) { + info!(context, "{}-IDLE started...", self.name,); + self.imap.idle(context); + info!(context, "{}-IDLE ended.", self.name); + } else { + // It's probably wrong that the thread even runs + // but let's call fake_idle and tell it to not try network at all. + // (once we move to rust-managed threads this problem goes away) + info!(context, "{}-IDLE not connected, fake-idling", self.name); + async_std::task::block_on(async move { self.imap.fake_idle(context, false).await }); + info!(context, "{}-IDLE fake-idling finished", self.name); + } self.state.0.lock().unwrap().using_handle = false; }