use super::{DueTimer, Fired, TimerCtx};
use crate::rt::{BoxFuture, MaybeSend, MaybeSync};
use crate::store::{NamespaceStore, StoreError};
use std::collections::BTreeMap;
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct TimerKind(u8);
impl TimerKind {
#[must_use]
pub const fn new(kind: u8) -> Self {
Self(kind)
}
#[must_use]
pub fn get(self) -> u8 {
self.0
}
}
pub mod kinds {
pub const LEASE_SWEEP: super::TimerKind = super::TimerKind::new(1);
pub const TICKET_EXPIRY: super::TimerKind = super::TimerKind::new(2);
pub const RELAY: super::TimerKind = super::TimerKind::new(3);
pub const BACKUP: super::TimerKind = super::TimerKind::new(4);
pub const QUOTA_ROLLUP: super::TimerKind = super::TimerKind::new(5);
pub const VERIFY: super::TimerKind = super::TimerKind::new(7);
pub const OUTCOME_DELIVERY: super::TimerKind = super::TimerKind::new(8);
pub const RESERVATION_RECONCILE: super::TimerKind = super::TimerKind::new(9);
pub const PUBLISHED_VIEW: super::TimerKind = super::TimerKind::new(10);
pub const CONTENT_TAKEDOWN_REQUEST: super::TimerKind = super::TimerKind::new(13);
pub const CACHE_PURGE: super::TimerKind = super::TimerKind::new(11);
pub const PUBLICATION_RECHECK: super::TimerKind = super::TimerKind::new(12);
pub const TAKEDOWN_WORK: super::TimerKind = super::TimerKind::new(15);
#[cfg(feature = "test-faults")]
pub const TEST: super::TimerKind = super::TimerKind::new(0xFF);
}
pub trait TimerHandler<S: NamespaceStore>: MaybeSend + MaybeSync {
fn kind(&self) -> TimerKind;
fn max_per_tick(&self) -> Option<u32> {
None
}
fn fire<'a>(
&'a self,
ctx: &'a TimerCtx<'a, S>,
timer: &'a DueTimer,
) -> BoxFuture<'a, Result<Fired, StoreError>>;
}
pub struct TimerRegistry<'a, S> {
handlers: BTreeMap<TimerKind, Box<dyn TimerHandler<S> + 'a>>,
}
impl<'a, S: NamespaceStore> TimerRegistry<'a, S> {
#[must_use]
pub fn new() -> Self {
Self {
handlers: BTreeMap::new(),
}
}
#[must_use]
pub fn register(mut self, handler: impl TimerHandler<S> + 'a) -> Self {
let kind = handler.kind();
assert_ne!(kind.get(), 0, "timer kind zero is invalid");
assert!(
!self.handlers.contains_key(&kind),
"timer kind already registered"
);
self.handlers.insert(kind, Box::new(handler));
self
}
pub(super) fn get(&self, kind: TimerKind) -> Option<&dyn TimerHandler<S>> {
self.handlers.get(&kind).map(Box::as_ref)
}
}
impl<S: NamespaceStore> Default for TimerRegistry<'_, S> {
fn default() -> Self {
Self::new()
}
}
impl<S> core::fmt::Debug for TimerRegistry<'_, S> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_struct("TimerRegistry")
.field("kinds", &self.handlers.keys().collect::<Vec<_>>())
.finish()
}
}