use super::types::{Hook, HookEvent};
use crate::store::Store;
use anyhow::Result;
use std::collections::HashMap;
use std::sync::Arc;
use tokio::sync::RwLock;
pub struct HookRegistry {
hooks: Arc<RwLock<HashMap<Arc<str>, Hook>>>,
event_hooks: Arc<RwLock<HashMap<HookEvent, Vec<Arc<str>>>>>,
store: Option<Arc<Store>>,
}
impl HookRegistry {
pub fn new() -> Self {
Self {
hooks: Arc::new(RwLock::new(HashMap::new())),
event_hooks: Arc::new(RwLock::new(HashMap::new())),
store: None,
}
}
pub fn with_store(store: Arc<Store>) -> Self {
Self {
hooks: Arc::new(RwLock::new(HashMap::new())),
event_hooks: Arc::new(RwLock::new(HashMap::new())),
store: Some(store),
}
}
pub async fn register(&self, hook: Hook) -> Result<Arc<str>> {
let id = hook.id.clone();
let event = hook.event.clone();
let event_name = event.to_string();
{
let mut hooks = self.hooks.write().await;
hooks.insert(id.clone(), hook);
}
{
let mut event_hooks = self.event_hooks.write().await;
let hooks_for_event = event_hooks.entry(event).or_insert_with(Vec::new);
if !hooks_for_event.contains(&id) {
hooks_for_event.push(id.clone());
}
}
tracing::info!("Hook '{}' registered for event '{}'", id, event_name);
Ok(id)
}
pub async fn unregister(&self, id: &str) -> Result<bool> {
let mut hooks = self.hooks.write().await;
if let Some(hook) = hooks.remove(id) {
let mut event_hooks = self.event_hooks.write().await;
if let Some(hooks_for_event) = event_hooks.get_mut(&hook.event) {
hooks_for_event.retain(|h| h.as_ref() != id);
}
tracing::info!("Hook '{}' unregistered", id);
Ok(true)
} else {
Ok(false)
}
}
pub async fn get(&self, id: &str) -> Option<Hook> {
let hooks = self.hooks.read().await;
hooks.get(id).cloned()
}
pub async fn list(&self) -> Vec<Hook> {
let hooks = self.hooks.read().await;
hooks.values().cloned().collect()
}
pub async fn get_hooks_for_event(&self, event: &HookEvent) -> Vec<Hook> {
let event_hooks = self.event_hooks.read().await;
let hooks = self.hooks.read().await;
let mut result = Vec::new();
if let Some(hook_ids) = event_hooks.get(event) {
for id in hook_ids {
if let Some(hook) = hooks.get(id) {
if hook.enabled {
result.push(hook.clone());
}
}
}
}
result.sort_by_key(|h| h.priority);
result
}
pub async fn list_events(&self) -> Vec<HookEvent> {
let event_hooks = self.event_hooks.read().await;
event_hooks.keys().cloned().collect()
}
pub async fn set_enabled(&self, id: &str, enabled: bool) -> Result<bool> {
let mut hooks = self.hooks.write().await;
if let Some(hook) = hooks.get_mut(id) {
hook.enabled = enabled;
Ok(true)
} else {
Ok(false)
}
}
}
impl Default for HookRegistry {
fn default() -> Self {
Self::new()
}
}