use std::sync::Arc;
use std::sync::atomic::{AtomicBool, AtomicU64, Ordering};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum CacheDomain {
GatewayPolicy,
Authz,
JtiRevocation,
}
impl CacheDomain {
pub const ALL: [Self; 3] = [Self::GatewayPolicy, Self::Authz, Self::JtiRevocation];
#[must_use]
pub const fn label(self) -> &'static str {
match self {
Self::GatewayPolicy => "gateway_policy",
Self::Authz => "authz",
Self::JtiRevocation => "jti_revocation",
}
}
#[must_use]
pub fn parse(label: &str) -> Option<Self> {
Self::ALL.into_iter().find(|domain| domain.label() == label)
}
const fn slot(self) -> usize {
match self {
Self::GatewayPolicy => 0,
Self::Authz => 1,
Self::JtiRevocation => 2,
}
}
}
#[derive(Debug, Clone, Default)]
pub struct CacheEpochs {
inner: Arc<EpochSlots>,
}
#[derive(Debug, Default)]
struct EpochSlots {
slots: [AtomicU64; 3],
relay_live: AtomicBool,
}
impl CacheEpochs {
#[must_use]
pub fn new() -> Self {
Self::default()
}
#[must_use]
pub fn current(&self, domain: CacheDomain) -> u64 {
self.inner.slots[domain.slot()].load(Ordering::Acquire)
}
pub fn advance(&self, domain: CacheDomain) -> u64 {
self.inner.slots[domain.slot()].fetch_add(1, Ordering::AcqRel) + 1
}
#[must_use]
pub fn relay_live(&self) -> bool {
self.inner.relay_live.load(Ordering::Acquire)
}
pub fn set_relay_live(&self, live: bool) {
self.inner.relay_live.store(live, Ordering::Release);
}
pub fn advance_all(&self) {
for domain in CacheDomain::ALL {
self.advance(domain);
}
}
}