imap: use uidnext for fetching all messages in get()

async
Manos Pitsidianakis 2020-06-23 12:37:27 +03:00
parent c08ceae97c
commit 6f6f795fd5
Signed by: Manos Pitsidianakis
GPG Key ID: 73627C2F690DF710
1 changed files with 27 additions and 16 deletions

View File

@ -235,10 +235,9 @@ impl MailBackend for ImapType {
if let Err(err) = (move || { if let Err(err) = (move || {
let tx = _tx; let tx = _tx;
let mut our_unseen = 0; let mut our_unseen = 0;
let mut max_uid: cache::MaxUID = 0;
let mut valid_hash_set: HashSet<EnvelopeHash> = HashSet::default(); let mut valid_hash_set: HashSet<EnvelopeHash> = HashSet::default();
let cached_hash_set: HashSet<EnvelopeHash> = let cached_hash_set: HashSet<EnvelopeHash> =
(|max_uid: &mut cache::MaxUID| -> Result<HashSet<EnvelopeHash>> { (|| -> Result<HashSet<EnvelopeHash>> {
if !uid_store.cache_headers { if !uid_store.cache_headers {
return Ok(HashSet::default()); return Ok(HashSet::default());
} }
@ -261,7 +260,6 @@ impl MailBackend for ImapType {
"Could not get envelopes in cache in get()" "Could not get envelopes in cache in get()"
})?; })?;
let (_max_uid, envelopes) = debug!(cached_envs); let (_max_uid, envelopes) = debug!(cached_envs);
*max_uid = _max_uid;
let ret = envelopes.iter().map(|(_, env)| env.hash()).collect(); let ret = envelopes.iter().map(|(_, env)| env.hash()).collect();
if !envelopes.is_empty() { if !envelopes.is_empty() {
let mut payload = vec![]; let mut payload = vec![];
@ -287,7 +285,7 @@ impl MailBackend for ImapType {
tx.send(AsyncStatus::Payload(Ok(payload))).unwrap(); tx.send(AsyncStatus::Payload(Ok(payload))).unwrap();
} }
Ok(ret) Ok(ret)
})(&mut max_uid) })()
.unwrap_or_default(); .unwrap_or_default();
let mut conn = connection.lock()?; let mut conn = connection.lock()?;
@ -338,11 +336,25 @@ impl MailBackend for ImapType {
*mailbox_exists = examine_response.exists; *mailbox_exists = examine_response.exists;
} }
if examine_response.exists == 0 { if examine_response.exists == 0 {
if uid_store.cache_headers {
for &env_hash in &cached_hash_set {
conn.add_refresh_event(RefreshEvent {
account_hash: uid_store.account_hash,
mailbox_hash,
kind: RefreshEventKind::Remove(env_hash),
});
}
let _ = cache::save_envelopes(
uid_store.account_hash,
mailbox_hash,
examine_response.uidvalidity,
&[],
);
}
tx.send(AsyncStatus::Payload(Ok(Vec::new()))).unwrap(); tx.send(AsyncStatus::Payload(Ok(Vec::new()))).unwrap();
tx.send(AsyncStatus::Finished).unwrap(); tx.send(AsyncStatus::Finished).unwrap();
return Ok(()); return Ok(());
} }
let mut exists: usize = examine_response.exists;
/* reselecting the same mailbox with EXAMINE prevents expunging it */ /* reselecting the same mailbox with EXAMINE prevents expunging it */
conn.examine_mailbox(mailbox_hash, &mut response)?; conn.examine_mailbox(mailbox_hash, &mut response)?;
if examine_response.uidnext == 0 { if examine_response.uidnext == 0 {
@ -363,13 +375,14 @@ impl MailBackend for ImapType {
return Err(MeliError::new("IMAP server did not reply with UIDNEXT")); return Err(MeliError::new("IMAP server did not reply with UIDNEXT"));
} }
} }
let mut max_uid_left: usize = examine_response.uidnext - 1;
let mut tag_lck = uid_store.tag_index.write().unwrap(); let mut tag_lck = uid_store.tag_index.write().unwrap();
while exists > max_uid { while max_uid_left > 0 {
let mut envelopes = vec![]; let mut envelopes = vec![];
debug!("{} exists= {}", mailbox_hash, exists); debug!("{} max_uid_left= {}", mailbox_hash, max_uid_left);
if exists == 1 { if max_uid_left == 1 {
debug!("UID FETCH 1 (UID FLAGS ENVELOPE BODYSTRUCTURE)"); debug!("UID FETCH 1 (UID FLAGS ENVELOPE BODYSTRUCTURE)");
conn.send_command(b"UID FETCH 1 (UID FLAGS ENVELOPE BODYSTRUCTURE)")?; conn.send_command(b"UID FETCH 1 (UID FLAGS ENVELOPE BODYSTRUCTURE)")?;
} else { } else {
@ -377,10 +390,10 @@ impl MailBackend for ImapType {
debug!(format!( debug!(format!(
"UID FETCH {}:{} (UID FLAGS ENVELOPE BODYSTRUCTURE)", "UID FETCH {}:{} (UID FLAGS ENVELOPE BODYSTRUCTURE)",
std::cmp::max( std::cmp::max(
std::cmp::max(exists.saturating_sub(500), 1), std::cmp::max(max_uid_left.saturating_sub(500), 1),
max_uid + 1 1
), ),
exists max_uid_left
)) ))
.as_bytes(), .as_bytes(),
)? )?
@ -437,10 +450,8 @@ impl MailBackend for ImapType {
.insert((mailbox_hash, uid), env.hash()); .insert((mailbox_hash, uid), env.hash());
envelopes.push((uid, env)); envelopes.push((uid, env));
} }
exists = std::cmp::max( max_uid_left =
std::cmp::max(exists.saturating_sub(500), 1), std::cmp::max(std::cmp::max(max_uid_left.saturating_sub(500), 1), 1);
max_uid + 1,
);
debug!("sending payload for {}", mailbox_hash); debug!("sending payload for {}", mailbox_hash);
if uid_store.cache_headers { if uid_store.cache_headers {
cache::save_envelopes( cache::save_envelopes(
@ -474,7 +485,7 @@ impl MailBackend for ImapType {
.collect::<Vec<Envelope>>()))) .collect::<Vec<Envelope>>())))
.unwrap(); .unwrap();
tx.send(AsyncStatus::ProgressReport(progress)).unwrap(); tx.send(AsyncStatus::ProgressReport(progress)).unwrap();
if exists == 1 { if max_uid_left == 1 {
break; break;
} }
} }