mirror of
https://github.com/chatmail/core.git
synced 2026-05-08 01:16:31 +03:00
Introduce config caching (#3131)
* Introduce config caching * Changelog * Update CHANGELOG.md Co-authored-by: bjoern <r10s@b44t.com> * Cache a value after reading it Co-authored-by: bjoern <r10s@b44t.com>
This commit is contained in:
@@ -19,8 +19,10 @@
|
|||||||
- place common headers like `From:` before the large `Autocrypt:` header #3079
|
- place common headers like `From:` before the large `Autocrypt:` header #3079
|
||||||
- keep track of securejoin joiner status in database to survive restarts #2920
|
- keep track of securejoin joiner status in database to survive restarts #2920
|
||||||
- remove never used `SentboxMove` option #3111
|
- remove never used `SentboxMove` option #3111
|
||||||
|
- improve speed by caching config values
|
||||||
- optimize `markseen_msgs` #3141
|
- optimize `markseen_msgs` #3141
|
||||||
|
|
||||||
|
|
||||||
### Fixes
|
### Fixes
|
||||||
- Fix a bug where sometimes the file extension of a long filename containing a dot was cropped #3098
|
- Fix a bug where sometimes the file extension of a long filename containing a dot was cropped #3098
|
||||||
|
|
||||||
|
|||||||
@@ -84,6 +84,7 @@ async fn reset_tables(context: &Context, bits: i32) {
|
|||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
context.sql().config_cache().write().await.clear();
|
||||||
context
|
context
|
||||||
.sql()
|
.sql()
|
||||||
.execute("DELETE FROM leftgrps;", paramsv![])
|
.execute("DELETE FROM leftgrps;", paramsv![])
|
||||||
|
|||||||
27
src/sql.rs
27
src/sql.rs
@@ -3,7 +3,7 @@
|
|||||||
use async_std::path::Path;
|
use async_std::path::Path;
|
||||||
use async_std::sync::RwLock;
|
use async_std::sync::RwLock;
|
||||||
|
|
||||||
use std::collections::HashSet;
|
use std::collections::{HashMap, HashSet};
|
||||||
use std::convert::TryFrom;
|
use std::convert::TryFrom;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
@@ -47,6 +47,8 @@ pub struct Sql {
|
|||||||
/// None if the database is not open, true if it is open with passphrase and false if it is
|
/// None if the database is not open, true if it is open with passphrase and false if it is
|
||||||
/// open without a passphrase.
|
/// open without a passphrase.
|
||||||
is_encrypted: RwLock<Option<bool>>,
|
is_encrypted: RwLock<Option<bool>>,
|
||||||
|
|
||||||
|
config_cache: RwLock<HashMap<String, Option<String>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Sql {
|
impl Sql {
|
||||||
@@ -55,6 +57,7 @@ impl Sql {
|
|||||||
dbfile,
|
dbfile,
|
||||||
pool: Default::default(),
|
pool: Default::default(),
|
||||||
is_encrypted: Default::default(),
|
is_encrypted: Default::default(),
|
||||||
|
config_cache: Default::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -497,6 +500,7 @@ impl Sql {
|
|||||||
/// will already have been logged.
|
/// will already have been logged.
|
||||||
pub async fn set_raw_config(&self, key: impl AsRef<str>, value: Option<&str>) -> Result<()> {
|
pub async fn set_raw_config(&self, key: impl AsRef<str>, value: Option<&str>) -> Result<()> {
|
||||||
let key = key.as_ref();
|
let key = key.as_ref();
|
||||||
|
|
||||||
if let Some(value) = value {
|
if let Some(value) = value {
|
||||||
let exists = self
|
let exists = self
|
||||||
.exists(
|
.exists(
|
||||||
@@ -523,11 +527,23 @@ impl Sql {
|
|||||||
.await?;
|
.await?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let mut lock = self.config_cache.write().await;
|
||||||
|
lock.insert(key.to_string(), value.map(|s| s.to_string()));
|
||||||
|
drop(lock);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get configuration options from the database.
|
/// Get configuration options from the database.
|
||||||
pub async fn get_raw_config(&self, key: impl AsRef<str>) -> Result<Option<String>> {
|
pub async fn get_raw_config(&self, key: impl AsRef<str>) -> Result<Option<String>> {
|
||||||
|
let lock = self.config_cache.read().await;
|
||||||
|
let cached = lock.get(key.as_ref()).cloned();
|
||||||
|
drop(lock);
|
||||||
|
|
||||||
|
if let Some(c) = cached {
|
||||||
|
return Ok(c);
|
||||||
|
}
|
||||||
|
|
||||||
let value = self
|
let value = self
|
||||||
.query_get_value(
|
.query_get_value(
|
||||||
"SELECT value FROM config WHERE keyname=?;",
|
"SELECT value FROM config WHERE keyname=?;",
|
||||||
@@ -536,6 +552,10 @@ impl Sql {
|
|||||||
.await
|
.await
|
||||||
.context(format!("failed to fetch raw config: {}", key.as_ref()))?;
|
.context(format!("failed to fetch raw config: {}", key.as_ref()))?;
|
||||||
|
|
||||||
|
let mut lock = self.config_cache.write().await;
|
||||||
|
lock.insert(key.as_ref().to_string(), value.clone());
|
||||||
|
drop(lock);
|
||||||
|
|
||||||
Ok(value)
|
Ok(value)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -573,6 +593,11 @@ impl Sql {
|
|||||||
.await
|
.await
|
||||||
.map(|s| s.and_then(|r| r.parse().ok()))
|
.map(|s| s.and_then(|r| r.parse().ok()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "internals")]
|
||||||
|
pub fn config_cache(&self) -> &RwLock<HashMap<String, Option<String>>> {
|
||||||
|
&self.config_cache
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn housekeeping(context: &Context) -> Result<()> {
|
pub async fn housekeeping(context: &Context) -> Result<()> {
|
||||||
|
|||||||
@@ -622,6 +622,10 @@ impl Sql {
|
|||||||
.await
|
.await
|
||||||
.with_context(|| format!("execute_migration failed for version {}", version))?;
|
.with_context(|| format!("execute_migration failed for version {}", version))?;
|
||||||
|
|
||||||
|
let mut lock = self.config_cache.write().await;
|
||||||
|
lock.insert(VERSION_CFG.to_string(), Some(format!("{}", version)));
|
||||||
|
drop(lock);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user