use crate::module::traits::{MempoolSize, ModuleHooks};
use std::sync::Arc;
use tokio::time::{timeout, Duration};
pub struct HookManager {
hooks: Vec<(String, Arc<dyn ModuleHooks>)>,
}
impl HookManager {
pub fn new() -> Self {
Self { hooks: Vec::new() }
}
pub fn register_hooks(&mut self, module_id: String, hooks: Arc<dyn ModuleHooks>) {
self.hooks.push((module_id, hooks));
}
pub fn unregister_hooks(&mut self, module_id: &str) {
self.hooks.retain(|(id, _)| id != module_id);
}
pub async fn get_fee_estimate_cached(&self, target_blocks: u32) -> Option<u64> {
for (module_id, hooks) in &self.hooks {
match timeout(
Duration::from_millis(100),
hooks.get_fee_estimate_cached(target_blocks),
)
.await
{
Ok(Ok(Some(estimate))) => {
tracing::debug!(
"Module {} provided cached fee estimate: {}",
module_id,
estimate
);
return Some(estimate);
}
Ok(Ok(None)) => {
continue;
}
Ok(Err(e)) => {
tracing::debug!("Module {} hook error: {}", module_id, e);
continue;
}
Err(_) => {
tracing::debug!("Module {} hook timeout", module_id);
continue;
}
}
}
None
}
pub async fn get_mempool_stats_cached(&self) -> Option<MempoolSize> {
for (module_id, hooks) in &self.hooks {
match timeout(Duration::from_millis(50), hooks.get_mempool_stats_cached()).await {
Ok(Ok(Some(stats))) => {
tracing::debug!("Module {} provided cached mempool stats", module_id);
return Some(stats);
}
Ok(Ok(None)) => {
continue;
}
Ok(Err(e)) => {
tracing::debug!("Module {} hook error: {}", module_id, e);
continue;
}
Err(_) => {
tracing::debug!("Module {} hook timeout", module_id);
continue;
}
}
}
None
}
}
impl Default for HookManager {
fn default() -> Self {
Self::new()
}
}