use bromine::context::Context; use bromine::event::Event; use std::collections::HashMap; use std::sync::atomic::{AtomicUsize, Ordering}; use std::sync::Arc; use tokio::sync::RwLock; use trait_bound_typemap::{TypeMap, TypeMapKey}; pub async fn get_counter_from_context(ctx: &Context) -> CallCounter { let data = ctx.data.read().await; data.get::().unwrap().clone() } pub async fn increment_counter_for_event(ctx: &Context, event: &Event) { let data = ctx.data.read().await; let key_name = if let Some(namespace) = event.namespace() { format!("{}:{}", namespace, event.name()) } else { event.name().to_string() }; data.get::().unwrap().incr(&key_name).await; } pub struct CallCounterKey; impl TypeMapKey for CallCounterKey { type Value = CallCounter; } #[derive(Clone, Default, Debug)] pub struct CallCounter { inner: Arc>>, } impl CallCounter { pub async fn incr(&self, name: &str) { { let calls = self.inner.read().await; if let Some(call) = calls.get(name) { call.fetch_add(1, Ordering::Relaxed); return; } } { let mut calls = self.inner.write().await; calls.insert(name.to_string(), AtomicUsize::new(1)); } } pub async fn get(&self, name: &str) -> usize { let calls = self.inner.read().await; calls .get(name) .map(|n| n.load(Ordering::SeqCst)) .unwrap_or(0) } }