Skip to main content

BlobCacheSweeper

Struct BlobCacheSweeper 

Source
pub struct BlobCacheSweeper;
Expand description

Stateless namespace for sweeper operations against a BlobCache.

The sweeper holds no state of its own; every method is a free-function over &BlobCache. This keeps the surface easy to call from admin handlers, the runtime scheduler, and tests without owning a sweeper instance.

Implementations§

Source§

impl BlobCacheSweeper

Source

pub fn sweep_expired(cache: &BlobCache, limit: SweepLimit) -> SweepReport

Bounded sweep of expired L1 entries.

Walks the L1 entries (across shards) checking Entry::is_expired_at(now), and evicts expired ones via BlobCache::invalidate_key. Honors limit precisely.

§Concurrency

Concurrent reads on the cache MUST NOT block. Per-shard locks are taken only for the brief windows that BlobCache::invalidate_key needs them; readers on other shards run unimpeded.

§Current implementation status

Today this is bounded scaffolding: it sets up the time/entries budget and returns a zero-work report. The actual L1 walk requires a public iteration accessor on BlobCache (see flag #2 at the top of this module). Once that lands, the body becomes:

cache.for_each_l1_entry(|namespace, key, view| {
    if budget.exhausted() { return ControlFlow::Break(()); }
    report.entries_scanned += 1;
    if view.is_expired_at(now_ms) {
        let bytes = view.size as u64;
        if cache.invalidate_key(namespace, key) > 0 {
            report.entries_evicted += 1;
            report.bytes_reclaimed += bytes;
            accumulate_namespace(&mut report, namespace, bytes);
        }
    }
    budget.tick()
});
Source

pub fn reclaim_orphans(cache: &BlobCache, limit: SweepLimit) -> OrphanReport

Bounded reclamation of L2 orphan blob chains.

Orphan chains arise when a writer flushes the blob bytes to L2 pages but is killed before the metadata B+ tree commit (see the WAL-ordering note in docs/perf/blob-cache-l2-spike.md). Recovery cannot tell these pages apart from a successful write without cross-checking the metadata catalog, so they accumulate as wasted L2 capacity until the sweeper reclaims them.

The algorithm (once accessor #2 lands):

  1. Walk the L2 free-list of allocated blob chains (cache.l2_blob_chains() — to-be-added).
  2. For each chain root, look up the metadata B+ tree (cache.for_each_l2_record) and check whether any record points at this root.
  3. Chains with no metadata reference are orphans — free their pages via the L2 API and accumulate bytes_reclaimed.
§Concurrency

Same contract as BlobCacheSweeper::sweep_expired.

Source

pub fn flush_namespace( cache: &BlobCache, namespace: &str, ) -> NamespaceFlushReport

Foreground-fast namespace flush.

Delegates to BlobCache::invalidate_namespace, which is O(1): it only bumps a per-namespace generation counter. Cached entries with the old generation become invisible immediately and are physically removed by later cache access or by BlobCacheSweeper::sweep_expired.

§Foreground-fast contract

Returns within ~100 µs typical. The elapsed_micros field on the returned NamespaceFlushReport makes the contract observable so admin endpoints can alert on regressions.

§Generation reporting

generation_before and generation_after are reported on a best-effort basis. Because BlobCache does not expose a public generation accessor, the sweeper reports them as (0, 0) when the flush call signals “namespace did not exist” and (0, 0) when it signals success — placeholder values until a current_generation public accessor is added (see flag #2). The namespace and elapsed_micros fields are accurate today.

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