Skip to content

Commit 7fef812

Browse files
committed
refactor(imap): move resync request from Context to Imap
For multiple transports we will need to run multiple IMAP clients in parallel. UID validity change detected by one IMAP client should not result in UID resync for another IMAP client.
1 parent 5f174ce commit 7fef812

File tree

6 files changed

+21
-27
lines changed

6 files changed

+21
-27
lines changed

src/configure.rs

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -565,14 +565,6 @@ async fn configure(ctx: &Context, param: &EnteredLoginParam) -> Result<Option<&'
565565

566566
progress!(ctx, 910);
567567

568-
if let Some(configured_addr) = ctx.get_config(Config::ConfiguredAddr).await? {
569-
if configured_addr != param.addr {
570-
// Switched account, all server UIDs we know are invalid
571-
info!(ctx, "Scheduling resync because the address has changed.");
572-
ctx.schedule_resync().await?;
573-
}
574-
}
575-
576568
let provider = configured_param.provider;
577569
configured_param
578570
.save_to_transports_table(ctx, param)

src/context.rs

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use std::collections::{BTreeMap, HashMap};
44
use std::ffi::OsString;
55
use std::ops::Deref;
66
use std::path::{Path, PathBuf};
7-
use std::sync::atomic::{AtomicBool, Ordering};
7+
use std::sync::atomic::AtomicBool;
88
use std::sync::{Arc, OnceLock};
99
use std::time::Duration;
1010

@@ -243,9 +243,6 @@ pub struct InnerContext {
243243
/// Set to `None` if quota was never tried to load.
244244
pub(crate) quota: RwLock<Option<QuotaInfo>>,
245245

246-
/// IMAP UID resync request.
247-
pub(crate) resync_request: AtomicBool,
248-
249246
/// Notify about new messages.
250247
///
251248
/// This causes [`Context::wait_next_msgs`] to wake up.
@@ -457,7 +454,6 @@ impl Context {
457454
scheduler: SchedulerState::new(),
458455
ratelimit: RwLock::new(Ratelimit::new(Duration::new(60, 0), 6.0)), // Allow at least 1 message every 10 seconds + a burst of 6.
459456
quota: RwLock::new(None),
460-
resync_request: AtomicBool::new(false),
461457
new_msgs_notify,
462458
server_id: RwLock::new(None),
463459
metadata: RwLock::new(None),
@@ -616,12 +612,6 @@ impl Context {
616612
Ok(())
617613
}
618614

619-
pub(crate) async fn schedule_resync(&self) -> Result<()> {
620-
self.resync_request.store(true, Ordering::Relaxed);
621-
self.scheduler.interrupt_inbox().await;
622-
Ok(())
623-
}
624-
625615
/// Returns a reference to the underlying SQL instance.
626616
///
627617
/// Warning: this is only here for testing, not part of the public API.

src/imap.rs

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,12 @@ pub(crate) struct Imap {
104104
/// immediately after logging in or returning an error in response to LOGIN command
105105
/// due to internal server error.
106106
ratelimit: Ratelimit,
107+
108+
/// IMAP UID resync request sender.
109+
pub(crate) resync_request_sender: async_channel::Sender<()>,
110+
111+
/// IMAP UID resync request receiver.
112+
pub(crate) resync_request_receiver: async_channel::Receiver<()>,
107113
}
108114

109115
#[derive(Debug)]
@@ -254,6 +260,7 @@ impl Imap {
254260
oauth2: bool,
255261
idle_interrupt_receiver: Receiver<()>,
256262
) -> Self {
263+
let (resync_request_sender, resync_request_receiver) = async_channel::bounded(1);
257264
Imap {
258265
idle_interrupt_receiver,
259266
addr: addr.to_string(),
@@ -268,6 +275,8 @@ impl Imap {
268275
conn_backoff_ms: 0,
269276
// 1 connection per minute + a burst of 2.
270277
ratelimit: Ratelimit::new(Duration::new(120, 0), 2.0),
278+
resync_request_sender,
279+
resync_request_receiver,
271280
}
272281
}
273282

@@ -392,6 +401,7 @@ impl Imap {
392401
match login_res {
393402
Ok(mut session) => {
394403
let capabilities = determine_capabilities(&mut session).await?;
404+
let resync_request_sender = self.resync_request_sender.clone();
395405

396406
let session = if capabilities.can_compress {
397407
info!(context, "Enabling IMAP compression.");
@@ -402,9 +412,9 @@ impl Imap {
402412
})
403413
.await
404414
.context("Failed to enable IMAP compression")?;
405-
Session::new(compressed_session, capabilities)
415+
Session::new(compressed_session, capabilities, resync_request_sender)
406416
} else {
407-
Session::new(session, capabilities)
417+
Session::new(session, capabilities, resync_request_sender)
408418
};
409419

410420
// Store server ID in the context to display in account info.

src/imap/select_folder.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -206,7 +206,7 @@ impl ImapSession {
206206
"The server illegally decreased the uid_next of folder {folder:?} from {old_uid_next} to {new_uid_next} without changing validity ({new_uid_validity}), resyncing UIDs...",
207207
);
208208
set_uid_next(context, folder, new_uid_next).await?;
209-
context.schedule_resync().await?;
209+
self.resync_request_sender.try_send(()).ok();
210210
}
211211

212212
// If UIDNEXT changed, there are new emails.
@@ -243,7 +243,7 @@ impl ImapSession {
243243
.await?;
244244

245245
if old_uid_validity != 0 || old_uid_next != 0 {
246-
context.schedule_resync().await?;
246+
self.resync_request_sender.try_send(()).ok();
247247
}
248248
info!(
249249
context,

src/imap/session.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,8 @@ pub(crate) struct Session {
4848
///
4949
/// Should be false if no folder is currently selected.
5050
pub new_mail: bool,
51+
52+
pub resync_request_sender: async_channel::Sender<()>,
5153
}
5254

5355
impl Deref for Session {
@@ -68,6 +70,7 @@ impl Session {
6870
pub(crate) fn new(
6971
inner: ImapSession<Box<dyn SessionStream>>,
7072
capabilities: Capabilities,
73+
resync_request_sender: async_channel::Sender<()>,
7174
) -> Self {
7275
Self {
7376
inner,
@@ -77,6 +80,7 @@ impl Session {
7780
selected_folder_needs_expunge: false,
7881
last_full_folder_scan: Mutex::new(None),
7982
new_mail: false,
83+
resync_request_sender,
8084
}
8185
}
8286

src/scheduler.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
use std::cmp;
22
use std::iter::{self, once};
33
use std::num::NonZeroUsize;
4-
use std::sync::atomic::Ordering;
54

65
use anyhow::{Context as _, Error, Result, bail};
76
use async_channel::{self as channel, Receiver, Sender};
@@ -481,11 +480,10 @@ async fn inbox_fetch_idle(ctx: &Context, imap: &mut Imap, mut session: Session)
481480
}
482481
}
483482

484-
let resync_requested = ctx.resync_request.swap(false, Ordering::Relaxed);
485-
if resync_requested {
483+
if let Ok(()) = imap.resync_request_receiver.try_recv() {
486484
if let Err(err) = session.resync_folders(ctx).await {
487485
warn!(ctx, "Failed to resync folders: {:#}.", err);
488-
ctx.resync_request.store(true, Ordering::Relaxed);
486+
imap.resync_request_sender.try_send(()).ok();
489487
}
490488
}
491489

0 commit comments

Comments
 (0)