refactor: use CancellationToken instead of a 1-message channel

This commit is contained in:
link2xt
2025-06-10 16:05:01 +00:00
committed by l
parent 7f6beeeecb
commit a8a7cec376

View File

@@ -10,6 +10,7 @@ use futures_lite::FutureExt;
use rand::Rng; use rand::Rng;
use tokio::sync::{oneshot, RwLock, RwLockWriteGuard}; use tokio::sync::{oneshot, RwLock, RwLockWriteGuard};
use tokio::task; use tokio::task;
use tokio_util::sync::CancellationToken;
use self::connectivity::ConnectivityStore; use self::connectivity::ConnectivityStore;
use crate::config::{self, Config}; use crate::config::{self, Config};
@@ -389,7 +390,7 @@ async fn inbox_loop(
info!(ctx, "Starting inbox loop."); info!(ctx, "Starting inbox loop.");
let ImapConnectionHandlers { let ImapConnectionHandlers {
mut connection, mut connection,
stop_receiver, stop_token,
} = inbox_handlers; } = inbox_handlers;
let ctx1 = ctx.clone(); let ctx1 = ctx.clone();
@@ -428,8 +429,8 @@ async fn inbox_loop(
} }
}; };
stop_receiver stop_token
.recv() .cancelled()
.map(|_| { .map(|_| {
info!(ctx, "Shutting down inbox loop."); info!(ctx, "Shutting down inbox loop.");
}) })
@@ -703,7 +704,7 @@ async fn simple_imap_loop(
info!(ctx, "Starting simple loop for {folder_meaning}."); info!(ctx, "Starting simple loop for {folder_meaning}.");
let ImapConnectionHandlers { let ImapConnectionHandlers {
mut connection, mut connection,
stop_receiver, stop_token,
} = inbox_handlers; } = inbox_handlers;
let ctx1 = ctx.clone(); let ctx1 = ctx.clone();
@@ -749,8 +750,8 @@ async fn simple_imap_loop(
} }
}; };
stop_receiver stop_token
.recv() .cancelled()
.map(|_| { .map(|_| {
info!(ctx, "Shutting down IMAP loop for {folder_meaning}."); info!(ctx, "Shutting down IMAP loop for {folder_meaning}.");
}) })
@@ -768,7 +769,7 @@ async fn smtp_loop(
info!(ctx, "Starting SMTP loop."); info!(ctx, "Starting SMTP loop.");
let SmtpConnectionHandlers { let SmtpConnectionHandlers {
mut connection, mut connection,
stop_receiver, stop_token,
idle_interrupt_receiver, idle_interrupt_receiver,
} = smtp_handlers; } = smtp_handlers;
@@ -836,8 +837,8 @@ async fn smtp_loop(
} }
}; };
stop_receiver stop_token
.recv() .cancelled()
.map(|_| { .map(|_| {
info!(ctx, "Shutting down SMTP loop."); info!(ctx, "Shutting down SMTP loop.");
}) })
@@ -982,9 +983,9 @@ impl Scheduler {
pub(crate) async fn stop(self, context: &Context) { pub(crate) async fn stop(self, context: &Context) {
// Send stop signals to tasks so they can shutdown cleanly. // Send stop signals to tasks so they can shutdown cleanly.
for b in self.boxes() { for b in self.boxes() {
b.conn_state.stop().await.log_err(context).ok(); b.conn_state.stop();
} }
self.smtp.stop().await.log_err(context).ok(); self.smtp.stop();
// Actually shutdown tasks. // Actually shutdown tasks.
let timeout_duration = std::time::Duration::from_secs(30); let timeout_duration = std::time::Duration::from_secs(30);
@@ -1014,8 +1015,8 @@ impl Scheduler {
/// Connection state logic shared between imap and smtp connections. /// Connection state logic shared between imap and smtp connections.
#[derive(Debug)] #[derive(Debug)]
struct ConnectionState { struct ConnectionState {
/// Channel to interrupt the whole connection. /// Cancellation token to interrupt the whole connection.
stop_sender: Sender<()>, stop_token: CancellationToken,
/// Channel to interrupt idle. /// Channel to interrupt idle.
idle_interrupt_sender: Sender<()>, idle_interrupt_sender: Sender<()>,
/// Mutex to pass connectivity info between IMAP/SMTP threads and the API /// Mutex to pass connectivity info between IMAP/SMTP threads and the API
@@ -1024,13 +1025,9 @@ struct ConnectionState {
impl ConnectionState { impl ConnectionState {
/// Shutdown this connection completely. /// Shutdown this connection completely.
async fn stop(&self) -> Result<()> { fn stop(&self) {
// Trigger shutdown of the run loop. // Trigger shutdown of the run loop.
self.stop_sender self.stop_token.cancel();
.send(())
.await
.context("failed to stop, missing receiver")?;
Ok(())
} }
fn interrupt(&self) { fn interrupt(&self) {
@@ -1046,17 +1043,17 @@ pub(crate) struct SmtpConnectionState {
impl SmtpConnectionState { impl SmtpConnectionState {
fn new() -> (Self, SmtpConnectionHandlers) { fn new() -> (Self, SmtpConnectionHandlers) {
let (stop_sender, stop_receiver) = channel::bounded(1); let stop_token = CancellationToken::new();
let (idle_interrupt_sender, idle_interrupt_receiver) = channel::bounded(1); let (idle_interrupt_sender, idle_interrupt_receiver) = channel::bounded(1);
let handlers = SmtpConnectionHandlers { let handlers = SmtpConnectionHandlers {
connection: Smtp::new(), connection: Smtp::new(),
stop_receiver, stop_token: stop_token.clone(),
idle_interrupt_receiver, idle_interrupt_receiver,
}; };
let state = ConnectionState { let state = ConnectionState {
stop_sender, stop_token,
idle_interrupt_sender, idle_interrupt_sender,
connectivity: handlers.connection.connectivity.clone(), connectivity: handlers.connection.connectivity.clone(),
}; };
@@ -1072,15 +1069,14 @@ impl SmtpConnectionState {
} }
/// Shutdown this connection completely. /// Shutdown this connection completely.
async fn stop(&self) -> Result<()> { fn stop(&self) {
self.state.stop().await?; self.state.stop();
Ok(())
} }
} }
struct SmtpConnectionHandlers { struct SmtpConnectionHandlers {
connection: Smtp, connection: Smtp,
stop_receiver: Receiver<()>, stop_token: CancellationToken,
idle_interrupt_receiver: Receiver<()>, idle_interrupt_receiver: Receiver<()>,
} }
@@ -1092,16 +1088,16 @@ pub(crate) struct ImapConnectionState {
impl ImapConnectionState { impl ImapConnectionState {
/// Construct a new connection. /// Construct a new connection.
async fn new(context: &Context) -> Result<(Self, ImapConnectionHandlers)> { async fn new(context: &Context) -> Result<(Self, ImapConnectionHandlers)> {
let (stop_sender, stop_receiver) = channel::bounded(1); let stop_token = CancellationToken::new();
let (idle_interrupt_sender, idle_interrupt_receiver) = channel::bounded(1); let (idle_interrupt_sender, idle_interrupt_receiver) = channel::bounded(1);
let handlers = ImapConnectionHandlers { let handlers = ImapConnectionHandlers {
connection: Imap::new_configured(context, idle_interrupt_receiver).await?, connection: Imap::new_configured(context, idle_interrupt_receiver).await?,
stop_receiver, stop_token: stop_token.clone(),
}; };
let state = ConnectionState { let state = ConnectionState {
stop_sender, stop_token,
idle_interrupt_sender, idle_interrupt_sender,
connectivity: handlers.connection.connectivity.clone(), connectivity: handlers.connection.connectivity.clone(),
}; };
@@ -1117,14 +1113,13 @@ impl ImapConnectionState {
} }
/// Shutdown this connection completely. /// Shutdown this connection completely.
async fn stop(&self) -> Result<()> { fn stop(&self) {
self.state.stop().await?; self.state.stop();
Ok(())
} }
} }
#[derive(Debug)] #[derive(Debug)]
struct ImapConnectionHandlers { struct ImapConnectionHandlers {
connection: Imap, connection: Imap,
stop_receiver: Receiver<()>, stop_token: CancellationToken,
} }