Skip to main content

BlobCache

Struct BlobCache 

Source
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

Source

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.

Source

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.

Source

pub fn with_defaults() -> BlobCache

Source

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.

Source

pub fn put( &self, namespace: impl Into<String>, key: impl Into<String>, input: BlobCachePut, ) -> Result<(), CacheError>

Source

pub fn get(&self, namespace: &str, key: &str) -> Option<BlobCacheHit>

Source

pub fn exists(&self, namespace: &str, key: &str) -> CachePresence

Probe whether (namespace, key) is cached.

Returns a three-valued CachePresence:

  • Present when an L1-resident entry is held for the key.
  • Absent when 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.
  • MaybePresent when L1 missed but the Bloom synopsis cannot rule the key out. Callers that need an exact answer must follow up with get, 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.

Source

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.

Source

pub fn invalidate_prefix(&self, namespace: &str, prefix: &str) -> usize

Node-local invalidation for keys with a namespace-local prefix.

Source

pub fn invalidate_tags(&self, namespace: &str, tags: &[&str]) -> usize

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.

Source

pub fn invalidate_dependencies( &self, namespace: &str, dependencies: &[&str], ) -> usize

Node-local batched invalidation for all entries carrying any of dependencies.

Source

pub fn invalidate_tag(&self, namespace: &str, tag: &str) -> usize

👎Deprecated since 0.1.0:

use invalidate_tags(namespace, &[tag]) for batched callers

Node-local invalidation for all entries carrying tag.

Source

pub fn invalidate_dependency(&self, namespace: &str, dependency: &str) -> usize

👎Deprecated since 0.1.0:

use invalidate_dependencies(namespace, &[dependency]) for batched callers

Node-local invalidation for all entries carrying dependency.

Source

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.

Source

pub fn stats(&self) -> BlobCacheStats

Source

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().

Source

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.

Source

pub fn config(&self) -> &BlobCacheConfig

Trait Implementations§

Source§

impl Default for BlobCache

Source§

fn default() -> BlobCache

Returns the “default value” for a type. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts 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 more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts 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
Source§

impl<T> IntoRequest<T> for T

Source§

fn into_request(self) -> Request<T>

Wrap the input message T in a tonic::Request
Source§

impl<L> LayerExt<L> for L

Source§

fn named_layer<S>(&self, service: S) -> Layered<<L as Layer<S>>::Service, S>
where L: Layer<S>,

Applies the layer to a service and wraps it in Layered.
Source§

impl<T> Pointable for T

Source§

const ALIGN: usize

The alignment of pointer.
Source§

type Init = T

The type for initializers.
Source§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
Source§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
Source§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
Source§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more