From b5f2c747e060bd11b6f2540c8f0f1dddfd2122dd Mon Sep 17 00:00:00 2001 From: iequidoo Date: Mon, 12 Feb 2024 14:22:23 -0300 Subject: [PATCH] feat: Context::set_config(): Restart IO scheduler if needed (#5111) Restart the IO scheduler if needed to make the new config value effective (for `MvboxMove, OnlyFetchMvbox, SentboxWatch` currently). Also add `set_config_internal()` which doesn't affect running the IO scheduler. The reason is that `Scheduler::start()` itself calls `set_config()`, although not for the mentioned keys, but still, and also Rust complains about recursive async calls. --- deltachat-ffi/deltachat.h | 5 +- deltachat-jsonrpc/src/api.rs | 11 +--- deltachat-repl/src/main.rs | 2 +- python/tests/test_1_online.py | 15 ++++++ src/authres.rs | 2 +- src/chat.rs | 8 ++- src/config.rs | 97 ++++++++++++++++++++++++----------- src/configure.rs | 11 ++-- src/contact.rs | 8 +-- src/context.rs | 2 +- src/imap.rs | 11 ++-- src/imap/scan_folders.rs | 2 +- src/message.rs | 6 ++- src/qr.rs | 10 ++-- src/qr/dclogin_scheme.rs | 44 +++++++++++----- src/quota.rs | 10 ++-- src/receive_imf.rs | 5 +- src/scheduler.rs | 12 +++-- src/sql.rs | 10 ++-- src/sql/migrations.rs | 2 +- 20 files changed, 180 insertions(+), 93 deletions(-) diff --git a/deltachat-ffi/deltachat.h b/deltachat-ffi/deltachat.h index f71010662..683081151 100644 --- a/deltachat-ffi/deltachat.h +++ b/deltachat-ffi/deltachat.h @@ -423,19 +423,16 @@ char* dc_get_blobdir (const dc_context_t* context); * Sending messages to self is needed for a proper multi-account setup, * however, on the other hand, may lead to unwanted notifications in non-delta clients. * - `sentbox_watch`= 1=watch `Sent`-folder for changes, - * 0=do not watch the `Sent`-folder (default), - * changes require restarting IO by calling dc_stop_io() and then dc_start_io(). + * 0=do not watch the `Sent`-folder (default). * - `mvbox_move` = 1=detect chat messages, * move them to the `DeltaChat` folder, * and watch the `DeltaChat` folder for updates (default), * 0=do not move chat-messages - * changes require restarting IO by calling dc_stop_io() and then dc_start_io(). * - `only_fetch_mvbox` = 1=Do not fetch messages from folders other than the * `DeltaChat` folder. Messages will still be fetched from the * spam folder and `sendbox_watch` will also still be respected * if enabled. * 0=watch all folders normally (default) - * changes require restarting IO by calling dc_stop_io() and then dc_start_io(). * - `show_emails` = DC_SHOW_EMAILS_OFF (0)= * show direct replies to chats only, * DC_SHOW_EMAILS_ACCEPTED_CONTACTS (1)= diff --git a/deltachat-jsonrpc/src/api.rs b/deltachat-jsonrpc/src/api.rs index fa0f6bed7..4d100b27d 100644 --- a/deltachat-jsonrpc/src/api.rs +++ b/deltachat-jsonrpc/src/api.rs @@ -251,7 +251,7 @@ impl CommandApi { /// Starts background tasks for a single account. async fn start_io(&self, account_id: u32) -> Result<()> { - let mut ctx = self.get_context(account_id).await?; + let ctx = self.get_context(account_id).await?; ctx.start_io().await; Ok(()) } @@ -402,7 +402,7 @@ impl CommandApi { /// Configures this account with the currently set parameters. /// Setup the credential config before calling this. async fn configure(&self, account_id: u32) -> Result<()> { - let mut ctx = self.get_context(account_id).await?; + let ctx = self.get_context(account_id).await?; ctx.stop_io().await; let result = ctx.configure().await; if result.is_err() { @@ -2125,13 +2125,6 @@ async fn set_config( value, ) .await?; - - match key { - "sentbox_watch" | "mvbox_move" | "only_fetch_mvbox" => { - ctx.restart_io_if_running().await; - } - _ => {} - } } Ok(()) } diff --git a/deltachat-repl/src/main.rs b/deltachat-repl/src/main.rs index 49d2b840e..1151925a8 100644 --- a/deltachat-repl/src/main.rs +++ b/deltachat-repl/src/main.rs @@ -401,7 +401,7 @@ enum ExitResult { async fn handle_cmd( line: &str, - mut ctx: Context, + ctx: Context, selected_chat: &mut ChatId, ) -> Result { let mut args = line.splitn(2, ' '); diff --git a/python/tests/test_1_online.py b/python/tests/test_1_online.py index ac0fde685..2a4f1f63c 100644 --- a/python/tests/test_1_online.py +++ b/python/tests/test_1_online.py @@ -382,6 +382,21 @@ def test_webxdc_download_on_demand(acfactory, data, lp): assert msgs_changed_event.data2 == 0 +def test_enable_mvbox_move(acfactory, lp): + (ac1,) = acfactory.get_online_accounts(1) + + lp.sec("ac2: start without mvbox thread") + ac2 = acfactory.new_online_configuring_account(mvbox_move=False) + acfactory.bring_accounts_online() + + lp.sec("ac2: configuring mvbox") + ac2.set_config("mvbox_move", "1") + + lp.sec("ac1: send message and wait for ac2 to receive it") + acfactory.get_accepted_chat(ac1, ac2).send_text("message1") + assert ac2._evtracker.wait_next_incoming_message().text == "message1" + + def test_mvbox_sentbox_threads(acfactory, lp): lp.sec("ac1: start with mvbox thread") ac1 = acfactory.new_online_configuring_account(mvbox_move=True, sentbox_watch=True) diff --git a/src/authres.rs b/src/authres.rs index 2192bfbb5..ef8fe4fc8 100644 --- a/src/authres.rs +++ b/src/authres.rs @@ -216,7 +216,7 @@ async fn update_authservid_candidates( if old_ids != new_ids { let new_config = new_ids.into_iter().collect::>().join(" "); context - .set_config(Config::AuthservIdCandidates, Some(&new_config)) + .set_config_internal(Config::AuthservIdCandidates, Some(&new_config)) .await?; // Updating the authservid candidates may mean that we now consider // emails as "failed" which "passed" previously, so we need to diff --git a/src/chat.rs b/src/chat.rs index b49e1bcc0..6ff2f6282 100644 --- a/src/chat.rs +++ b/src/chat.rs @@ -783,7 +783,9 @@ impl ChatId { context.emit_msgs_changed_without_ids(); - context.set_config(Config::LastHousekeeping, None).await?; + context + .set_config_internal(Config::LastHousekeeping, None) + .await?; context.scheduler.interrupt_inbox().await; if chat.is_self_talk() { @@ -4266,7 +4268,9 @@ pub(crate) async fn delete_and_reset_all_device_msgs(context: &Context) -> Resul (), ) .await?; - context.set_config(Config::QuotaExceeding, None).await?; + context + .set_config_internal(Config::QuotaExceeding, None) + .await?; Ok(()) } diff --git a/src/config.rs b/src/config.rs index a99902bc3..856944aa0 100644 --- a/src/config.rs +++ b/src/config.rs @@ -367,11 +367,23 @@ impl Config { /// multiple users are sharing an account. Another example is `Self::SyncMsgs` itself which /// mustn't be controlled by other devices. pub(crate) fn is_synced(&self) -> bool { + // We don't restart IO from the synchronisation code, so this is to be on the safe side. + if self.needs_io_restart() { + return false; + } matches!( self, Self::Displayname | Self::MdnsEnabled | Self::ShowEmails ) } + + /// Whether the config option needs an IO scheduler restart to take effect. + pub(crate) fn needs_io_restart(&self) -> bool { + matches!( + self, + Config::MvboxMove | Config::OnlyFetchMvbox | Config::SentboxWatch + ) + } } impl Context { @@ -491,10 +503,50 @@ impl Context { } } - /// Set the given config key. - /// If `None` is passed as a value the value is cleared and set to the default if there is one. + fn check_config(key: Config, value: Option<&str>) -> Result<()> { + match key { + Config::Socks5Enabled + | Config::BccSelf + | Config::E2eeEnabled + | Config::MdnsEnabled + | Config::SentboxWatch + | Config::MvboxMove + | Config::OnlyFetchMvbox + | Config::FetchExistingMsgs + | Config::DeleteToTrash + | Config::SaveMimeHeaders + | Config::Configured + | Config::Bot + | Config::NotifyAboutWrongPw + | Config::SyncMsgs + | Config::SignUnencrypted + | Config::DisableIdle => { + ensure!( + matches!(value, None | Some("0") | Some("1")), + "Boolean value must be either 0 or 1" + ); + } + _ => (), + } + Ok(()) + } + + /// Set the given config key and make it effective. + /// This may restart the IO scheduler. If `None` is passed as a value the value is cleared and + /// set to the default if there is one. pub async fn set_config(&self, key: Config, value: Option<&str>) -> Result<()> { - self.set_config_ex(key.is_synced().into(), key, value).await + Self::check_config(key, value)?; + + let _pause = match key.needs_io_restart() { + true => self.scheduler.pause(self.clone()).await?, + _ => Default::default(), + }; + self.set_config_internal(key, value).await?; + Ok(()) + } + + pub(crate) async fn set_config_internal(&self, key: Config, value: Option<&str>) -> Result<()> { + self.set_config_ex(Sync, key, value).await } pub(crate) async fn set_config_ex( @@ -503,7 +555,10 @@ impl Context { key: Config, mut value: Option<&str>, ) -> Result<()> { + Self::check_config(key, value)?; + let sync = sync == Sync && key.is_synced(); let better_value; + match key { Config::Selfavatar => { self.sql @@ -536,28 +591,6 @@ impl Context { } self.sql.set_raw_config(key.as_ref(), value).await?; } - Config::Socks5Enabled - | Config::BccSelf - | Config::E2eeEnabled - | Config::MdnsEnabled - | Config::SentboxWatch - | Config::MvboxMove - | Config::OnlyFetchMvbox - | Config::FetchExistingMsgs - | Config::DeleteToTrash - | Config::SaveMimeHeaders - | Config::Configured - | Config::Bot - | Config::NotifyAboutWrongPw - | Config::SyncMsgs - | Config::SignUnencrypted - | Config::DisableIdle => { - ensure!( - matches!(value, None | Some("0") | Some("1")), - "Boolean value must be either 0 or 1" - ); - self.sql.set_raw_config(key.as_ref(), value).await?; - } Config::Addr => { self.sql .set_raw_config(key.as_ref(), value.map(|s| s.to_lowercase()).as_deref()) @@ -570,7 +603,7 @@ impl Context { if key.is_synced() { self.emit_event(EventType::ConfigSynced { key }); } - if sync != Sync { + if !sync { return Ok(()); } let Some(val) = value else { @@ -597,8 +630,7 @@ impl Context { /// Set the given config to a boolean value. pub async fn set_config_bool(&self, key: Config, value: bool) -> Result<()> { - self.set_config(key, if value { Some("1") } else { Some("0") }) - .await?; + self.set_config(key, from_bool(value)).await?; Ok(()) } @@ -618,6 +650,11 @@ impl Context { } } +/// Returns a value for use in `Context::set_config_*()` for the given `bool`. +pub(crate) fn from_bool(val: bool) -> Option<&'static str> { + Some(if val { "1" } else { "0" }) +} + // Separate impl block for self address handling impl Context { /// Determine whether the specified addr maps to the/a self addr. @@ -644,13 +681,13 @@ impl Context { let mut secondary_addrs = self.get_all_self_addrs().await?; // never store a primary address also as a secondary secondary_addrs.retain(|a| !addr_cmp(a, primary_new)); - self.set_config( + self.set_config_internal( Config::SecondaryAddrs, Some(secondary_addrs.join(" ").as_str()), ) .await?; - self.set_config(Config::ConfiguredAddr, Some(primary_new)) + self.set_config_internal(Config::ConfiguredAddr, Some(primary_new)) .await?; Ok(()) diff --git a/src/configure.rs b/src/configure.rs index 7f85552c4..8908bfb7d 100644 --- a/src/configure.rs +++ b/src/configure.rs @@ -22,7 +22,7 @@ use percent_encoding::{utf8_percent_encode, NON_ALPHANUMERIC}; use server_params::{expand_param_vector, ServerParams}; use tokio::task; -use crate::config::Config; +use crate::config::{self, Config}; use crate::contact::addr_cmp; use crate::context::Context; use crate::imap::Imap; @@ -112,12 +112,13 @@ impl Context { let mut param = LoginParam::load_candidate_params(self).await?; let old_addr = self.get_config(Config::ConfiguredAddr).await?; let success = configure(self, &mut param).await; - self.set_config(Config::NotifyAboutWrongPw, None).await?; + self.set_config_internal(Config::NotifyAboutWrongPw, None) + .await?; on_configure_completed(self, param, old_addr).await?; success?; - self.set_config(Config::NotifyAboutWrongPw, Some("1")) + self.set_config_internal(Config::NotifyAboutWrongPw, Some("1")) .await?; Ok(()) } @@ -473,7 +474,7 @@ async fn configure(ctx: &Context, param: &mut LoginParam) -> Result<()> { // the trailing underscore is correct param.save_as_configured_params(ctx).await?; - ctx.set_config(Config::ConfiguredTimestamp, Some(&time().to_string())) + ctx.set_config_internal(Config::ConfiguredTimestamp, Some(&time().to_string())) .await?; progress!(ctx, 920); @@ -481,7 +482,7 @@ async fn configure(ctx: &Context, param: &mut LoginParam) -> Result<()> { e2ee::ensure_secret_key_exists(ctx).await?; info!(ctx, "key generation completed"); - ctx.set_config_bool(Config::FetchedExistingMsgs, false) + ctx.set_config_internal(Config::FetchedExistingMsgs, config::from_bool(false)) .await?; ctx.scheduler.interrupt_inbox().await; diff --git a/src/contact.rs b/src/contact.rs index 836a46003..bd7930b9e 100644 --- a/src/contact.rs +++ b/src/contact.rs @@ -1550,7 +1550,7 @@ pub(crate) async fn set_profile_image( if contact_id == ContactId::SELF { if was_encrypted { context - .set_config(Config::Selfavatar, Some(profile_image)) + .set_config_internal(Config::Selfavatar, Some(profile_image)) .await?; } else { info!(context, "Do not use unencrypted selfavatar."); @@ -1563,7 +1563,9 @@ pub(crate) async fn set_profile_image( AvatarAction::Delete => { if contact_id == ContactId::SELF { if was_encrypted { - context.set_config(Config::Selfavatar, None).await?; + context + .set_config_internal(Config::Selfavatar, None) + .await?; } else { info!(context, "Do not use unencrypted selfavatar deletion."); } @@ -1595,7 +1597,7 @@ pub(crate) async fn set_status( if contact_id == ContactId::SELF { if encrypted && has_chat_version { context - .set_config(Config::Selfstatus, Some(&status)) + .set_config_internal(Config::Selfstatus, Some(&status)) .await?; } } else { diff --git a/src/context.rs b/src/context.rs index 54969471b..1832ae2de 100644 --- a/src/context.rs +++ b/src/context.rs @@ -408,7 +408,7 @@ impl Context { } /// Starts the IO scheduler. - pub async fn start_io(&mut self) { + pub async fn start_io(&self) { if !self.is_configured().await.unwrap_or_default() { warn!(self, "can not start io on a context that is not configured"); return; diff --git a/src/imap.rs b/src/imap.rs index 4bf3cc240..519c1bfa7 100644 --- a/src/imap.rs +++ b/src/imap.rs @@ -451,7 +451,10 @@ impl Imap { && err.to_string().to_lowercase().contains("authentication") && context.get_config_bool(Config::NotifyAboutWrongPw).await? { - if let Err(e) = context.set_config(Config::NotifyAboutWrongPw, None).await { + if let Err(e) = context + .set_config_internal(Config::NotifyAboutWrongPw, None) + .await + { warn!(context, "{:#}", e); } drop(lock); @@ -1877,16 +1880,16 @@ impl Imap { .context("failed to configure mvbox")?; context - .set_config(Config::ConfiguredInboxFolder, Some("INBOX")) + .set_config_internal(Config::ConfiguredInboxFolder, Some("INBOX")) .await?; if let Some(mvbox_folder) = mvbox_folder { info!(context, "Setting MVBOX FOLDER TO {}", &mvbox_folder); context - .set_config(Config::ConfiguredMvboxFolder, Some(mvbox_folder)) + .set_config_internal(Config::ConfiguredMvboxFolder, Some(mvbox_folder)) .await?; } for (config, name) in folder_configs { - context.set_config(config, Some(&name)).await?; + context.set_config_internal(config, Some(&name)).await?; } context .sql diff --git a/src/imap/scan_folders.rs b/src/imap/scan_folders.rs index 714c961f3..257d1a483 100644 --- a/src/imap/scan_folders.rs +++ b/src/imap/scan_folders.rs @@ -89,7 +89,7 @@ impl Imap { Config::ConfiguredTrashFolder, ] { context - .set_config(conf, folder_configs.get(&conf).map(|s| s.as_str())) + .set_config_internal(conf, folder_configs.get(&conf).map(|s| s.as_str())) .await?; } diff --git a/src/message.rs b/src/message.rs index 0ea6edcc4..a2cfbfc8a 100644 --- a/src/message.rs +++ b/src/message.rs @@ -1522,7 +1522,9 @@ pub async fn delete_msgs(context: &Context, msg_ids: &[MsgId]) -> Result<()> { if !msg_ids.is_empty() { // Run housekeeping to delete unused blobs. - context.set_config(Config::LastHousekeeping, None).await?; + context + .set_config_internal(Config::LastHousekeeping, None) + .await?; } // Interrupt Inbox loop to start message deletion and run housekeeping. @@ -1550,7 +1552,7 @@ pub async fn markseen_msgs(context: &Context, msg_ids: Vec) -> Result<()> let old_last_msg_id = MsgId::new(context.get_config_u32(Config::LastMsgId).await?); let last_msg_id = msg_ids.iter().fold(&old_last_msg_id, std::cmp::max); context - .set_config_u32(Config::LastMsgId, last_msg_id.to_u32()) + .set_config_internal(Config::LastMsgId, Some(&last_msg_id.to_u32().to_string())) .await?; let msgs = context diff --git a/src/qr.rs b/src/qr.rs index fcefaf13a..eafec7fa4 100644 --- a/src/qr.rs +++ b/src/qr.rs @@ -560,8 +560,12 @@ async fn set_account_from_qr(context: &Context, qr: &str) -> Result<()> { "Cannot create account, response from {url_str:?} is malformed:\n{response_text:?}" ) })?; - context.set_config(Config::Addr, Some(&email)).await?; - context.set_config(Config::MailPw, Some(&password)).await?; + context + .set_config_internal(Config::Addr, Some(&email)) + .await?; + context + .set_config_internal(Config::MailPw, Some(&password)) + .await?; Ok(()) } else { @@ -589,7 +593,7 @@ pub async fn set_config_from_qr(context: &Context, qr: &str) -> Result<()> { instance_pattern, } => { context - .set_config(Config::WebrtcInstance, Some(&instance_pattern)) + .set_config_internal(Config::WebrtcInstance, Some(&instance_pattern)) .await?; } Qr::WithdrawVerifyContact { diff --git a/src/qr/dclogin_scheme.rs b/src/qr/dclogin_scheme.rs index 36118e386..01ae8203e 100644 --- a/src/qr/dclogin_scheme.rs +++ b/src/qr/dclogin_scheme.rs @@ -163,7 +163,9 @@ pub(crate) async fn configure_from_login_qr( address: &str, options: LoginOptions, ) -> Result<()> { - context.set_config(Config::Addr, Some(address)).await?; + context + .set_config_internal(Config::Addr, Some(address)) + .await?; match options { LoginOptions::V1 { @@ -181,27 +183,35 @@ pub(crate) async fn configure_from_login_qr( smtp_security, smtp_certificate_checks, } => { - context.set_config(Config::MailPw, Some(&mail_pw)).await?; + context + .set_config_internal(Config::MailPw, Some(&mail_pw)) + .await?; if let Some(value) = imap_host { - context.set_config(Config::MailServer, Some(&value)).await?; + context + .set_config_internal(Config::MailServer, Some(&value)) + .await?; } if let Some(value) = imap_port { context - .set_config(Config::MailPort, Some(&value.to_string())) + .set_config_internal(Config::MailPort, Some(&value.to_string())) .await?; } if let Some(value) = imap_username { - context.set_config(Config::MailUser, Some(&value)).await?; + context + .set_config_internal(Config::MailUser, Some(&value)) + .await?; } if let Some(value) = imap_password { - context.set_config(Config::MailPw, Some(&value)).await?; + context + .set_config_internal(Config::MailPw, Some(&value)) + .await?; } if let Some(value) = imap_security { let code = value .to_u8() .context("could not convert imap security value to number")?; context - .set_config(Config::MailSecurity, Some(&code.to_string())) + .set_config_internal(Config::MailSecurity, Some(&code.to_string())) .await?; } if let Some(value) = imap_certificate_checks { @@ -209,29 +219,35 @@ pub(crate) async fn configure_from_login_qr( .to_u32() .context("could not convert imap certificate checks value to number")?; context - .set_config(Config::ImapCertificateChecks, Some(&code.to_string())) + .set_config_internal(Config::ImapCertificateChecks, Some(&code.to_string())) .await?; } if let Some(value) = smtp_host { - context.set_config(Config::SendServer, Some(&value)).await?; + context + .set_config_internal(Config::SendServer, Some(&value)) + .await?; } if let Some(value) = smtp_port { context - .set_config(Config::SendPort, Some(&value.to_string())) + .set_config_internal(Config::SendPort, Some(&value.to_string())) .await?; } if let Some(value) = smtp_username { - context.set_config(Config::SendUser, Some(&value)).await?; + context + .set_config_internal(Config::SendUser, Some(&value)) + .await?; } if let Some(value) = smtp_password { - context.set_config(Config::SendPw, Some(&value)).await?; + context + .set_config_internal(Config::SendPw, Some(&value)) + .await?; } if let Some(value) = smtp_security { let code = value .to_u8() .context("could not convert smtp security value to number")?; context - .set_config(Config::SendSecurity, Some(&code.to_string())) + .set_config_internal(Config::SendSecurity, Some(&code.to_string())) .await?; } if let Some(value) = smtp_certificate_checks { @@ -239,7 +255,7 @@ pub(crate) async fn configure_from_login_qr( .to_u32() .context("could not convert smtp certificate checks value to number")?; context - .set_config(Config::SmtpCertificateChecks, Some(&code.to_string())) + .set_config_internal(Config::SmtpCertificateChecks, Some(&code.to_string())) .await?; } Ok(()) diff --git a/src/quota.rs b/src/quota.rs index 5fc976437..6fa272a88 100644 --- a/src/quota.rs +++ b/src/quota.rs @@ -132,13 +132,17 @@ impl Context { highest, self.get_config_int(Config::QuotaExceeding).await? as u64, ) { - self.set_config(Config::QuotaExceeding, Some(&highest.to_string())) - .await?; + self.set_config_internal( + Config::QuotaExceeding, + Some(&highest.to_string()), + ) + .await?; let mut msg = Message::new(Viewtype::Text); msg.text = stock_str::quota_exceeding(self, highest).await; add_device_msg_with_importance(self, None, Some(&mut msg), true).await?; } else if highest <= QUOTA_ALLCLEAR_PERCENTAGE { - self.set_config(Config::QuotaExceeding, None).await?; + self.set_config_internal(Config::QuotaExceeding, None) + .await?; } } Err(err) => warn!(self, "cannot get highest quota usage: {:#}", err), diff --git a/src/receive_imf.rs b/src/receive_imf.rs index 355cba10c..dd22f0829 100644 --- a/src/receive_imf.rs +++ b/src/receive_imf.rs @@ -1034,7 +1034,10 @@ async fn add_parts( }; if update_config { context - .set_config(Config::LastCantDecryptOutgoingMsgs, Some(&now.to_string())) + .set_config_internal( + Config::LastCantDecryptOutgoingMsgs, + Some(&now.to_string()), + ) .await?; } } diff --git a/src/scheduler.rs b/src/scheduler.rs index 9a8b651ea..ed50b504e 100644 --- a/src/scheduler.rs +++ b/src/scheduler.rs @@ -12,7 +12,7 @@ use tokio::sync::{oneshot, RwLock, RwLockWriteGuard}; use tokio::task; use self::connectivity::ConnectivityStore; -use crate::config::Config; +use crate::config::{self, Config}; use crate::contact::{ContactId, RecentlySeenLoop}; use crate::context::Context; use crate::download::{download_msg, DownloadState}; @@ -290,7 +290,7 @@ enum InnerSchedulerState { /// /// Returned by [`SchedulerState::pause`]. To resume the IO scheduler simply drop this /// guard. -#[derive(Debug)] +#[derive(Default, Debug)] pub(crate) struct IoPausedGuard { sender: Option>, } @@ -439,8 +439,12 @@ async fn inbox_loop( // // This operation is not critical enough to retry, // especially if the error is persistent. - if let Err(err) = - ctx.set_config_bool(Config::FetchedExistingMsgs, true).await + if let Err(err) = ctx + .set_config_internal( + Config::FetchedExistingMsgs, + config::from_bool(true), + ) + .await { warn!(ctx, "Can't set Config::FetchedExistingMsgs: {:#}", err); } diff --git a/src/sql.rs b/src/sql.rs index 51b1d422b..9333ba161 100644 --- a/src/sql.rs +++ b/src/sql.rs @@ -248,7 +248,7 @@ impl Sql { msg.set_text(stock_str::delete_server_turned_off(context).await); add_device_msg(context, None, Some(&mut msg)).await?; context - .set_config(Config::DeleteServerAfter, Some("0")) + .set_config_internal(Config::DeleteServerAfter, Some("0")) .await?; } } @@ -259,12 +259,14 @@ impl Sql { match blob.recode_to_avatar_size(context).await { Ok(()) => { context - .set_config(Config::Selfavatar, Some(&avatar)) + .set_config_internal(Config::Selfavatar, Some(&avatar)) .await? } Err(e) => { warn!(context, "Migrations can't recode avatar, removing. {:#}", e); - context.set_config(Config::Selfavatar, None).await? + context + .set_config_internal(Config::Selfavatar, None) + .await? } } } @@ -702,7 +704,7 @@ pub async fn housekeeping(context: &Context) -> Result<()> { // Setting `Config::LastHousekeeping` at the beginning avoids endless loops when things do not // work out for whatever reason or are interrupted by the OS. if let Err(e) = context - .set_config(Config::LastHousekeeping, Some(&time().to_string())) + .set_config_internal(Config::LastHousekeeping, Some(&time().to_string())) .await { warn!(context, "Can't set config: {e:#}."); diff --git a/src/sql/migrations.rs b/src/sql/migrations.rs index 5301f7de3..090cedc2f 100644 --- a/src/sql/migrations.rs +++ b/src/sql/migrations.rs @@ -368,7 +368,7 @@ UPDATE chats SET protected=1, type=120 WHERE type=130;"#, if let Ok(addr) = context.get_primary_self_addr().await { if let Ok(domain) = EmailAddress::new(&addr).map(|email| email.domain) { context - .set_config( + .set_config_internal( Config::ConfiguredProvider, get_provider_by_domain(&domain).map(|provider| provider.id), )