pub struct RedisBackend<C>where
C: RedisConn,{ /* private fields */ }Expand description
L1 hot cache: content-addressed key → value, sub-ms hits, TTL/eviction-aware.
Generic over the RedisConn seam so it is fully testable against a mock.
Implementations§
Source§impl<C> RedisBackend<C>where
C: RedisConn,
impl<C> RedisBackend<C>where
C: RedisConn,
Sourcepub fn new(conn: C) -> RedisBackend<C>
pub fn new(conn: C) -> RedisBackend<C>
Wrap a RedisConn with no per-write TTL (entries are LRU-evicted by
the maxmemory band).
Sourcepub fn with_ttl(conn: C, ttl_secs: u64) -> RedisBackend<C>
pub fn with_ttl(conn: C, ttl_secs: u64) -> RedisBackend<C>
Wrap a RedisConn, stamping every write with a ttl_secs expiry.
Sourcepub fn with_max_value_bytes(self, max: usize) -> RedisBackend<C>
pub fn with_max_value_bytes(self, max: usize) -> RedisBackend<C>
Override the per-value byte cap (default
DEFAULT_REDIS_MAX_VALUE_BYTES).
Sourcepub fn max_value_bytes(&self) -> usize
pub fn max_value_bytes(&self) -> usize
The per-value byte cap this tier refuses beyond.
Trait Implementations§
Source§impl<C> NarRefIndex for RedisBackend<C>where
C: RedisConn,
The reverse index as one Redis key per edge.
impl<C> NarRefIndex for RedisBackend<C>where
C: RedisConn,
The reverse index as one Redis key per edge.
Edges carry no TTL, deliberately, even when narinfo/NAR writes do. An
edge that expired while the narinfo it describes is still live would be an
under-report, and an under-report authorizes deleting a NAR out from under
that narinfo. An edge that outlives its narinfo is an over-report, which
costs a retained NAR. The whole tier is still best-effort — Redis
maxmemory LRU can drop an edge regardless — which is why a
TieredBackend unions this tier’s answer with the
durable tiers’ rather than trusting it alone.
Source§fn record<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
nar_path: &'life1 str,
hash: &'life2 str,
) -> Pin<Box<dyn Future<Output = Result<(), StoreError>> + Send + 'async_trait>>where
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
RedisBackend<C>: 'async_trait,
fn record<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
nar_path: &'life1 str,
hash: &'life2 str,
) -> Pin<Box<dyn Future<Output = Result<(), StoreError>> + Send + 'async_trait>>where
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
RedisBackend<C>: 'async_trait,
Source§fn forget<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
nar_path: &'life1 str,
hash: &'life2 str,
) -> Pin<Box<dyn Future<Output = Result<(), StoreError>> + Send + 'async_trait>>where
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
RedisBackend<C>: 'async_trait,
fn forget<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
nar_path: &'life1 str,
hash: &'life2 str,
) -> Pin<Box<dyn Future<Output = Result<(), StoreError>> + Send + 'async_trait>>where
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
RedisBackend<C>: 'async_trait,
Ok(()). Read moreSource§fn referrers<'life0, 'life1, 'async_trait>(
&'life0 self,
nar_path: &'life1 str,
) -> Pin<Box<dyn Future<Output = Result<Vec<String>, StoreError>> + Send + 'async_trait>>where
'life0: 'async_trait,
'life1: 'async_trait,
RedisBackend<C>: 'async_trait,
fn referrers<'life0, 'life1, 'async_trait>(
&'life0 self,
nar_path: &'life1 str,
) -> Pin<Box<dyn Future<Output = Result<Vec<String>, StoreError>> + Send + 'async_trait>>where
'life0: 'async_trait,
'life1: 'async_trait,
RedisBackend<C>: 'async_trait,
nar_path, sorted and
deduplicated. Read moreSource§impl<C> StorageBackend for RedisBackend<C>where
C: RedisConn,
impl<C> StorageBackend for RedisBackend<C>where
C: RedisConn,
Source§fn put_nar<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
path: &'life1 str,
data: &'life2 [u8],
) -> Pin<Box<dyn Future<Output = Result<(), StoreError>> + Send + 'async_trait>>where
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
RedisBackend<C>: 'async_trait,
fn put_nar<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
path: &'life1 str,
data: &'life2 [u8],
) -> Pin<Box<dyn Future<Output = Result<(), StoreError>> + Send + 'async_trait>>where
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
RedisBackend<C>: 'async_trait,
Store a NAR in the hot tier, refusing anything over the cap.
The cap is checked against the slice’s length before the value ever reaches the wire, so an oversized NAR costs this tier nothing.
Source§fn nar_residency(&self) -> NarResidency
fn nar_residency(&self) -> NarResidency
O(min(nar, cap)). Redis has no streaming SET — a value is one
contiguous buffer by protocol — so this tier is bounded by a cap rather
than by a chunk. That is a real bound: see
DEFAULT_REDIS_MAX_VALUE_BYTES for why refusing is the correct
behavior for a best-effort hot tier.
Source§fn put_nar_stream<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
path: &'life1 str,
src: &'life2 dyn NarSource,
) -> Pin<Box<dyn Future<Output = Result<(), StoreError>> + Send + 'async_trait>>where
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
RedisBackend<C>: 'async_trait,
fn put_nar_stream<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
path: &'life1 str,
src: &'life2 dyn NarSource,
) -> Pin<Box<dyn Future<Output = Result<(), StoreError>> + Send + 'async_trait>>where
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
RedisBackend<C>: 'async_trait,
Drain the source only up to the cap, refusing the moment it is crossed.
The refusal is the load-bearing part: collection stops at the cap and the
remainder of the NAR is never read, so a 2 GiB NAR costs this tier
cap + one chunk and not 2 GiB. Without it, “L1 refuses oversized
values” would be a claim the code does not make.
Source§fn wipe_all<'life0, 'async_trait>(
&'life0 self,
) -> Pin<Box<dyn Future<Output = Result<usize, StoreError>> + Send + 'async_trait>>where
'life0: 'async_trait,
RedisBackend<C>: 'async_trait,
fn wipe_all<'life0, 'async_trait>(
&'life0 self,
) -> Pin<Box<dyn Future<Output = Result<usize, StoreError>> + Send + 'async_trait>>where
'life0: 'async_trait,
RedisBackend<C>: 'async_trait,
Complete L1 wipe: DEL every key under BOTH the narinfo and NAR prefixes
(a scoped clear — never FLUSHDB, which would blow away an unrelated
co-tenant of the same Redis db). Returns the narinfo key count removed.
Source§fn get_narinfo<'life0, 'life1, 'async_trait>(
&'life0 self,
hash: &'life1 str,
) -> Pin<Box<dyn Future<Output = Result<Option<String>, StoreError>> + Send + 'async_trait>>where
'life0: 'async_trait,
'life1: 'async_trait,
RedisBackend<C>: 'async_trait,
fn get_narinfo<'life0, 'life1, 'async_trait>(
&'life0 self,
hash: &'life1 str,
) -> Pin<Box<dyn Future<Output = Result<Option<String>, StoreError>> + Send + 'async_trait>>where
'life0: 'async_trait,
'life1: 'async_trait,
RedisBackend<C>: 'async_trait,
Source§fn put_narinfo_record<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
hash: &'life1 str,
content: &'life2 str,
) -> Pin<Box<dyn Future<Output = Result<(), StoreError>> + Send + 'async_trait>>where
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
RedisBackend<C>: 'async_trait,
fn put_narinfo_record<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
hash: &'life1 str,
content: &'life2 str,
) -> Pin<Box<dyn Future<Output = Result<(), StoreError>> + Send + 'async_trait>>where
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
RedisBackend<C>: 'async_trait,
Source§fn delete_narinfo_record<'life0, 'life1, 'async_trait>(
&'life0 self,
hash: &'life1 str,
) -> Pin<Box<dyn Future<Output = Result<(), StoreError>> + Send + 'async_trait>>where
'life0: 'async_trait,
'life1: 'async_trait,
RedisBackend<C>: 'async_trait,
fn delete_narinfo_record<'life0, 'life1, 'async_trait>(
&'life0 self,
hash: &'life1 str,
) -> Pin<Box<dyn Future<Output = Result<(), StoreError>> + Send + 'async_trait>>where
'life0: 'async_trait,
'life1: 'async_trait,
RedisBackend<C>: 'async_trait,
Ok(()). Read moreSource§fn delete_nar_record<'life0, 'life1, 'async_trait>(
&'life0 self,
nar_path: &'life1 str,
) -> Pin<Box<dyn Future<Output = Result<(), StoreError>> + Send + 'async_trait>>where
'life0: 'async_trait,
'life1: 'async_trait,
RedisBackend<C>: 'async_trait,
fn delete_nar_record<'life0, 'life1, 'async_trait>(
&'life0 self,
nar_path: &'life1 str,
) -> Pin<Box<dyn Future<Output = Result<(), StoreError>> + Send + 'async_trait>>where
'life0: 'async_trait,
'life1: 'async_trait,
RedisBackend<C>: 'async_trait,
Source§fn nar_ref_index(&self) -> &dyn NarRefIndex
fn nar_ref_index(&self) -> &dyn NarRefIndex
Source§fn get_nar<'life0, 'life1, 'async_trait>(
&'life0 self,
path: &'life1 str,
) -> Pin<Box<dyn Future<Output = Result<Option<Vec<u8>>, StoreError>> + Send + 'async_trait>>where
'life0: 'async_trait,
'life1: 'async_trait,
RedisBackend<C>: 'async_trait,
fn get_nar<'life0, 'life1, 'async_trait>(
&'life0 self,
path: &'life1 str,
) -> Pin<Box<dyn Future<Output = Result<Option<Vec<u8>>, StoreError>> + Send + 'async_trait>>where
'life0: 'async_trait,
'life1: 'async_trait,
RedisBackend<C>: 'async_trait,
Source§fn list_narinfos<'life0, 'async_trait>(
&'life0 self,
) -> Pin<Box<dyn Future<Output = Result<Vec<String>, StoreError>> + Send + 'async_trait>>where
'life0: 'async_trait,
RedisBackend<C>: 'async_trait,
fn list_narinfos<'life0, 'async_trait>(
&'life0 self,
) -> Pin<Box<dyn Future<Output = Result<Vec<String>, StoreError>> + Send + 'async_trait>>where
'life0: 'async_trait,
RedisBackend<C>: 'async_trait,
Source§fn get_nar_stream<'life0, 'life1, 'async_trait>(
&'life0 self,
path: &'life1 str,
) -> Pin<Box<dyn Future<Output = Result<Option<Pin<Box<dyn Stream<Item = Result<Bytes, StoreError>> + Send>>>, StoreError>> + Send + 'async_trait>>where
'life0: 'async_trait,
'life1: 'async_trait,
Self: 'async_trait,
fn get_nar_stream<'life0, 'life1, 'async_trait>(
&'life0 self,
path: &'life1 str,
) -> Pin<Box<dyn Future<Output = Result<Option<Pin<Box<dyn Stream<Item = Result<Bytes, StoreError>> + Send>>>, StoreError>> + Send + 'async_trait>>where
'life0: 'async_trait,
'life1: 'async_trait,
Self: 'async_trait,
Source§fn put_narinfo<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
hash: &'life1 str,
content: &'life2 str,
) -> Pin<Box<dyn Future<Output = Result<(), StoreError>> + Send + 'async_trait>>where
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
Self: 'async_trait,
fn put_narinfo<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
hash: &'life1 str,
content: &'life2 str,
) -> Pin<Box<dyn Future<Output = Result<(), StoreError>> + Send + 'async_trait>>where
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
Self: 'async_trait,
Source§fn advertised_nar<'life0, 'life1, 'async_trait>(
&'life0 self,
hash: &'life1 str,
) -> Pin<Box<dyn Future<Output = Result<Option<String>, StoreError>> + Send + 'async_trait>>where
'life0: 'async_trait,
'life1: 'async_trait,
Self: 'async_trait,
fn advertised_nar<'life0, 'life1, 'async_trait>(
&'life0 self,
hash: &'life1 str,
) -> Pin<Box<dyn Future<Output = Result<Option<String>, StoreError>> + Send + 'async_trait>>where
'life0: 'async_trait,
'life1: 'async_trait,
Self: 'async_trait,
Source§fn delete<'life0, 'life1, 'async_trait>(
&'life0 self,
hash: &'life1 str,
) -> Pin<Box<dyn Future<Output = Result<(), StoreError>> + Send + 'async_trait>>where
'life0: 'async_trait,
'life1: 'async_trait,
Self: 'async_trait,
fn delete<'life0, 'life1, 'async_trait>(
&'life0 self,
hash: &'life1 str,
) -> Pin<Box<dyn Future<Output = Result<(), StoreError>> + Send + 'async_trait>>where
'life0: 'async_trait,
'life1: 'async_trait,
Self: 'async_trait,
Source§fn reindex_nar_refs<'life0, 'async_trait>(
&'life0 self,
) -> Pin<Box<dyn Future<Output = Result<usize, StoreError>> + Send + 'async_trait>>where
'life0: 'async_trait,
Self: 'async_trait,
fn reindex_nar_refs<'life0, 'async_trait>(
&'life0 self,
) -> Pin<Box<dyn Future<Output = Result<usize, StoreError>> + Send + 'async_trait>>where
'life0: 'async_trait,
Self: 'async_trait,
Auto Trait Implementations§
impl<C> Freeze for RedisBackend<C>where
C: Freeze,
impl<C> RefUnwindSafe for RedisBackend<C>where
C: RefUnwindSafe,
impl<C> Send for RedisBackend<C>
impl<C> Sync for RedisBackend<C>
impl<C> Unpin for RedisBackend<C>where
C: Unpin,
impl<C> UnsafeUnpin for RedisBackend<C>where
C: UnsafeUnpin,
impl<C> UnwindSafe for RedisBackend<C>where
C: UnwindSafe,
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<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
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