pub struct BlobCache { /* private fields */ }Expand description
Sharded, byte-bounded blob cache with optional durable L2 backing.
§Concurrency
BlobCache is Send + Sync. All public methods are safe to call from
multiple threads concurrently. Internal sharding ensures disjoint-key
contention does not serialize: independent keys land on independent
RwLock<Shard> instances, and the global indexes (namespace set, tag /
dependency maps) are read-mostly behind their own RwLocks.
BlobCache is not Clone — share ownership via Arc<BlobCache>.
§Blocking
All methods are synchronous. put may perform L2 disk I/O on the
calling thread when an L2 path is configured; tokio callers should wrap
put in spawn_blocking. get, exists, and the invalidate_*
family touch L2 only on rehydrate / delete paths.
Implementations§
Source§impl BlobCache
impl BlobCache
Sourcepub fn new(config: BlobCacheConfig) -> BlobCache
pub fn new(config: BlobCacheConfig) -> BlobCache
Infallible constructor. Panics if config.l2_path is set and the L2
file cannot be opened — use BlobCache::open_with_l2 instead for
configs that include an L2 path so boot errors are handled gracefully.
Sourcepub fn open_with_l2(config: BlobCacheConfig) -> Result<BlobCache, CacheError>
pub fn open_with_l2(config: BlobCacheConfig) -> Result<BlobCache, CacheError>
Fallible constructor for configs that include an L2 path.
Returns Err(CacheError::L2Io(...)) on invalid path, corrupt control
sidecar, or any other recoverable I/O failure — the process stays alive.
pub fn with_defaults() -> BlobCache
Sourcepub fn l2_path(&self) -> Option<&Path>
pub fn l2_path(&self) -> Option<&Path>
Path to the L2 metadata B+ tree directory, when L2 is enabled.
Used by the backup orchestrator (include_blob_cache=true) so it
can locate the on-disk L2 tree for tarball / per-file upload, and
by the runbook procedures in
docs/operations/blob-cache-backup-restore.md §2 / §3 to confirm
where on disk the cache lives.
pub fn put( &self, namespace: impl Into<String>, key: impl Into<String>, input: BlobCachePut, ) -> Result<(), CacheError>
pub fn get(&self, namespace: &str, key: &str) -> Option<BlobCacheHit>
Sourcepub fn exists(&self, namespace: &str, key: &str) -> CachePresence
pub fn exists(&self, namespace: &str, key: &str) -> CachePresence
Probe whether (namespace, key) is cached.
Returns a three-valued CachePresence:
Presentwhen an L1-resident entry is held for the key.Absentwhen the cache can authoritatively rule the key out: either no L2 is configured, or the per-namespace Bloom synopsis (no-false-negatives) says the key was never inserted into L2.MaybePresentwhen L1 missed but the Bloom synopsis cannot rule the key out. Callers that need an exact answer must follow up withget, which performs the authoritative metadata read and either rehydrates a hit or surfaces a genuine miss.
exists deliberately does NOT touch the L2 metadata B+ tree on a
MaybePresent answer — that is the whole reason the synopsis exists
(#146). The probabilistic answer is the cheap fast path; pay the
metadata-read cost only when you actually need the bytes.
Sourcepub fn invalidate_key(&self, namespace: &str, key: &str) -> usize
pub fn invalidate_key(&self, namespace: &str, key: &str) -> usize
Node-local invalidation for one exact cache key.
This does not propagate to replicas. Cluster-wide invalidation is a future contract; callers that need cross-node coherence must rely on the underlying write reaching each node and triggering local eviction there.
Sourcepub fn invalidate_prefix(&self, namespace: &str, prefix: &str) -> usize
pub fn invalidate_prefix(&self, namespace: &str, prefix: &str) -> usize
Node-local invalidation for keys with a namespace-local prefix.
Node-local batched invalidation for all entries carrying any of tags.
Locks each affected shard once per call, so a batched invalidation from a downstream adapter (#143) does not multiply lock acquisitions the way N singular calls would.
Sourcepub fn invalidate_dependencies(
&self,
namespace: &str,
dependencies: &[&str],
) -> usize
pub fn invalidate_dependencies( &self, namespace: &str, dependencies: &[&str], ) -> usize
Node-local batched invalidation for all entries carrying any of dependencies.
Sourcepub fn invalidate_tag(&self, namespace: &str, tag: &str) -> usize
👎Deprecated since 0.1.0: use invalidate_tags(namespace, &[tag]) for batched callers
pub fn invalidate_tag(&self, namespace: &str, tag: &str) -> usize
use invalidate_tags(namespace, &[tag]) for batched callers
Node-local invalidation for all entries carrying tag.
Sourcepub fn invalidate_dependency(&self, namespace: &str, dependency: &str) -> usize
👎Deprecated since 0.1.0: use invalidate_dependencies(namespace, &[dependency]) for batched callers
pub fn invalidate_dependency(&self, namespace: &str, dependency: &str) -> usize
use invalidate_dependencies(namespace, &[dependency]) for batched callers
Node-local invalidation for all entries carrying dependency.
Sourcepub fn invalidate_namespace(&self, namespace: &str) -> bool
pub fn invalidate_namespace(&self, namespace: &str) -> bool
O(1) foreground namespace flush.
The foreground path only bumps a namespace generation. Old entries become invisible immediately and are physically removed by later cache access or a future sweeper.
pub fn stats(&self) -> BlobCacheStats
Sourcepub fn enable_async_promotion(
self: &Arc<BlobCache>,
opts: PoolOpts,
) -> Arc<AsyncPromotionPool> ⓘ
pub fn enable_async_promotion( self: &Arc<BlobCache>, opts: PoolOpts, ) -> Arc<AsyncPromotionPool> ⓘ
Initialize the async L2->L1 promotion pool. Must be called on an
Arc<Self> so the executor closure can hold a Weak<Self> (no
reference cycle).
Idempotent on first call only — OnceLock semantics: a second call
returns the previously-installed pool unchanged. The returned Arc
can be used by callers that want to inspect metrics directly; most
callers should ignore it and read metrics via stats().
Sourcepub fn shutdown_async_promotion(&self)
pub fn shutdown_async_promotion(&self)
Drain and stop the async promotion pool, if enabled. Safe to call
from Drop impls / test teardown — no-op when the pool was never
initialized.
pub fn config(&self) -> &BlobCacheConfig
Trait Implementations§
Auto Trait Implementations§
impl !Freeze for BlobCache
impl !RefUnwindSafe for BlobCache
impl Send for BlobCache
impl Sync for BlobCache
impl Unpin for BlobCache
impl UnsafeUnpin for BlobCache
impl !UnwindSafe for BlobCache
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
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 moreSource§impl<T> IntoRequest<T> for T
impl<T> IntoRequest<T> for T
Source§fn into_request(self) -> Request<T>
fn into_request(self) -> Request<T>
T in a tonic::Request