fix: Prefetch messages in limited batches (#6915)

I have logs from a user where messages are prefetched for long minutes, and while it's not a problem
on its own, we can't rely that the connection overlives such a period, so make
`fetch_new_messages()` prefetch (and then actually download) messages in batches of 500 messages.
This commit is contained in:
iequidoo
2025-07-22 11:41:52 -03:00
committed by iequidoo
parent b9068b95b8
commit 481f5cae22
2 changed files with 44 additions and 19 deletions

View File

@@ -110,14 +110,16 @@ impl Session {
Ok(list)
}
/// Prefetch all messages greater than or equal to `uid_next`. Returns a list of fetch results
/// in the order of ascending delivery time to the server (INTERNALDATE).
/// Prefetch `n_uids` messages starting from `uid_next`. Returns a list of fetch results in the
/// order of ascending delivery time to the server (INTERNALDATE).
pub(crate) async fn prefetch(
&mut self,
uid_next: u32,
n_uids: u32,
) -> Result<Vec<(u32, async_imap::types::Fetch)>> {
let uid_last = uid_next.saturating_add(n_uids - 1);
// fetch messages with larger UID than the last one seen
let set = format!("{uid_next}:*");
let set = format!("{uid_next}:{uid_last}");
let mut list = self
.uid_fetch(set, PREFETCH_FLAGS)
.await
@@ -126,16 +128,7 @@ impl Session {
let mut msgs = BTreeMap::new();
while let Some(msg) = list.try_next().await? {
if let Some(msg_uid) = msg.uid {
// If the mailbox is not empty, results always include
// at least one UID, even if last_seen_uid+1 is past
// the last UID in the mailbox. It happens because
// uid:* is interpreted the same way as *:uid.
// See <https://tools.ietf.org/html/rfc3501#page-61> for
// standard reference. Therefore, sometimes we receive
// already seen messages and have to filter them out.
if msg_uid >= uid_next {
msgs.insert((msg.internal_date(), msg_uid), msg);
}
msgs.insert((msg.internal_date(), msg_uid), msg);
}
}