chore: finalize redb migration for all memory stores

This commit is contained in:
Riz Ashraf committed 2026-09-10 10:48:37 +01:00
1 parent 9a8b6e52e9
commit 721f564910
4 files changed
+107 -88

No files matched your search

+36 -65
View File
@@ -1,84 +1,55 @@
use redb::{Database, ReadableDatabase, TableDefinition};
use serde::{Serialize, de::DeserializeOwned};
use std::fs;
use std::path::{Path, PathBuf};
use std::sync::RwLock;
use std::time::SystemTime;
use std::sync::{Arc, RwLock};
pub fn read_json_file<T: DeserializeOwned + Default>(path: &Path) -> T {
if let Ok(data) = fs::read(path)
&& let Ok(parsed) = serde_json::from_slice(&data)
{
return parsed;
}
let bak_path = path.with_extension("json.bak");
if let Ok(data) = fs::read(&bak_path)
&& let Ok(parsed) = serde_json::from_slice(&data)
{
let _ = fs::write(path, data);
return parsed;
}
T::default()
}
pub fn write_json_atomic<T: Serialize>(path: &Path, data: &T) -> std::io::Result<()> {
if path.exists() {
let bak_path = path.with_extension("json.bak");
let _ = fs::copy(path, &bak_path);
}
let tmp_path = path.with_extension("json.tmp");
let json_data = serde_json::to_string_pretty(data)?;
fs::write(&tmp_path, json_data)?;
fs::rename(&tmp_path, path)
}
pub const STORE_TABLE: TableDefinition<&str, &[u8]> = TableDefinition::new("store");
pub struct Store<T> {
pub path: PathBuf,
pub cache: RwLock<(T, SystemTime)>,
pub key: String,
pub db: Arc<Database>,
pub cache: RwLock<T>,
}
impl<T: DeserializeOwned + Default + Serialize + Clone> Store<T> {
fn mtime(&self) -> SystemTime {
fs::metadata(&self.path)
.and_then(|m| m.modified())
.unwrap_or(SystemTime::UNIX_EPOCH)
pub fn new(key: &str, db: Arc<Database>) -> Self {
let initial_data = Self::load_from_db(key, &db);
Self {
key: key.to_string(),
db,
cache: RwLock::new(initial_data),
}
}
pub fn new(path: PathBuf) -> Self {
let mtime = fs::metadata(&path)
.and_then(|m| m.modified())
.unwrap_or(SystemTime::UNIX_EPOCH);
let initial_data = read_json_file(&path);
Self {
path,
cache: RwLock::new((initial_data, mtime)),
fn load_from_db(key: &str, db: &Database) -> T {
let read_txn = db.begin_read().unwrap();
if let Ok(table) = read_txn.open_table(STORE_TABLE) {
if let Ok(Some(value)) = table.get(key) {
if let Ok(parsed) = serde_json::from_slice::<T>(value.value()) {
return parsed;
}
}
}
T::default()
}
fn save_to_db(key: &str, db: &Database, data: &T) {
let write_txn = db.begin_write().unwrap();
{
let mut table = write_txn.open_table(STORE_TABLE).unwrap();
let json_data = serde_json::to_vec(data).unwrap();
table.insert(key, json_data.as_slice()).unwrap();
}
write_txn.commit().unwrap();
}
pub fn read(&self) -> T {
let current_mtime = self.mtime();
{
let lock = self.cache.read().unwrap();
if lock.1 == current_mtime {
return lock.0.clone();
}
}
let mut lock = self.cache.write().unwrap();
let new_mtime = self.mtime();
if lock.1 != new_mtime {
lock.0 = read_json_file(&self.path);
lock.1 = new_mtime;
}
lock.0.clone()
let lock = self.cache.read().unwrap();
lock.clone()
}
pub fn modify<F: FnOnce(&mut T)>(&self, f: F) {
let mut lock = self.cache.write().unwrap();
let current_mtime = self.mtime();
if lock.1 != current_mtime {
lock.0 = read_json_file(&self.path);
}
f(&mut lock.0);
let _ = write_json_atomic(&self.path, &lock.0);
lock.1 = self.mtime();
f(&mut lock);
Self::save_to_db(&self.key, &self.db, &lock);
}
}