Skip to main content

TieredStorage

Struct TieredStorage 

Source
pub struct TieredStorage<Hot, Cold> { /* private fields */ }
Expand description

Two-tier cache storage: a fast hot tier over a durable cold tier.

TieredStorage layers two backends: a Hot tier serving the working set from fast storage and a Cold tier holding the larger, durable set. It is itself a CacheStorage, so it drops in wherever a single backend would go — the headline pairing is an InMemoryStorage hot tier over a FileSystemStorage cold tier, but any two backends compose.

Clone is available when both tiers are Clone, and shares their backing storage.

§Runtime

The write path finishes asynchronously (see below), so a TieredStorage is constructed with the Runtime it spawns that background work on — and it must be the runtime actually driving the process, or the flush never makes progress. Construct the adapter for your runtime directly (for example trillium_smol::SmolRuntime::default() or trillium_tokio::TokioRuntime::default()); on a client you can instead take it from the connector with client.connector().runtime(). The tiered_cache example wires this up end to end.

§Read path

get consults the hot tier first and, on a hit, serves from it alone. On a hot miss it reads the cold tier; opening a cold entry promotes it, streaming the body to the reader and into the hot tier at once (the same teeing used on the origin→user+storage path), so the working set migrates into fast storage as it is served. A hot tier emptied by a restart repopulates from cold as entries are read.

The hot-first lookup assumes the hot tier evicts a whole CacheKey at once — all Vary variants of a URL together — so a hot hit implies the full variant set for that key is present. InMemoryStorage satisfies this. A hot tier that evicts individual variants could leave siblings only in cold and hide them behind a hot hit; pair TieredStorage with a whole-key-eviction hot tier.

§Write path

put writes the body into the hot tier as it streams, then finalizing the entry spawns a background task that copies it into the cold tier — a write-back. The hot tier is populated synchronously; cold durability follows shortly after, off the request path. A crash in that window loses the not-yet-flushed entry, which for a cache means only an extra origin fetch. Because cold ends up holding every stored entry, evicting from hot only drops a fast-path copy — the entry stays served from cold and re-promotes on its next read.

§Policy refresh

A 304 revalidation refreshes the policy on whichever tier served the entry. After a hot eviction a request may fall through to a cold copy carrying the pre-refresh policy and revalidate once more; the content served is always correct.

Implementations§

Source§

impl<Hot, Cold> TieredStorage<Hot, Cold>

Source

pub fn new(hot: Hot, cold: Cold, runtime: impl RuntimeTrait) -> Self

Compose hot and cold into a tiered storage, spawning background write-back onto runtime. Lookups and promotions favor hot; every stored entry is flushed through to cold.

Pass the runtime the surrounding server or client already runs on.

Source

pub fn hot(&self) -> &Hot

Borrow the hot tier.

Source

pub fn cold(&self) -> &Cold

Borrow the cold tier.

Trait Implementations§

Source§

impl<Hot, Cold> CacheStorage for TieredStorage<Hot, Cold>
where Hot: CacheStorage + Clone, Cold: CacheStorage + Clone,

Source§

type StoredEntry = TieredEntry<Hot, Cold>

Concrete entry type returned by get.
Source§

type PutHandle = TieredPutHandle<Hot, Cold>

Streaming writer returned by put.
Source§

async fn get(&self, key: &CacheKey) -> Vec<Self::StoredEntry>

Fetch all entries stored under key. Returns an empty vec when the key has no entries.
Source§

async fn put( &self, key: CacheKey, policy: CachePolicy, ) -> Result<Self::PutHandle>

Open a streaming insert for key with the supplied policy. Returns a PutHandle that the caller writes body bytes into, then closes with PutHandle::finalize. If an existing entry has the same Vary signature, finalize replaces it; otherwise the new entry is appended. Read more
Source§

async fn invalidate(&self, key: &CacheKey)

Remove all entries stored under key.
Source§

impl<Hot: Clone, Cold: Clone> Clone for TieredStorage<Hot, Cold>

Source§

fn clone(&self) -> Self

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl<Hot: CacheStorage, Cold: CacheStorage> Debug for TieredStorage<Hot, Cold>

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

§

impl<Hot, Cold> !RefUnwindSafe for TieredStorage<Hot, Cold>

§

impl<Hot, Cold> !UnwindSafe for TieredStorage<Hot, Cold>

§

impl<Hot, Cold> Freeze for TieredStorage<Hot, Cold>
where Hot: Freeze, Cold: Freeze,

§

impl<Hot, Cold> Send for TieredStorage<Hot, Cold>
where Hot: Send, Cold: Send,

§

impl<Hot, Cold> Sync for TieredStorage<Hot, Cold>
where Hot: Sync, Cold: Sync,

§

impl<Hot, Cold> Unpin for TieredStorage<Hot, Cold>
where Hot: Unpin, Cold: Unpin,

§

impl<Hot, Cold> UnsafeUnpin for TieredStorage<Hot, Cold>
where Hot: UnsafeUnpin, Cold: UnsafeUnpin,

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> ArchivePointee for T

Source§

type ArchivedMetadata = ()

The archived version of the pointer metadata for this type.
Source§

fn pointer_metadata( _: &<T as ArchivePointee>::ArchivedMetadata, ) -> <T as Pointee>::Metadata

Converts some archived metadata to the pointer metadata for itself.
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> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

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> LayoutRaw for T

Source§

fn layout_raw(_: <T as Pointee>::Metadata) -> Result<Layout, LayoutError>

Returns the layout of the type.
Source§

impl<T, N1, N2> Niching<NichedOption<T, N1>> for N2
where T: SharedNiching<N1, N2>, N1: Niching<T>, N2: Niching<T>,

Source§

unsafe fn is_niched(niched: *const NichedOption<T, N1>) -> bool

Returns whether the given value has been niched. Read more
Source§

fn resolve_niched(out: Place<NichedOption<T, N1>>)

Writes data to out indicating that a T is niched.
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> Pointee for T

Source§

type Metadata = ()

The metadata type for pointers and references to this type.
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
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.