From 76c1c1a213fb35d882a82694da74b55b69d31c03 Mon Sep 17 00:00:00 2001 From: Manos Pitsidianakis Date: Sun, 29 Nov 2020 15:52:48 +0200 Subject: [PATCH] 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 --- melib/src/backends/imap.rs | 1 + melib/src/backends/imap/mailbox.rs | 19 +++++++++++++++++++ melib/src/backends/imap/watch.rs | 14 ++++++++++++++ 3 files changed, 34 insertions(+) diff --git a/melib/src/backends/imap.rs b/melib/src/backends/imap.rs index e3186a65..135ab90f 100644 --- a/melib/src/backends/imap.rs +++ b/melib/src/backends/imap.rs @@ -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; diff --git a/melib/src/backends/imap/mailbox.rs b/melib/src/backends/imap/mailbox.rs index 7461e814..baa918ca 100644 --- a/melib/src/backends/imap/mailbox.rs +++ b/melib/src/backends/imap/mailbox.rs @@ -43,12 +43,31 @@ pub struct ImapMailbox { pub permissions: Arc>, pub exists: Arc>, pub unseen: Arc>, + pub warm: Arc>, } 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 { diff --git a/melib/src/backends/imap/watch.rs b/melib/src/backends/imap/watch.rs index b521970d..fe7cd87c 100644 --- a/melib/src/backends/imap/watch.rs +++ b/melib/src/backends/imap/watch.rs @@ -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?;