pub struct UsageAggregator { /* private fields */ }Expand description
Thread-safe, in-memory usage counter store with optional persistence backend.
Cheaply cloneable via Arc — all clones share the same underlying map.
§Persistence
By default, the aggregator uses NoopBackend and counters are lost on
restart. Pass a [RedisBackend] (or any UsageBackend impl) to
UsageAggregator::new_with_backend to enable durable storage.
let agg = UsageAggregator::new_with_backend(Arc::new(NoopBackend));§Example
use std::sync::Arc;
use fraiseql_server::usage::aggregator::UsageAggregator;
use fraiseql_server::usage::events::MutationAuditEvent;
let agg = Arc::new(UsageAggregator::new());
let event = MutationAuditEvent::new("create_user", "User", "create", "acme", "2026-05");
agg.record(&event);
let summary = agg.query("acme", "2026-05");
assert_eq!(summary.mutations["User"], 1);Implementations§
Source§impl UsageAggregator
impl UsageAggregator
Sourcepub fn new_with_backend(backend: Arc<dyn UsageBackend>) -> Self
pub fn new_with_backend(backend: Arc<dyn UsageBackend>) -> Self
Create an empty aggregator backed by the given persistence backend.
Sourcepub fn set_backend(&self, backend: Arc<dyn UsageBackend>)
pub fn set_backend(&self, backend: Arc<dyn UsageBackend>)
Replace the persistence backend at runtime.
Called during server startup to upgrade from the default NoopBackend
to a durable backend (e.g. PostgresBackend) once the database pool
is available. Any in-flight in-memory counters are preserved.
§Panics
Panics if the backend RwLock is poisoned (unrecoverable state).
Sourcepub fn record(&self, event: &MutationAuditEvent)
pub fn record(&self, event: &MutationAuditEvent)
Record one mutation audit event, incrementing the appropriate counter.
This method is lock-free on the hot path: it uses AtomicU64::fetch_add
after the initial shard lock in DashMap::entry.
Sourcepub fn query(&self, tenant_id: &str, period: &str) -> UsageSummary
pub fn query(&self, tenant_id: &str, period: &str) -> UsageSummary
Return the usage summary for a tenant and period.
Returns UsageSummary { mutations: {} } (never an error) when no events
have been recorded for the given (tenant_id, period) pair.
Sourcepub fn entry_count(&self) -> usize
pub fn entry_count(&self) -> usize
Return the total number of distinct counter entries (for monitoring).
Sourcepub async fn flush_to_backend(&self) -> Result<(), String>
pub async fn flush_to_backend(&self) -> Result<(), String>
Flush all current counters to the persistence backend.
A no-op when using the default NoopBackend.
§Errors
Propagates errors from the underlying UsageBackend::flush.
§Panics
Panics if the backend RwLock is poisoned (unrecoverable state).
Sourcepub async fn load_from_backend(&self) -> Result<(), String>
pub async fn load_from_backend(&self) -> Result<(), String>
Load persisted counters from the backend into the in-memory map.
Existing in-memory counters are merged (not replaced): the loaded value is added to any in-flight in-memory count so that events recorded between the last flush and this load are not lost.
§Errors
Propagates errors from the underlying UsageBackend::load.
§Panics
Panics if the backend RwLock is poisoned (unrecoverable state).
Trait Implementations§
Source§impl Debug for UsageAggregator
impl Debug for UsageAggregator
Auto Trait Implementations§
impl !Freeze for UsageAggregator
impl !RefUnwindSafe for UsageAggregator
impl Send for UsageAggregator
impl Sync for UsageAggregator
impl Unpin for UsageAggregator
impl UnsafeUnpin for UsageAggregator
impl UnwindSafe for UsageAggregator
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
impl<A, B, T> HttpServerConnExec<A, B> for Twhere
B: Body,
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more