make setup_handle_if_needed async, call it ahead of select_folder and fetch_new_messages (renamed from fetch_from_single_folder), and be more eager triggering reconnect on error conditions

This commit is contained in:
holger krekel
2019-12-05 20:57:58 +01:00
parent 4a9fb0212f
commit 174bc017ad
2 changed files with 107 additions and 105 deletions

View File

@@ -201,8 +201,7 @@ impl Imap {
self.should_reconnect.store(true, Ordering::Relaxed)
}
fn setup_handle_if_needed(&self, context: &Context) -> Result<()> {
task::block_on(async move {
async fn setup_handle_if_needed(&self, context: &Context) -> Result<()> {
if self.config.read().await.imap_server.is_empty() {
return Err(Error::InTeardown);
}
@@ -254,9 +253,7 @@ impl Imap {
if (server_flags & DC_LP_AUTH_OAUTH2) != 0 {
let addr: &str = config.addr.as_ref();
if let Some(token) =
dc_get_oauth2_access_token(context, addr, imap_pw, true)
{
if let Some(token) = dc_get_oauth2_access_token(context, addr, imap_pw, true) {
let auth = OAuth2 {
user: imap_user.into(),
access_token: token,
@@ -295,8 +292,7 @@ impl Imap {
}
Err((err, _)) => {
let imap_user = self.config.read().await.imap_user.to_owned();
let message =
context.stock_string_repl_str(StockMessage::CannotLogin, &imap_user);
let message = context.stock_string_repl_str(StockMessage::CannotLogin, &imap_user);
emit_event!(
context,
@@ -306,7 +302,6 @@ impl Imap {
Err(Error::LoginFailed(format!("cannot login as {}", imap_user)))
}
}
})
}
async fn unsetup_handle(&self, context: &Context) {
@@ -387,7 +382,7 @@ impl Imap {
config.server_flags = server_flags;
}
if let Err(err) = self.setup_handle_if_needed(context) {
if let Err(err) = self.setup_handle_if_needed(context).await {
warn!(context, "failed to setup imap handle: {}", err);
self.free_connect_params().await;
return false;
@@ -449,10 +444,9 @@ impl Imap {
// probably shutdown
return Err(Error::InTeardown);
}
while self
.fetch_from_single_folder(context, &watch_folder)
.await?
{
self.setup_handle_if_needed(context).await?;
while self.fetch_new_messages(context, &watch_folder).await? {
// We fetch until no more new messages are there.
}
Ok(())
@@ -560,7 +554,7 @@ impl Imap {
})
}
async fn fetch_from_single_folder<S: AsRef<str>>(
async fn fetch_new_messages<S: AsRef<str>>(
&self,
context: &Context,
folder: S,
@@ -593,9 +587,11 @@ impl Imap {
for msg in &list {
let cur_uid = msg.uid.unwrap_or_default();
if cur_uid <= last_seen_uid {
warn!(
// seems that at least dovecot sends the last available UID
// even if we asked for higher UID+N:*
info!(
context,
"unexpected uid {}, last seen was {}", cur_uid, last_seen_uid
"fetch_new_messages: ignoring uid {}, last seen was {}", cur_uid, last_seen_uid
);
continue;
}
@@ -740,7 +736,7 @@ impl Imap {
return Err(Error::IdleAbilityMissing);
}
self.setup_handle_if_needed(context)?;
self.setup_handle_if_needed(context).await?;
self.select_folder(context, watch_folder.clone()).await?;
@@ -886,9 +882,9 @@ impl Imap {
// will not find any new.
if let Some(ref watch_folder) = watch_folder {
match self.fetch_from_single_folder(context, watch_folder).await {
match self.fetch_new_messages(context, watch_folder).await {
Ok(res) => {
info!(context, "fetch_from_single_folder returned {:?}", res);
info!(context, "fetch_new_messages returned {:?}", res);
if res {
break;
}
@@ -1322,13 +1318,17 @@ impl Imap {
task::block_on(async move {
info!(context, "emptying folder {}", folder);
// we want to report all error to the user
// (no retry should be attempted)
if folder.is_empty() {
error!(context, "cannot perform empty, folder not set");
return;
}
if let Err(err) = self.setup_handle_if_needed(context).await {
error!(context, "could not setup imap connection: {:?}", err);
return;
}
if let Err(err) = self.select_folder(context, Some(&folder)).await {
// we want to report all error to the user
// (no retry should be attempted)
error!(
context,
"Could not select {} for expunging: {:?}", folder, err

View File

@@ -34,6 +34,7 @@ impl Imap {
let mut cfg = self.config.write().await;
cfg.selected_folder = None;
cfg.selected_folder_needs_expunge = false;
self.trigger_reconnect();
return Err(Error::NoSession);
}
@@ -61,6 +62,7 @@ impl Imap {
info!(context, "close/expunge succeeded");
}
Err(err) => {
self.trigger_reconnect();
return Err(Error::CloseExpungeFailed(err));
}
}