aa_cache/source.rs
1//! [`CacheSource`] — the store an [`L1Cache`](crate::L1Cache) loads from on a miss.
2
3use std::hash::Hash;
4
5use aa_core::storage::{AgentId, PolicyDocument, PolicyStore, Result};
6use async_trait::async_trait;
7
8/// The backing store an [`L1Cache`](crate::L1Cache) fronts.
9///
10/// Abstracts "load the value for a key" so the cache is generic over any store —
11/// `PolicyStore`, `SessionStore`, `CredentialStore`, … — without depending on a
12/// concrete one. The associated [`Key`](CacheSource::Key) and
13/// [`Value`](CacheSource::Value) become the cache's key and cached value types.
14#[async_trait]
15pub trait CacheSource: Send + Sync {
16 /// The key the source is addressed by; also the cache key.
17 type Key: Eq + Hash + Clone + Send + Sync;
18
19 /// The value the source returns; cloned out of the cache on a hit.
20 type Value: Clone + Send + Sync;
21
22 /// Load the value for `key` from the underlying store.
23 async fn load(&self, key: &Self::Key) -> Result<Self::Value>;
24}
25
26/// Every [`PolicyStore`] is a [`CacheSource`] keyed by [`AgentId`] returning a
27/// [`PolicyDocument`], so `L1Cache<P>` fronts any policy backend directly.
28#[async_trait]
29impl<P: PolicyStore> CacheSource for P {
30 type Key = AgentId;
31 type Value = PolicyDocument;
32
33 async fn load(&self, key: &AgentId) -> Result<PolicyDocument> {
34 self.get_policy(key).await
35 }
36}