use std::any::Any;
use std::sync::{Arc, RwLock};
use sofie_core::{Uuid, unpoisoned};
use crate::{Db, Driver};
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct ChangedRecord {
pub module: &'static str,
pub aggregate: &'static str,
pub id: Option<Uuid>,
}
pub trait CommitHook: Any + Send + Sync {
fn committed(&self, changes: &[ChangedRecord]);
}
pub fn add_commit_hook(db: &Db, hook: Arc<dyn CommitHook>) {
unpoisoned::write(&db.commit_hooks.0).push(hook);
}
#[must_use]
pub fn commit_hook<T: CommitHook>(db: &Db) -> Option<Arc<T>> {
let hooks = unpoisoned::read(&db.commit_hooks.0);
hooks.iter().find_map(|hook| {
let hook: Arc<dyn Any + Send + Sync> = hook.clone();
hook.downcast().ok()
})
}
#[must_use]
pub fn cache_driver(db: &Db) -> &dyn Driver {
db.driver()
}
#[derive(Default)]
pub(crate) struct CommitHooks(RwLock<Vec<Arc<dyn CommitHook>>>);
impl CommitHooks {
pub(crate) fn run(&self, changes: &[ChangedRecord]) {
if changes.is_empty() {
return;
}
let hooks = unpoisoned::read(&self.0);
for hook in hooks.iter() {
hook.committed(changes);
}
}
}