mirror of
https://github.com/chatmail/core.git
synced 2026-04-24 00:46:30 +03:00
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.
This commit is contained in:
@@ -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,
|
* 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.
|
* however, on the other hand, may lead to unwanted notifications in non-delta clients.
|
||||||
* - `sentbox_watch`= 1=watch `Sent`-folder for changes,
|
* - `sentbox_watch`= 1=watch `Sent`-folder for changes,
|
||||||
* 0=do not watch the `Sent`-folder (default),
|
* 0=do not watch the `Sent`-folder (default).
|
||||||
* changes require restarting IO by calling dc_stop_io() and then dc_start_io().
|
|
||||||
* - `mvbox_move` = 1=detect chat messages,
|
* - `mvbox_move` = 1=detect chat messages,
|
||||||
* move them to the `DeltaChat` folder,
|
* move them to the `DeltaChat` folder,
|
||||||
* and watch the `DeltaChat` folder for updates (default),
|
* and watch the `DeltaChat` folder for updates (default),
|
||||||
* 0=do not move chat-messages
|
* 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
|
* - `only_fetch_mvbox` = 1=Do not fetch messages from folders other than the
|
||||||
* `DeltaChat` folder. Messages will still be fetched from the
|
* `DeltaChat` folder. Messages will still be fetched from the
|
||||||
* spam folder and `sendbox_watch` will also still be respected
|
* spam folder and `sendbox_watch` will also still be respected
|
||||||
* if enabled.
|
* if enabled.
|
||||||
* 0=watch all folders normally (default)
|
* 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_emails` = DC_SHOW_EMAILS_OFF (0)=
|
||||||
* show direct replies to chats only,
|
* show direct replies to chats only,
|
||||||
* DC_SHOW_EMAILS_ACCEPTED_CONTACTS (1)=
|
* DC_SHOW_EMAILS_ACCEPTED_CONTACTS (1)=
|
||||||
|
|||||||
@@ -251,7 +251,7 @@ impl CommandApi {
|
|||||||
|
|
||||||
/// Starts background tasks for a single account.
|
/// Starts background tasks for a single account.
|
||||||
async fn start_io(&self, account_id: u32) -> Result<()> {
|
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;
|
ctx.start_io().await;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -402,7 +402,7 @@ impl CommandApi {
|
|||||||
/// Configures this account with the currently set parameters.
|
/// Configures this account with the currently set parameters.
|
||||||
/// Setup the credential config before calling this.
|
/// Setup the credential config before calling this.
|
||||||
async fn configure(&self, account_id: u32) -> Result<()> {
|
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;
|
ctx.stop_io().await;
|
||||||
let result = ctx.configure().await;
|
let result = ctx.configure().await;
|
||||||
if result.is_err() {
|
if result.is_err() {
|
||||||
@@ -2125,13 +2125,6 @@ async fn set_config(
|
|||||||
value,
|
value,
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
match key {
|
|
||||||
"sentbox_watch" | "mvbox_move" | "only_fetch_mvbox" => {
|
|
||||||
ctx.restart_io_if_running().await;
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -401,7 +401,7 @@ enum ExitResult {
|
|||||||
|
|
||||||
async fn handle_cmd(
|
async fn handle_cmd(
|
||||||
line: &str,
|
line: &str,
|
||||||
mut ctx: Context,
|
ctx: Context,
|
||||||
selected_chat: &mut ChatId,
|
selected_chat: &mut ChatId,
|
||||||
) -> Result<ExitResult, Error> {
|
) -> Result<ExitResult, Error> {
|
||||||
let mut args = line.splitn(2, ' ');
|
let mut args = line.splitn(2, ' ');
|
||||||
|
|||||||
@@ -382,6 +382,21 @@ def test_webxdc_download_on_demand(acfactory, data, lp):
|
|||||||
assert msgs_changed_event.data2 == 0
|
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):
|
def test_mvbox_sentbox_threads(acfactory, lp):
|
||||||
lp.sec("ac1: start with mvbox thread")
|
lp.sec("ac1: start with mvbox thread")
|
||||||
ac1 = acfactory.new_online_configuring_account(mvbox_move=True, sentbox_watch=True)
|
ac1 = acfactory.new_online_configuring_account(mvbox_move=True, sentbox_watch=True)
|
||||||
|
|||||||
@@ -216,7 +216,7 @@ async fn update_authservid_candidates(
|
|||||||
if old_ids != new_ids {
|
if old_ids != new_ids {
|
||||||
let new_config = new_ids.into_iter().collect::<Vec<_>>().join(" ");
|
let new_config = new_ids.into_iter().collect::<Vec<_>>().join(" ");
|
||||||
context
|
context
|
||||||
.set_config(Config::AuthservIdCandidates, Some(&new_config))
|
.set_config_internal(Config::AuthservIdCandidates, Some(&new_config))
|
||||||
.await?;
|
.await?;
|
||||||
// Updating the authservid candidates may mean that we now consider
|
// Updating the authservid candidates may mean that we now consider
|
||||||
// emails as "failed" which "passed" previously, so we need to
|
// emails as "failed" which "passed" previously, so we need to
|
||||||
|
|||||||
@@ -783,7 +783,9 @@ impl ChatId {
|
|||||||
|
|
||||||
context.emit_msgs_changed_without_ids();
|
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;
|
context.scheduler.interrupt_inbox().await;
|
||||||
|
|
||||||
if chat.is_self_talk() {
|
if chat.is_self_talk() {
|
||||||
@@ -4266,7 +4268,9 @@ pub(crate) async fn delete_and_reset_all_device_msgs(context: &Context) -> Resul
|
|||||||
(),
|
(),
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
context.set_config(Config::QuotaExceeding, None).await?;
|
context
|
||||||
|
.set_config_internal(Config::QuotaExceeding, None)
|
||||||
|
.await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -367,11 +367,23 @@ impl Config {
|
|||||||
/// multiple users are sharing an account. Another example is `Self::SyncMsgs` itself which
|
/// multiple users are sharing an account. Another example is `Self::SyncMsgs` itself which
|
||||||
/// mustn't be controlled by other devices.
|
/// mustn't be controlled by other devices.
|
||||||
pub(crate) fn is_synced(&self) -> bool {
|
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!(
|
matches!(
|
||||||
self,
|
self,
|
||||||
Self::Displayname | Self::MdnsEnabled | Self::ShowEmails
|
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 {
|
impl Context {
|
||||||
@@ -491,10 +503,50 @@ impl Context {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set the given config key.
|
fn check_config(key: Config, value: Option<&str>) -> Result<()> {
|
||||||
/// If `None` is passed as a value the value is cleared and set to the default if there is one.
|
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<()> {
|
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(
|
pub(crate) async fn set_config_ex(
|
||||||
@@ -503,7 +555,10 @@ impl Context {
|
|||||||
key: Config,
|
key: Config,
|
||||||
mut value: Option<&str>,
|
mut value: Option<&str>,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
|
Self::check_config(key, value)?;
|
||||||
|
let sync = sync == Sync && key.is_synced();
|
||||||
let better_value;
|
let better_value;
|
||||||
|
|
||||||
match key {
|
match key {
|
||||||
Config::Selfavatar => {
|
Config::Selfavatar => {
|
||||||
self.sql
|
self.sql
|
||||||
@@ -536,28 +591,6 @@ impl Context {
|
|||||||
}
|
}
|
||||||
self.sql.set_raw_config(key.as_ref(), value).await?;
|
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 => {
|
Config::Addr => {
|
||||||
self.sql
|
self.sql
|
||||||
.set_raw_config(key.as_ref(), value.map(|s| s.to_lowercase()).as_deref())
|
.set_raw_config(key.as_ref(), value.map(|s| s.to_lowercase()).as_deref())
|
||||||
@@ -570,7 +603,7 @@ impl Context {
|
|||||||
if key.is_synced() {
|
if key.is_synced() {
|
||||||
self.emit_event(EventType::ConfigSynced { key });
|
self.emit_event(EventType::ConfigSynced { key });
|
||||||
}
|
}
|
||||||
if sync != Sync {
|
if !sync {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
let Some(val) = value else {
|
let Some(val) = value else {
|
||||||
@@ -597,8 +630,7 @@ impl Context {
|
|||||||
|
|
||||||
/// Set the given config to a boolean value.
|
/// Set the given config to a boolean value.
|
||||||
pub async fn set_config_bool(&self, key: Config, value: bool) -> Result<()> {
|
pub async fn set_config_bool(&self, key: Config, value: bool) -> Result<()> {
|
||||||
self.set_config(key, if value { Some("1") } else { Some("0") })
|
self.set_config(key, from_bool(value)).await?;
|
||||||
.await?;
|
|
||||||
Ok(())
|
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
|
// Separate impl block for self address handling
|
||||||
impl Context {
|
impl Context {
|
||||||
/// Determine whether the specified addr maps to the/a self addr.
|
/// 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?;
|
let mut secondary_addrs = self.get_all_self_addrs().await?;
|
||||||
// never store a primary address also as a secondary
|
// never store a primary address also as a secondary
|
||||||
secondary_addrs.retain(|a| !addr_cmp(a, primary_new));
|
secondary_addrs.retain(|a| !addr_cmp(a, primary_new));
|
||||||
self.set_config(
|
self.set_config_internal(
|
||||||
Config::SecondaryAddrs,
|
Config::SecondaryAddrs,
|
||||||
Some(secondary_addrs.join(" ").as_str()),
|
Some(secondary_addrs.join(" ").as_str()),
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
self.set_config(Config::ConfiguredAddr, Some(primary_new))
|
self.set_config_internal(Config::ConfiguredAddr, Some(primary_new))
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ use percent_encoding::{utf8_percent_encode, NON_ALPHANUMERIC};
|
|||||||
use server_params::{expand_param_vector, ServerParams};
|
use server_params::{expand_param_vector, ServerParams};
|
||||||
use tokio::task;
|
use tokio::task;
|
||||||
|
|
||||||
use crate::config::Config;
|
use crate::config::{self, Config};
|
||||||
use crate::contact::addr_cmp;
|
use crate::contact::addr_cmp;
|
||||||
use crate::context::Context;
|
use crate::context::Context;
|
||||||
use crate::imap::Imap;
|
use crate::imap::Imap;
|
||||||
@@ -112,12 +112,13 @@ impl Context {
|
|||||||
let mut param = LoginParam::load_candidate_params(self).await?;
|
let mut param = LoginParam::load_candidate_params(self).await?;
|
||||||
let old_addr = self.get_config(Config::ConfiguredAddr).await?;
|
let old_addr = self.get_config(Config::ConfiguredAddr).await?;
|
||||||
let success = configure(self, &mut param).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?;
|
on_configure_completed(self, param, old_addr).await?;
|
||||||
|
|
||||||
success?;
|
success?;
|
||||||
self.set_config(Config::NotifyAboutWrongPw, Some("1"))
|
self.set_config_internal(Config::NotifyAboutWrongPw, Some("1"))
|
||||||
.await?;
|
.await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -473,7 +474,7 @@ async fn configure(ctx: &Context, param: &mut LoginParam) -> Result<()> {
|
|||||||
|
|
||||||
// the trailing underscore is correct
|
// the trailing underscore is correct
|
||||||
param.save_as_configured_params(ctx).await?;
|
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?;
|
.await?;
|
||||||
|
|
||||||
progress!(ctx, 920);
|
progress!(ctx, 920);
|
||||||
@@ -481,7 +482,7 @@ async fn configure(ctx: &Context, param: &mut LoginParam) -> Result<()> {
|
|||||||
e2ee::ensure_secret_key_exists(ctx).await?;
|
e2ee::ensure_secret_key_exists(ctx).await?;
|
||||||
info!(ctx, "key generation completed");
|
info!(ctx, "key generation completed");
|
||||||
|
|
||||||
ctx.set_config_bool(Config::FetchedExistingMsgs, false)
|
ctx.set_config_internal(Config::FetchedExistingMsgs, config::from_bool(false))
|
||||||
.await?;
|
.await?;
|
||||||
ctx.scheduler.interrupt_inbox().await;
|
ctx.scheduler.interrupt_inbox().await;
|
||||||
|
|
||||||
|
|||||||
@@ -1550,7 +1550,7 @@ pub(crate) async fn set_profile_image(
|
|||||||
if contact_id == ContactId::SELF {
|
if contact_id == ContactId::SELF {
|
||||||
if was_encrypted {
|
if was_encrypted {
|
||||||
context
|
context
|
||||||
.set_config(Config::Selfavatar, Some(profile_image))
|
.set_config_internal(Config::Selfavatar, Some(profile_image))
|
||||||
.await?;
|
.await?;
|
||||||
} else {
|
} else {
|
||||||
info!(context, "Do not use unencrypted selfavatar.");
|
info!(context, "Do not use unencrypted selfavatar.");
|
||||||
@@ -1563,7 +1563,9 @@ pub(crate) async fn set_profile_image(
|
|||||||
AvatarAction::Delete => {
|
AvatarAction::Delete => {
|
||||||
if contact_id == ContactId::SELF {
|
if contact_id == ContactId::SELF {
|
||||||
if was_encrypted {
|
if was_encrypted {
|
||||||
context.set_config(Config::Selfavatar, None).await?;
|
context
|
||||||
|
.set_config_internal(Config::Selfavatar, None)
|
||||||
|
.await?;
|
||||||
} else {
|
} else {
|
||||||
info!(context, "Do not use unencrypted selfavatar deletion.");
|
info!(context, "Do not use unencrypted selfavatar deletion.");
|
||||||
}
|
}
|
||||||
@@ -1595,7 +1597,7 @@ pub(crate) async fn set_status(
|
|||||||
if contact_id == ContactId::SELF {
|
if contact_id == ContactId::SELF {
|
||||||
if encrypted && has_chat_version {
|
if encrypted && has_chat_version {
|
||||||
context
|
context
|
||||||
.set_config(Config::Selfstatus, Some(&status))
|
.set_config_internal(Config::Selfstatus, Some(&status))
|
||||||
.await?;
|
.await?;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -408,7 +408,7 @@ impl Context {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Starts the IO scheduler.
|
/// 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() {
|
if !self.is_configured().await.unwrap_or_default() {
|
||||||
warn!(self, "can not start io on a context that is not configured");
|
warn!(self, "can not start io on a context that is not configured");
|
||||||
return;
|
return;
|
||||||
|
|||||||
11
src/imap.rs
11
src/imap.rs
@@ -451,7 +451,10 @@ impl Imap {
|
|||||||
&& err.to_string().to_lowercase().contains("authentication")
|
&& err.to_string().to_lowercase().contains("authentication")
|
||||||
&& context.get_config_bool(Config::NotifyAboutWrongPw).await?
|
&& 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);
|
warn!(context, "{:#}", e);
|
||||||
}
|
}
|
||||||
drop(lock);
|
drop(lock);
|
||||||
@@ -1877,16 +1880,16 @@ impl Imap {
|
|||||||
.context("failed to configure mvbox")?;
|
.context("failed to configure mvbox")?;
|
||||||
|
|
||||||
context
|
context
|
||||||
.set_config(Config::ConfiguredInboxFolder, Some("INBOX"))
|
.set_config_internal(Config::ConfiguredInboxFolder, Some("INBOX"))
|
||||||
.await?;
|
.await?;
|
||||||
if let Some(mvbox_folder) = mvbox_folder {
|
if let Some(mvbox_folder) = mvbox_folder {
|
||||||
info!(context, "Setting MVBOX FOLDER TO {}", &mvbox_folder);
|
info!(context, "Setting MVBOX FOLDER TO {}", &mvbox_folder);
|
||||||
context
|
context
|
||||||
.set_config(Config::ConfiguredMvboxFolder, Some(mvbox_folder))
|
.set_config_internal(Config::ConfiguredMvboxFolder, Some(mvbox_folder))
|
||||||
.await?;
|
.await?;
|
||||||
}
|
}
|
||||||
for (config, name) in folder_configs {
|
for (config, name) in folder_configs {
|
||||||
context.set_config(config, Some(&name)).await?;
|
context.set_config_internal(config, Some(&name)).await?;
|
||||||
}
|
}
|
||||||
context
|
context
|
||||||
.sql
|
.sql
|
||||||
|
|||||||
@@ -89,7 +89,7 @@ impl Imap {
|
|||||||
Config::ConfiguredTrashFolder,
|
Config::ConfiguredTrashFolder,
|
||||||
] {
|
] {
|
||||||
context
|
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?;
|
.await?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1522,7 +1522,9 @@ pub async fn delete_msgs(context: &Context, msg_ids: &[MsgId]) -> Result<()> {
|
|||||||
|
|
||||||
if !msg_ids.is_empty() {
|
if !msg_ids.is_empty() {
|
||||||
// Run housekeeping to delete unused blobs.
|
// 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.
|
// Interrupt Inbox loop to start message deletion and run housekeeping.
|
||||||
@@ -1550,7 +1552,7 @@ pub async fn markseen_msgs(context: &Context, msg_ids: Vec<MsgId>) -> Result<()>
|
|||||||
let old_last_msg_id = MsgId::new(context.get_config_u32(Config::LastMsgId).await?);
|
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);
|
let last_msg_id = msg_ids.iter().fold(&old_last_msg_id, std::cmp::max);
|
||||||
context
|
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?;
|
.await?;
|
||||||
|
|
||||||
let msgs = context
|
let msgs = context
|
||||||
|
|||||||
10
src/qr.rs
10
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:?}"
|
"Cannot create account, response from {url_str:?} is malformed:\n{response_text:?}"
|
||||||
)
|
)
|
||||||
})?;
|
})?;
|
||||||
context.set_config(Config::Addr, Some(&email)).await?;
|
context
|
||||||
context.set_config(Config::MailPw, Some(&password)).await?;
|
.set_config_internal(Config::Addr, Some(&email))
|
||||||
|
.await?;
|
||||||
|
context
|
||||||
|
.set_config_internal(Config::MailPw, Some(&password))
|
||||||
|
.await?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
@@ -589,7 +593,7 @@ pub async fn set_config_from_qr(context: &Context, qr: &str) -> Result<()> {
|
|||||||
instance_pattern,
|
instance_pattern,
|
||||||
} => {
|
} => {
|
||||||
context
|
context
|
||||||
.set_config(Config::WebrtcInstance, Some(&instance_pattern))
|
.set_config_internal(Config::WebrtcInstance, Some(&instance_pattern))
|
||||||
.await?;
|
.await?;
|
||||||
}
|
}
|
||||||
Qr::WithdrawVerifyContact {
|
Qr::WithdrawVerifyContact {
|
||||||
|
|||||||
@@ -163,7 +163,9 @@ pub(crate) async fn configure_from_login_qr(
|
|||||||
address: &str,
|
address: &str,
|
||||||
options: LoginOptions,
|
options: LoginOptions,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
context.set_config(Config::Addr, Some(address)).await?;
|
context
|
||||||
|
.set_config_internal(Config::Addr, Some(address))
|
||||||
|
.await?;
|
||||||
|
|
||||||
match options {
|
match options {
|
||||||
LoginOptions::V1 {
|
LoginOptions::V1 {
|
||||||
@@ -181,27 +183,35 @@ pub(crate) async fn configure_from_login_qr(
|
|||||||
smtp_security,
|
smtp_security,
|
||||||
smtp_certificate_checks,
|
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 {
|
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 {
|
if let Some(value) = imap_port {
|
||||||
context
|
context
|
||||||
.set_config(Config::MailPort, Some(&value.to_string()))
|
.set_config_internal(Config::MailPort, Some(&value.to_string()))
|
||||||
.await?;
|
.await?;
|
||||||
}
|
}
|
||||||
if let Some(value) = imap_username {
|
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 {
|
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 {
|
if let Some(value) = imap_security {
|
||||||
let code = value
|
let code = value
|
||||||
.to_u8()
|
.to_u8()
|
||||||
.context("could not convert imap security value to number")?;
|
.context("could not convert imap security value to number")?;
|
||||||
context
|
context
|
||||||
.set_config(Config::MailSecurity, Some(&code.to_string()))
|
.set_config_internal(Config::MailSecurity, Some(&code.to_string()))
|
||||||
.await?;
|
.await?;
|
||||||
}
|
}
|
||||||
if let Some(value) = imap_certificate_checks {
|
if let Some(value) = imap_certificate_checks {
|
||||||
@@ -209,29 +219,35 @@ pub(crate) async fn configure_from_login_qr(
|
|||||||
.to_u32()
|
.to_u32()
|
||||||
.context("could not convert imap certificate checks value to number")?;
|
.context("could not convert imap certificate checks value to number")?;
|
||||||
context
|
context
|
||||||
.set_config(Config::ImapCertificateChecks, Some(&code.to_string()))
|
.set_config_internal(Config::ImapCertificateChecks, Some(&code.to_string()))
|
||||||
.await?;
|
.await?;
|
||||||
}
|
}
|
||||||
if let Some(value) = smtp_host {
|
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 {
|
if let Some(value) = smtp_port {
|
||||||
context
|
context
|
||||||
.set_config(Config::SendPort, Some(&value.to_string()))
|
.set_config_internal(Config::SendPort, Some(&value.to_string()))
|
||||||
.await?;
|
.await?;
|
||||||
}
|
}
|
||||||
if let Some(value) = smtp_username {
|
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 {
|
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 {
|
if let Some(value) = smtp_security {
|
||||||
let code = value
|
let code = value
|
||||||
.to_u8()
|
.to_u8()
|
||||||
.context("could not convert smtp security value to number")?;
|
.context("could not convert smtp security value to number")?;
|
||||||
context
|
context
|
||||||
.set_config(Config::SendSecurity, Some(&code.to_string()))
|
.set_config_internal(Config::SendSecurity, Some(&code.to_string()))
|
||||||
.await?;
|
.await?;
|
||||||
}
|
}
|
||||||
if let Some(value) = smtp_certificate_checks {
|
if let Some(value) = smtp_certificate_checks {
|
||||||
@@ -239,7 +255,7 @@ pub(crate) async fn configure_from_login_qr(
|
|||||||
.to_u32()
|
.to_u32()
|
||||||
.context("could not convert smtp certificate checks value to number")?;
|
.context("could not convert smtp certificate checks value to number")?;
|
||||||
context
|
context
|
||||||
.set_config(Config::SmtpCertificateChecks, Some(&code.to_string()))
|
.set_config_internal(Config::SmtpCertificateChecks, Some(&code.to_string()))
|
||||||
.await?;
|
.await?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|||||||
10
src/quota.rs
10
src/quota.rs
@@ -132,13 +132,17 @@ impl Context {
|
|||||||
highest,
|
highest,
|
||||||
self.get_config_int(Config::QuotaExceeding).await? as u64,
|
self.get_config_int(Config::QuotaExceeding).await? as u64,
|
||||||
) {
|
) {
|
||||||
self.set_config(Config::QuotaExceeding, Some(&highest.to_string()))
|
self.set_config_internal(
|
||||||
.await?;
|
Config::QuotaExceeding,
|
||||||
|
Some(&highest.to_string()),
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
let mut msg = Message::new(Viewtype::Text);
|
let mut msg = Message::new(Viewtype::Text);
|
||||||
msg.text = stock_str::quota_exceeding(self, highest).await;
|
msg.text = stock_str::quota_exceeding(self, highest).await;
|
||||||
add_device_msg_with_importance(self, None, Some(&mut msg), true).await?;
|
add_device_msg_with_importance(self, None, Some(&mut msg), true).await?;
|
||||||
} else if highest <= QUOTA_ALLCLEAR_PERCENTAGE {
|
} 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),
|
Err(err) => warn!(self, "cannot get highest quota usage: {:#}", err),
|
||||||
|
|||||||
@@ -1034,7 +1034,10 @@ async fn add_parts(
|
|||||||
};
|
};
|
||||||
if update_config {
|
if update_config {
|
||||||
context
|
context
|
||||||
.set_config(Config::LastCantDecryptOutgoingMsgs, Some(&now.to_string()))
|
.set_config_internal(
|
||||||
|
Config::LastCantDecryptOutgoingMsgs,
|
||||||
|
Some(&now.to_string()),
|
||||||
|
)
|
||||||
.await?;
|
.await?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ use tokio::sync::{oneshot, RwLock, RwLockWriteGuard};
|
|||||||
use tokio::task;
|
use tokio::task;
|
||||||
|
|
||||||
use self::connectivity::ConnectivityStore;
|
use self::connectivity::ConnectivityStore;
|
||||||
use crate::config::Config;
|
use crate::config::{self, Config};
|
||||||
use crate::contact::{ContactId, RecentlySeenLoop};
|
use crate::contact::{ContactId, RecentlySeenLoop};
|
||||||
use crate::context::Context;
|
use crate::context::Context;
|
||||||
use crate::download::{download_msg, DownloadState};
|
use crate::download::{download_msg, DownloadState};
|
||||||
@@ -290,7 +290,7 @@ enum InnerSchedulerState {
|
|||||||
///
|
///
|
||||||
/// Returned by [`SchedulerState::pause`]. To resume the IO scheduler simply drop this
|
/// Returned by [`SchedulerState::pause`]. To resume the IO scheduler simply drop this
|
||||||
/// guard.
|
/// guard.
|
||||||
#[derive(Debug)]
|
#[derive(Default, Debug)]
|
||||||
pub(crate) struct IoPausedGuard {
|
pub(crate) struct IoPausedGuard {
|
||||||
sender: Option<oneshot::Sender<()>>,
|
sender: Option<oneshot::Sender<()>>,
|
||||||
}
|
}
|
||||||
@@ -439,8 +439,12 @@ async fn inbox_loop(
|
|||||||
//
|
//
|
||||||
// This operation is not critical enough to retry,
|
// This operation is not critical enough to retry,
|
||||||
// especially if the error is persistent.
|
// especially if the error is persistent.
|
||||||
if let Err(err) =
|
if let Err(err) = ctx
|
||||||
ctx.set_config_bool(Config::FetchedExistingMsgs, true).await
|
.set_config_internal(
|
||||||
|
Config::FetchedExistingMsgs,
|
||||||
|
config::from_bool(true),
|
||||||
|
)
|
||||||
|
.await
|
||||||
{
|
{
|
||||||
warn!(ctx, "Can't set Config::FetchedExistingMsgs: {:#}", err);
|
warn!(ctx, "Can't set Config::FetchedExistingMsgs: {:#}", err);
|
||||||
}
|
}
|
||||||
|
|||||||
10
src/sql.rs
10
src/sql.rs
@@ -248,7 +248,7 @@ impl Sql {
|
|||||||
msg.set_text(stock_str::delete_server_turned_off(context).await);
|
msg.set_text(stock_str::delete_server_turned_off(context).await);
|
||||||
add_device_msg(context, None, Some(&mut msg)).await?;
|
add_device_msg(context, None, Some(&mut msg)).await?;
|
||||||
context
|
context
|
||||||
.set_config(Config::DeleteServerAfter, Some("0"))
|
.set_config_internal(Config::DeleteServerAfter, Some("0"))
|
||||||
.await?;
|
.await?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -259,12 +259,14 @@ impl Sql {
|
|||||||
match blob.recode_to_avatar_size(context).await {
|
match blob.recode_to_avatar_size(context).await {
|
||||||
Ok(()) => {
|
Ok(()) => {
|
||||||
context
|
context
|
||||||
.set_config(Config::Selfavatar, Some(&avatar))
|
.set_config_internal(Config::Selfavatar, Some(&avatar))
|
||||||
.await?
|
.await?
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
warn!(context, "Migrations can't recode avatar, removing. {:#}", 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
|
// Setting `Config::LastHousekeeping` at the beginning avoids endless loops when things do not
|
||||||
// work out for whatever reason or are interrupted by the OS.
|
// work out for whatever reason or are interrupted by the OS.
|
||||||
if let Err(e) = context
|
if let Err(e) = context
|
||||||
.set_config(Config::LastHousekeeping, Some(&time().to_string()))
|
.set_config_internal(Config::LastHousekeeping, Some(&time().to_string()))
|
||||||
.await
|
.await
|
||||||
{
|
{
|
||||||
warn!(context, "Can't set config: {e:#}.");
|
warn!(context, "Can't set config: {e:#}.");
|
||||||
|
|||||||
@@ -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(addr) = context.get_primary_self_addr().await {
|
||||||
if let Ok(domain) = EmailAddress::new(&addr).map(|email| email.domain) {
|
if let Ok(domain) = EmailAddress::new(&addr).map(|email| email.domain) {
|
||||||
context
|
context
|
||||||
.set_config(
|
.set_config_internal(
|
||||||
Config::ConfiguredProvider,
|
Config::ConfiguredProvider,
|
||||||
get_provider_by_domain(&domain).map(|provider| provider.id),
|
get_provider_by_domain(&domain).map(|provider| provider.id),
|
||||||
)
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user