mirror of
https://github.com/chatmail/core.git
synced 2026-05-07 17:06:35 +03:00
* fix interrupt_idle by signalling "skip_next_idle_wait" to the potentially concurrently "fn idle" function
This commit is contained in:
committed by
dignifiedquire
parent
6bdc207277
commit
e225a6fb17
64
src/imap.rs
64
src/imap.rs
@@ -45,6 +45,7 @@ pub struct Imap {
|
|||||||
session: Arc<Mutex<Option<Session>>>,
|
session: Arc<Mutex<Option<Session>>>,
|
||||||
connected: Arc<Mutex<bool>>,
|
connected: Arc<Mutex<bool>>,
|
||||||
interrupt: Arc<Mutex<Option<stop_token::StopSource>>>,
|
interrupt: Arc<Mutex<Option<stop_token::StopSource>>>,
|
||||||
|
skip_next_idle_wait: Arc<Mutex<bool>>,
|
||||||
|
|
||||||
should_reconnect: AtomicBool,
|
should_reconnect: AtomicBool,
|
||||||
}
|
}
|
||||||
@@ -119,6 +120,7 @@ impl Imap {
|
|||||||
config: Arc::new(RwLock::new(ImapConfig::default())),
|
config: Arc::new(RwLock::new(ImapConfig::default())),
|
||||||
interrupt: Arc::new(Mutex::new(None)),
|
interrupt: Arc::new(Mutex::new(None)),
|
||||||
connected: Arc::new(Mutex::new(false)),
|
connected: Arc::new(Mutex::new(false)),
|
||||||
|
skip_next_idle_wait: Arc::new(Mutex::new(false)),
|
||||||
should_reconnect: AtomicBool::new(false),
|
should_reconnect: AtomicBool::new(false),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -496,24 +498,16 @@ impl Imap {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async fn fetch_from_single_folder<S: AsRef<str>>(&self, context: &Context, folder: S) -> usize {
|
async fn fetch_from_single_folder<S: AsRef<str>>(&self, context: &Context, folder: S) -> usize {
|
||||||
if !self.is_connected().await {
|
match self.select_folder(context, Some(&folder)).await {
|
||||||
info!(
|
ImapActionResult::Failed | ImapActionResult::RetryLater => {
|
||||||
context,
|
warn!(
|
||||||
"Cannot fetch from \"{}\" - not connected.",
|
context,
|
||||||
folder.as_ref()
|
"Cannot select folder \"{}\" for fetching.",
|
||||||
);
|
folder.as_ref()
|
||||||
|
);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
ImapActionResult::Success | ImapActionResult::AlreadyDone => {}
|
||||||
let res = self.select_folder(context, Some(&folder)).await;
|
|
||||||
if res == ImapActionResult::Failed || res == ImapActionResult::RetryLater {
|
|
||||||
info!(
|
|
||||||
context,
|
|
||||||
"Cannot select folder \"{}\" for fetching.",
|
|
||||||
folder.as_ref()
|
|
||||||
);
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// compare last seen UIDVALIDITY against the current one
|
// compare last seen UIDVALIDITY against the current one
|
||||||
@@ -789,8 +783,17 @@ impl Imap {
|
|||||||
let (idle_wait, interrupt) = handle.wait_with_timeout(timeout);
|
let (idle_wait, interrupt) = handle.wait_with_timeout(timeout);
|
||||||
*self.interrupt.lock().await = Some(interrupt);
|
*self.interrupt.lock().await = Some(interrupt);
|
||||||
|
|
||||||
let res = idle_wait.await;
|
if *self.skip_next_idle_wait.lock().await {
|
||||||
info!(context, "Idle finished: {:?}", res);
|
// interrupt_idle has happened before we
|
||||||
|
// provided self.interrupt
|
||||||
|
*self.skip_next_idle_wait.lock().await = false;
|
||||||
|
std::mem::drop(idle_wait);
|
||||||
|
info!(context, "Idle wait was skipped");
|
||||||
|
} else {
|
||||||
|
info!(context, "Idle entering wait-on-remote state");
|
||||||
|
let res = idle_wait.await;
|
||||||
|
info!(context, "Idle finished wait-on-remote: {:?}", res);
|
||||||
|
}
|
||||||
match handle.done().await {
|
match handle.done().await {
|
||||||
Ok(session) => {
|
Ok(session) => {
|
||||||
*self.session.lock().await = Some(Session::Secure(session));
|
*self.session.lock().await = Some(Session::Secure(session));
|
||||||
@@ -808,8 +811,18 @@ impl Imap {
|
|||||||
let (idle_wait, interrupt) = handle.wait_with_timeout(timeout);
|
let (idle_wait, interrupt) = handle.wait_with_timeout(timeout);
|
||||||
*self.interrupt.lock().await = Some(interrupt);
|
*self.interrupt.lock().await = Some(interrupt);
|
||||||
|
|
||||||
let res = idle_wait.await;
|
if *self.skip_next_idle_wait.lock().await {
|
||||||
info!(context, "Idle finished: {:?}", res);
|
// interrupt_idle has happened before we
|
||||||
|
// provided self.interrupt
|
||||||
|
*self.skip_next_idle_wait.lock().await = false;
|
||||||
|
std::mem::drop(idle_wait);
|
||||||
|
info!(context, "Idle wait was skipped");
|
||||||
|
} else {
|
||||||
|
info!(context, "Idle entering wait-on-remote state");
|
||||||
|
let res = idle_wait.await;
|
||||||
|
info!(context, "Idle finished wait-on-remote: {:?}", res);
|
||||||
|
}
|
||||||
|
|
||||||
match handle.done().await {
|
match handle.done().await {
|
||||||
Ok(session) => {
|
Ok(session) => {
|
||||||
*self.session.lock().await = Some(Session::Insecure(session));
|
*self.session.lock().await = Some(Session::Insecure(session));
|
||||||
@@ -877,7 +890,10 @@ impl Imap {
|
|||||||
|
|
||||||
pub fn interrupt_idle(&self) {
|
pub fn interrupt_idle(&self) {
|
||||||
task::block_on(async move {
|
task::block_on(async move {
|
||||||
let _ = self.interrupt.lock().await.take();
|
if self.interrupt.lock().await.take().is_none() {
|
||||||
|
// idle wait is not running
|
||||||
|
*self.skip_next_idle_wait.lock().await = true;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1241,7 +1257,7 @@ impl Imap {
|
|||||||
task::block_on(async move {
|
task::block_on(async move {
|
||||||
info!(context, "emptying folder {}", folder);
|
info!(context, "emptying folder {}", folder);
|
||||||
|
|
||||||
if !folder.is_empty() {
|
if folder.is_empty() {
|
||||||
warn!(context, "cannot perform empty, folder not set");
|
warn!(context, "cannot perform empty, folder not set");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user