Optimize handlers to avoid deep clones of KnowledgeGraph, and fix database write concurrency issues

This commit is contained in:
Riz Ashraf committed 2026-09-21 06:53:32 +01:00
1 parent 7a48fa5d34
commit 9b349e6459
4 files changed
+197 -170

No files matched your search

+32 -16
View File
@@ -5,18 +5,35 @@ use std::sync::{Arc, RwLock};
pub const STORE_TABLE: TableDefinition<&str, &[u8]> = TableDefinition::new("store");
pub struct Store<T> {
pub key: String,
pub db: Arc<Database>,
pub cache: RwLock<T>,
tx: tokio::sync::mpsc::UnboundedSender<Vec<u8>>,
}
impl<T: DeserializeOwned + Default + Serialize + Clone + Send + 'static> Store<T> {
pub fn new(key: &str, db: Arc<Database>) -> Self {
let initial_data = Self::load_from_db(key, &db);
let (tx, mut rx) = tokio::sync::mpsc::unbounded_channel::<Vec<u8>>();
let db_clone = db.clone();
let key_clone = key.to_string();
tokio::spawn(async move {
while let Some(json_data) = rx.recv().await {
let db_inner = db_clone.clone();
let key_inner = key_clone.clone();
let _ = tokio::task::spawn_blocking(move || {
let write_txn = db_inner.begin_write().unwrap();
{
let mut table = write_txn.open_table(STORE_TABLE).unwrap();
table.insert(key_inner.as_str(), json_data.as_slice()).unwrap();
}
write_txn.commit().unwrap();
}).await;
}
});
Self {
key: key.to_string(),
db,
cache: RwLock::new(initial_data),
tx,
}
}
@@ -35,23 +52,22 @@ impl<T: DeserializeOwned + Default + Serialize + Clone + Send + 'static> Store<T
lock.clone()
}
pub fn read_with<F, R>(&self, f: F) -> R
where
F: FnOnce(&T) -> R,
{
let lock = self.cache.read().unwrap();
f(&lock)
}
pub fn modify<F: FnOnce(&mut T)>(&self, f: F) {
let (key, db, json_data) = {
let json_data = {
let mut lock = self.cache.write().unwrap();
f(&mut lock);
// Serialize while holding lock to avoid expensive deep clone of T
let json = serde_json::to_vec(&*lock).unwrap();
(self.key.clone(), self.db.clone(), json)
serde_json::to_vec(&*lock).unwrap()
};
tokio::task::spawn_blocking(move || {
let write_txn = db.begin_write().unwrap();
{
let mut table = write_txn.open_table(STORE_TABLE).unwrap();
table.insert(key.as_str(), json_data.as_slice()).unwrap();
}
write_txn.commit().unwrap();
});
let _ = self.tx.send(json_data);
}
}