mirror of
https://github.com/chatmail/core.git
synced 2026-05-08 09:26:29 +03:00
implement timeout handling
This commit is contained in:
@@ -50,7 +50,7 @@ impl Imap {
|
|||||||
&self,
|
&self,
|
||||||
context: &Context,
|
context: &Context,
|
||||||
watch_folder: Option<String>,
|
watch_folder: Option<String>,
|
||||||
timeout: Duration,
|
until: SystemTime,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
task::block_on(async move {
|
task::block_on(async move {
|
||||||
if !self.can_idle() {
|
if !self.can_idle() {
|
||||||
@@ -63,8 +63,18 @@ impl Imap {
|
|||||||
|
|
||||||
self.select_folder(context, watch_folder.clone()).await?;
|
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 session = self.session.lock().await.take();
|
||||||
let max_duration = Duration::from_secs(23 * 60);
|
|
||||||
if let Some(session) = session {
|
if let Some(session) = session {
|
||||||
match session.idle() {
|
match session.idle() {
|
||||||
// BEWARE: If you change the Secure branch you
|
// BEWARE: If you change the Secure branch you
|
||||||
@@ -73,8 +83,7 @@ impl Imap {
|
|||||||
if let Err(err) = handle.init().await {
|
if let Err(err) = handle.init().await {
|
||||||
return Err(Error::IdleProtocolFailed(err));
|
return Err(Error::IdleProtocolFailed(err));
|
||||||
}
|
}
|
||||||
let real_timeout = min(timeout, max_duration);
|
let (idle_wait, interrupt) = handle.wait_with_timeout(timeout);
|
||||||
let (idle_wait, interrupt) = handle.wait_with_timeout(real_timeout);
|
|
||||||
*self.interrupt.lock().await = Some(interrupt);
|
*self.interrupt.lock().await = Some(interrupt);
|
||||||
|
|
||||||
if self.skip_next_idle_wait.load(Ordering::SeqCst) {
|
if self.skip_next_idle_wait.load(Ordering::SeqCst) {
|
||||||
@@ -188,7 +197,7 @@ impl Imap {
|
|||||||
&self,
|
&self,
|
||||||
context: &Context,
|
context: &Context,
|
||||||
watch_folder: Option<String>,
|
watch_folder: Option<String>,
|
||||||
timeout: Duration,
|
until: SystemTime,
|
||||||
) {
|
) {
|
||||||
// Idle using polling. This is also needed if we're not yet configured -
|
// 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).
|
// 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");
|
info!(context, "fake_idle is connected");
|
||||||
|
|
||||||
if SystemTime::now()
|
if SystemTime::now() > until {
|
||||||
.duration_since(fake_idle_start_time)
|
|
||||||
.unwrap_or_default()
|
|
||||||
> timeout
|
|
||||||
{
|
|
||||||
info!(context, "fake_idle stopping as jobs need running");
|
info!(context, "fake_idle stopping as jobs need running");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
13
src/job.rs
13
src/job.rs
@@ -466,9 +466,7 @@ pub fn perform_sentbox_idle(context: &Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn interrupt_inbox_idle(context: &Context) {
|
pub fn interrupt_inbox_idle(context: &Context) {
|
||||||
info!(context, "interrupt_inbox_idle begin");
|
|
||||||
context.inbox_thread.read().unwrap().interrupt_idle(context);
|
context.inbox_thread.read().unwrap().interrupt_idle(context);
|
||||||
info!(context, "interrupt_inbox_idle finish");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn interrupt_mvbox_idle(context: &Context) {
|
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();
|
.unwrap_or_default();
|
||||||
|
|
||||||
let mut wakeup_time = Duration::new(10 * 60, 0);
|
|
||||||
let now = time();
|
|
||||||
if t > 0 {
|
if t > 0 {
|
||||||
|
let now = time();
|
||||||
if t > now {
|
if t > now {
|
||||||
wakeup_time = Duration::new((t - now) as u64, 0);
|
Duration::new((t - now) as u64, 0)
|
||||||
} else {
|
} 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) {
|
pub fn maybe_network(context: &Context) {
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ use crate::context::Context;
|
|||||||
use crate::error::{Error, Result};
|
use crate::error::{Error, Result};
|
||||||
use crate::imap::Imap;
|
use crate::imap::Imap;
|
||||||
use crate::job::{get_next_wakeup_time, Thread};
|
use crate::job::{get_next_wakeup_time, Thread};
|
||||||
use std::time::Duration;
|
use std::time::{Duration, SystemTime};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct JobThread {
|
pub struct JobThread {
|
||||||
@@ -136,13 +136,12 @@ impl JobThread {
|
|||||||
pub fn idle(&self, context: &Context, use_network: bool) {
|
pub fn idle(&self, context: &Context, use_network: bool) {
|
||||||
// standard idle wait timeout
|
// standard idle wait timeout
|
||||||
let mut timeout = Duration::from_secs(23 * 60);
|
let mut timeout = Duration::from_secs(23 * 60);
|
||||||
|
|
||||||
{
|
{
|
||||||
let &(ref lock, ref cvar) = &*self.state.clone();
|
let &(ref lock, ref cvar) = &*self.state.clone();
|
||||||
let mut state = lock.lock().unwrap();
|
let mut state = lock.lock().unwrap();
|
||||||
|
|
||||||
// if we are in the inbox (job) thread
|
// if we are in the inbox (job) thread we only want to wait
|
||||||
// we check if a job is due.
|
// until the next job is due.
|
||||||
if self.folder_config_name == "configured_inbox_folder" {
|
if self.folder_config_name == "configured_inbox_folder" {
|
||||||
timeout = get_next_wakeup_time(context, Thread::Imap);
|
timeout = get_next_wakeup_time(context, Thread::Imap);
|
||||||
if timeout <= Duration::from_millis(20) {
|
if timeout <= Duration::from_millis(20) {
|
||||||
@@ -175,6 +174,8 @@ impl JobThread {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let until = SystemTime::now() + timeout;
|
||||||
|
|
||||||
let prefix = format!("{}-IDLE", self.name);
|
let prefix = format!("{}-IDLE", self.name);
|
||||||
let do_fake_idle = match self.imap.connect_configured(context) {
|
let do_fake_idle = match self.imap.connect_configured(context) {
|
||||||
Ok(()) => {
|
Ok(()) => {
|
||||||
@@ -183,7 +184,7 @@ impl JobThread {
|
|||||||
} else {
|
} else {
|
||||||
let watch_folder = self.get_watch_folder(context);
|
let watch_folder = self.get_watch_folder(context);
|
||||||
info!(context, "{} started...", prefix);
|
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);
|
info!(context, "{} ended...", prefix);
|
||||||
if let Err(err) = res {
|
if let Err(err) = res {
|
||||||
warn!(context, "{} failed: {} -> reconnecting", prefix, err);
|
warn!(context, "{} failed: {} -> reconnecting", prefix, err);
|
||||||
@@ -203,7 +204,7 @@ impl JobThread {
|
|||||||
};
|
};
|
||||||
if do_fake_idle {
|
if do_fake_idle {
|
||||||
let watch_folder = self.get_watch_folder(context);
|
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;
|
self.state.0.lock().unwrap().using_handle = false;
|
||||||
|
|||||||
Reference in New Issue
Block a user