refactor: rename automatic_relay_management to autorelay

"automatic_relay_management" is a long unwiedly name with no UI using the mode yet,
so let's rename it to something more succinct: autorelay
This commit is contained in:
holger krekel
2026-08-27 16:52:38 +02:00
parent 96f051a2f0
commit a344cab046
8 changed files with 50 additions and 66 deletions
@@ -1,3 +1,18 @@
//! # Automatic relay handling (experimental, still in development)
//!
//! Chatmail relays create an account on first login,
//! so a profile can add further transports on its own without user interaction.
//! Candidate hosts come from the `relay_candidates` table,
//! which migrations seed with a list of known chatmail relays.
//!
//! Status of implementation:
//! Additions are attempted right before going into IMAP IDLE,
//! i.e. only while connected and with nothing more important to do,
//! and only if a UI opted in via [`Config::Autorelay`].
//! Once a profile has reached `NUM_TRANSPORTS_TARGET` transports,
//! [`Config::AutorelayFinished`] is set and nothing is ever added again,
//! so deleting a transport later does not pull in a replacement.
use std::pin::Pin; use std::pin::Pin;
use anyhow::Result; use anyhow::Result;
@@ -46,9 +61,7 @@ async fn maybe_add_additional_relays_inner(context: &Context, skip_network: bool
// Housekeeping or automatic relay management is already running in another thread, do nothing. // Housekeeping or automatic relay management is already running in another thread, do nothing.
return Ok(false); return Ok(false);
}; };
let last_timestamp = context let last_timestamp = context.get_config_i64(Config::LastAutorelay).await?;
.get_config_i64(Config::LastAutomaticRelayManagement)
.await?;
if last_timestamp > now { if last_timestamp > now {
warn!( warn!(
context, context,
@@ -57,22 +70,16 @@ async fn maybe_add_additional_relays_inner(context: &Context, skip_network: bool
} else if last_timestamp > now.saturating_sub(AUTOMATIC_ADDITION_DEBOUNCE_SECONDS) { } else if last_timestamp > now.saturating_sub(AUTOMATIC_ADDITION_DEBOUNCE_SECONDS) {
return Ok(false); return Ok(false);
} }
if !context if !context.get_config_bool(Config::Autorelay).await? {
.get_config_bool(Config::AutomaticRelayManagement)
.await?
{
return Ok(false); return Ok(false);
} }
if context if context.get_config_bool(Config::AutorelayFinished).await? {
.get_config_bool(Config::AutomaticRelayManagementFinished)
.await?
{
return Ok(false); return Ok(false);
} }
// Set the config at the beginning to avoid endless loops. // Set the config at the beginning to avoid endless loops.
// Race conditions are not a concern because we locked the mutex. // Race conditions are not a concern because we locked the mutex.
context context
.set_config_internal(Config::LastAutomaticRelayManagement, Some(&now.to_string())) .set_config_internal(Config::LastAutorelay, Some(&now.to_string()))
.await?; .await?;
let mut relay_added = false; let mut relay_added = false;
@@ -80,10 +87,7 @@ async fn maybe_add_additional_relays_inner(context: &Context, skip_network: bool
for _ in 0..NUM_TRANSPORTS_TARGET { for _ in 0..NUM_TRANSPORTS_TARGET {
if context.count_transports().await? >= NUM_TRANSPORTS_TARGET { if context.count_transports().await? >= NUM_TRANSPORTS_TARGET {
context context
.set_config_internal( .set_config_internal(Config::AutorelayFinished, config::from_bool(true))
Config::AutomaticRelayManagementFinished,
config::from_bool(true),
)
.await?; .await?;
return Ok(relay_added); return Ok(relay_added);
@@ -175,4 +179,4 @@ pub(crate) fn login_param_from_host(host: &str) -> EnteredLoginParam {
} }
#[cfg(test)] #[cfg(test)]
mod automatic_relay_management_tests; mod autorelay_tests;
@@ -73,12 +73,9 @@ async fn test_load_relay_candidates_multiple() -> Result<()> {
Ok(()) Ok(())
} }
async fn assert_automatic_relay_management_does_nothing(t: &TestContext) { async fn assert_autorelay_does_nothing(t: &TestContext) {
let transports_before = t.count_transports().await.unwrap(); let transports_before = t.count_transports().await.unwrap();
let config_before = t let config_before = t.get_config_i64(Config::LastAutorelay).await.unwrap();
.get_config_i64(Config::LastAutomaticRelayManagement)
.await
.unwrap();
let skip_network = false; // No need to skip network, nothing is supposed to happen let skip_network = false; // No need to skip network, nothing is supposed to happen
let relay_added = maybe_add_additional_relays_inner(t, skip_network) let relay_added = maybe_add_additional_relays_inner(t, skip_network)
@@ -86,10 +83,7 @@ async fn assert_automatic_relay_management_does_nothing(t: &TestContext) {
.unwrap(); .unwrap();
assert_eq!(relay_added, false); assert_eq!(relay_added, false);
let config_after = t let config_after = t.get_config_i64(Config::LastAutorelay).await.unwrap();
.get_config_i64(Config::LastAutomaticRelayManagement)
.await
.unwrap();
let transports_after = t.count_transports().await.unwrap(); let transports_after = t.count_transports().await.unwrap();
assert_eq!(config_after, config_before); assert_eq!(config_after, config_before);
@@ -105,7 +99,7 @@ async fn test_maybe_add_additional_relays_mutex_held() -> Result<()> {
// already running housekeeping or relay management. // already running housekeeping or relay management.
let _lock = t.background_task_mutex.lock().await; let _lock = t.background_task_mutex.lock().await;
assert_automatic_relay_management_does_nothing(t).await; assert_autorelay_does_nothing(t).await;
Ok(()) Ok(())
} }
@@ -117,13 +111,10 @@ async fn test_maybe_add_additional_relays_debounce() -> Result<()> {
let some_seconds_ago = time() - 10; let some_seconds_ago = time() - 10;
// Pretend automatic relay management just ran. // Pretend automatic relay management just ran.
t.set_config_internal( t.set_config_internal(Config::LastAutorelay, Some(&some_seconds_ago.to_string()))
Config::LastAutomaticRelayManagement, .await?;
Some(&some_seconds_ago.to_string()),
)
.await?;
assert_automatic_relay_management_does_nothing(t).await; assert_autorelay_does_nothing(t).await;
Ok(()) Ok(())
} }
@@ -132,7 +123,7 @@ async fn test_maybe_add_additional_relays_debounce() -> Result<()> {
async fn test_maybe_add_additional_relays_disabled() { async fn test_maybe_add_additional_relays_disabled() {
// By default, automatic relay management is disabled: // By default, automatic relay management is disabled:
let t = &TestContext::new_alice().await; let t = &TestContext::new_alice().await;
assert_automatic_relay_management_does_nothing(t).await; assert_autorelay_does_nothing(t).await;
} }
/// Runs maybe_add_additional_relays_inner(), then deletes one of the transports. /// Runs maybe_add_additional_relays_inner(), then deletes one of the transports.
@@ -158,11 +149,8 @@ async fn test_maybe_add_additional_relays_does_nothing_after_finishing_once() ->
let transports_count = t.count_transports().await?; let transports_count = t.count_transports().await?;
assert_eq!(transports_count, NUM_TRANSPORTS_TARGET - 1); assert_eq!(transports_count, NUM_TRANSPORTS_TARGET - 1);
assert!( assert!(t.get_config_bool(Config::AutorelayFinished).await?);
t.get_config_bool(Config::AutomaticRelayManagementFinished) assert_autorelay_does_nothing(t).await;
.await?
);
assert_automatic_relay_management_does_nothing(t).await;
Ok(()) Ok(())
} }
@@ -187,9 +175,7 @@ async fn test_maybe_add_additional_relays_add_one() -> Result<()> {
let relay_added = maybe_add_additional_relays_inner(t, skip_network).await?; let relay_added = maybe_add_additional_relays_inner(t, skip_network).await?;
assert!(relay_added); assert!(relay_added);
let config_after = t let config_after = t.get_config_i64(Config::LastAutorelay).await?;
.get_config_i64(Config::LastAutomaticRelayManagement)
.await?;
assert!(config_after >= now); assert!(config_after >= now);
let transports_after = t.count_transports().await?; let transports_after = t.count_transports().await?;
@@ -218,9 +204,7 @@ async fn test_maybe_add_additional_relays_add_multiple() -> Result<()> {
let relay_added = maybe_add_additional_relays_inner(t, skip_network).await?; let relay_added = maybe_add_additional_relays_inner(t, skip_network).await?;
assert!(relay_added); assert!(relay_added);
let config_after = t let config_after = t.get_config_i64(Config::LastAutorelay).await?;
.get_config_i64(Config::LastAutomaticRelayManagement)
.await?;
assert!(config_after >= now); assert!(config_after >= now);
let transports_after = t.count_transports().await?; let transports_after = t.count_transports().await?;
@@ -253,9 +237,7 @@ async fn test_maybe_add_additional_relays_failure() -> Result<()> {
assert_eq!(relay_added, false); assert_eq!(relay_added, false);
// The config is still updated: // The config is still updated:
let config_after = t let config_after = t.get_config_i64(Config::LastAutorelay).await?;
.get_config_i64(Config::LastAutomaticRelayManagement)
.await?;
assert!(config_after >= now); assert!(config_after >= now);
let transports_after = t.count_transports().await?; let transports_after = t.count_transports().await?;
@@ -286,7 +268,7 @@ async fn test_maybe_add_additional_relays_failure() -> Result<()> {
async fn enable_config(context: &Context) { async fn enable_config(context: &Context) {
context context
.set_config_bool(Config::AutomaticRelayManagement, true) .set_config_bool(Config::Autorelay, true)
.await .await
.unwrap(); .unwrap();
} }
+3 -3
View File
@@ -353,13 +353,13 @@ pub enum Config {
LastCantDecryptOutgoingMsgs, LastCantDecryptOutgoingMsgs,
/// Timestamp of the last time automatic relay management was run /// Timestamp of the last time automatic relay management was run
LastAutomaticRelayManagement, LastAutorelay,
/// Whether to automatically add/remove transports /// Whether to automatically add/remove transports
AutomaticRelayManagement, Autorelay,
/// Whether automatic relay management successfully added the desired number of relays /// Whether automatic relay management successfully added the desired number of relays
AutomaticRelayManagementFinished, AutorelayFinished,
/// Whether to avoid using IMAP IDLE even if the server supports it. /// Whether to avoid using IMAP IDLE even if the server supports it.
/// ///
+1 -1
View File
@@ -749,7 +749,7 @@ mod tests {
use crate::tools::SystemTime; use crate::tools::SystemTime;
use super::*; use super::*;
use crate::automatic_relay_management::login_param_from_host; use crate::autorelay::login_param_from_host;
use crate::config::Config; use crate::config::Config;
use crate::login_param::EnteredImapLoginParam; use crate::login_param::EnteredImapLoginParam;
use crate::sql::update_transport_last_rcvd_timestamp; use crate::sql::update_transport_last_rcvd_timestamp;
+6 -8
View File
@@ -1047,20 +1047,18 @@ impl Context {
.to_string(), .to_string(),
); );
res.insert( res.insert(
"last_automatic_relay_management", "last_autorelay",
self.get_config_i64(Config::LastAutomaticRelayManagement) self.get_config_i64(Config::LastAutorelay)
.await? .await?
.to_string(), .to_string(),
); );
res.insert( res.insert(
"automatic_relay_management", "autorelay",
self.get_config_bool(Config::AutomaticRelayManagement) self.get_config_bool(Config::Autorelay).await?.to_string(),
.await?
.to_string(),
); );
res.insert( res.insert(
"automatic_relay_management_finished", "autorelay_finished",
self.get_config_bool(Config::AutomaticRelayManagementFinished) self.get_config_bool(Config::AutorelayFinished)
.await? .await?
.to_string(), .to_string(),
); );
+3 -3
View File
@@ -53,9 +53,9 @@ impl Session {
// we try to add additional relays right before going into IDLE mode, // we try to add additional relays right before going into IDLE mode,
// because we are connected and don't have anything important to do. // because we are connected and don't have anything important to do.
tokio::task::spawn( tokio::task::spawn(crate::autorelay::maybe_add_additional_relays(
crate::automatic_relay_management::maybe_add_additional_relays(context.clone()), context.clone(),
); ));
let mut handle = self.inner.idle(); let mut handle = self.inner.idle();
handle handle
+1 -1
View File
@@ -55,7 +55,7 @@ pub use events::*;
mod aheader; mod aheader;
pub mod appversions; pub mod appversions;
mod automatic_relay_management; mod autorelay;
pub mod blob; pub mod blob;
pub mod calls; pub mod calls;
pub mod chat; pub mod chat;
+1 -1
View File
@@ -11,7 +11,7 @@ use deltachat_contact_tools::{ContactAddress, addr_normalize, may_be_valid_addr}
use percent_encoding::{NON_ALPHANUMERIC, percent_decode_str, percent_encode}; use percent_encoding::{NON_ALPHANUMERIC, percent_decode_str, percent_encode};
use serde::Deserialize; use serde::Deserialize;
use crate::automatic_relay_management::login_param_from_host; use crate::autorelay::login_param_from_host;
use crate::config::Config; use crate::config::Config;
use crate::contact::{Contact, ContactId, Origin}; use crate::contact::{Contact, ContactId, Origin};
use crate::context::Context; use crate::context::Context;