cleanup interrupt and exit of imap idle

This commit is contained in:
dignifiedquire
2020-07-07 12:54:24 +02:00
committed by link2xt
parent 3df0ef50a4
commit 7d08397b48
2 changed files with 83 additions and 118 deletions

View File

@@ -48,11 +48,10 @@ impl Imap {
self.select_folder(context, watch_folder.clone()).await?;
let session = self.session.take();
let timeout = Duration::from_secs(23 * 60);
let mut info = Default::default();
if let Some(session) = session {
if let Some(session) = self.session.take() {
let mut handle = session.idle();
if let Err(err) = handle.init().await {
return Err(Error::IdleProtocolFailed(err));
@@ -65,29 +64,20 @@ impl Imap {
Interrupt(InterruptInfo),
}
if self.skip_next_idle_wait {
// interrupt_idle has happened before we
// provided self.interrupt
self.skip_next_idle_wait = false;
drop(idle_wait);
info!(context, "Idle entering wait-on-remote state");
let fut = idle_wait.map(|ev| ev.map(Event::IdleResponse)).race(async {
let probe_network = self.idle_interrupt.recv().await;
// cancel imap idle connection properly
drop(interrupt);
info!(context, "Idle wait was skipped");
} else {
info!(context, "Idle entering wait-on-remote state");
let fut = idle_wait.map(|ev| ev.map(Event::IdleResponse)).race(
self.idle_interrupt.recv().map(|probe_network| {
Ok(Event::Interrupt(probe_network.unwrap_or_default()))
}),
);
});
match fut.await {
Ok(Event::IdleResponse(IdleResponse::NewData(_))) => {
info!(context, "Idle has NewData");
}
// TODO: idle_wait does not distinguish manual interrupts
// from Timeouts if we would know it's a Timeout we could bail
// directly and reconnect .
Ok(Event::IdleResponse(IdleResponse::Timeout)) => {
info!(context, "Idle-wait timeout or interruption");
}
@@ -102,31 +92,15 @@ impl Imap {
warn!(context, "Idle wait errored: {:?}", err);
}
}
}
// if we can't properly terminate the idle
// protocol let's break the connection.
let res = handle
let session = handle
.done()
.timeout(Duration::from_secs(15))
.await
.map_err(|err| {
self.trigger_reconnect();
Error::IdleTimeout(err)
})?;
match res {
Ok(session) => {
.map_err(Error::IdleTimeout)??;
self.session = Some(Session { inner: session });
}
Err(err) => {
// if we cannot terminate IDLE it probably
// means that we waited long (with idle_wait)
// but the network went away/changed
self.trigger_reconnect();
return Err(Error::IdleProtocolFailed(err));
}
}
} else {
warn!(context, "Attempted to idle without a session");
}
Ok(info)
@@ -148,13 +122,6 @@ impl Imap {
return self.idle_interrupt.recv().await.unwrap_or_default();
}
let mut info: InterruptInfo = Default::default();
if self.skip_next_idle_wait {
// interrupt_idle has happened before we
// provided self.interrupt
self.skip_next_idle_wait = false;
info!(context, "fake-idle wait was skipped");
} else {
// check every minute if there are new messages
// TODO: grow sleep durations / make them more flexible
let mut interval = async_std::stream::interval(Duration::from_secs(60));
@@ -164,15 +131,16 @@ impl Imap {
Interrupt(InterruptInfo),
}
// loop until we are interrupted or if we fetched something
info =
loop {
let info = loop {
use futures::future::FutureExt;
match interval
.next()
.map(|_| Event::Tick)
.race(self.idle_interrupt.recv().map(|probe_network| {
Event::Interrupt(probe_network.unwrap_or_default())
}))
.race(
self.idle_interrupt
.recv()
.map(|probe_network| Event::Interrupt(probe_network.unwrap_or_default())),
)
.await
{
Event::Tick => {
@@ -214,7 +182,6 @@ impl Imap {
}
}
};
}
info!(
context,

View File

@@ -117,7 +117,6 @@ pub struct Imap {
session: Option<Session>,
connected: bool,
interrupt: Option<stop_token::StopSource>,
skip_next_idle_wait: bool,
should_reconnect: bool,
}
@@ -191,7 +190,6 @@ impl Imap {
session: Default::default(),
connected: Default::default(),
interrupt: Default::default(),
skip_next_idle_wait: Default::default(),
should_reconnect: Default::default(),
}
}