melib/imap: don't examine unloaded mailboxes for updates

In examine_updates() which is periodically executed in the IMAP watch
thread, the mailbox's contents get fetched regardless if the user has
fetched the mailbox before. That means eg a large mailbox that was
unused by the user might perform a large fetch all of a sudden without
the user's knowledge/touch.

Add `warm` property in ImapMailbox that states whether the mailbox has
been loaded before in current execution.

Closes #88 IMAP: don't examine unloaded mailboxes for updates, just for message count stats
jmap-eventsource
Manos Pitsidianakis 2020-11-29 15:52:48 +02:00
parent ddfadc748d
commit 76c1c1a213
Signed by: Manos Pitsidianakis
GPG Key ID: 73627C2F690DF710
3 changed files with 34 additions and 0 deletions

View File

@ -348,6 +348,7 @@ impl MailBackend for ImapType {
let f = &state.uid_store.mailboxes.lock().await[&mailbox_hash];
f.exists.lock().unwrap().clear();
f.unseen.lock().unwrap().clear();
f.set_warm(true);
if f.no_select {
yield vec![];
return;

View File

@ -43,12 +43,31 @@ pub struct ImapMailbox {
pub permissions: Arc<Mutex<MailboxPermissions>>,
pub exists: Arc<Mutex<LazyCountSet>>,
pub unseen: Arc<Mutex<LazyCountSet>>,
pub warm: Arc<Mutex<bool>>,
}
impl ImapMailbox {
pub fn imap_path(&self) -> &str {
&self.imap_path
}
/// Establish that mailbox contents have been fetched at least once during this execution
#[inline(always)]
pub fn set_warm(&self, new_value: bool) {
*self.warm.lock().unwrap() = new_value;
}
/// Mailbox contents have been fetched at least once during this execution
#[inline(always)]
pub fn is_warm(&self) -> bool {
*self.warm.lock().unwrap()
}
/// Mailbox contents have not been fetched at all during this execution
#[inline(always)]
pub fn is_cold(&self) -> bool {
!self.is_warm()
}
}
impl BackendMailbox for ImapMailbox {

View File

@ -244,6 +244,20 @@ pub async fn examine_updates(
uidvalidities.insert(mailbox_hash, select_response.uidvalidity);
}
}
if mailbox.is_cold() {
/* Mailbox hasn't been loaded yet */
if let Ok(mut exists_lck) = mailbox.exists.lock() {
exists_lck.clear();
exists_lck.set_not_yet_seen(select_response.exists);
}
if let Ok(mut unseen_lck) = mailbox.unseen.lock() {
unseen_lck.clear();
unseen_lck.set_not_yet_seen(select_response.unseen);
}
mailbox.set_warm(true);
return Ok(());
}
if debug!(select_response.recent > 0) {
/* UID SEARCH RECENT */
conn.send_command(b"UID SEARCH RECENT").await?;