Skip to main content

PgCacheConn

Trait PgCacheConn 

Source
pub trait PgCacheConn: Send + Sync {
    // Required methods
    fn select<'life0, 'life1, 'async_trait>(
        &'life0 self,
        table: PgTable,
        key: &'life1 str,
    ) -> Pin<Box<dyn Future<Output = Result<Option<Vec<u8>>, StoreError>> + Send + 'async_trait>>
       where 'life0: 'async_trait,
             'life1: 'async_trait,
             Self: 'async_trait;
    fn upsert<'life0, 'life1, 'life2, 'async_trait>(
        &'life0 self,
        table: PgTable,
        key: &'life1 str,
        value: &'life2 [u8],
    ) -> Pin<Box<dyn Future<Output = Result<(), StoreError>> + Send + 'async_trait>>
       where 'life0: 'async_trait,
             'life1: 'async_trait,
             'life2: 'async_trait,
             Self: 'async_trait;
    fn delete<'life0, 'life1, 'async_trait>(
        &'life0 self,
        table: PgTable,
        key: &'life1 str,
    ) -> Pin<Box<dyn Future<Output = Result<(), StoreError>> + Send + 'async_trait>>
       where 'life0: 'async_trait,
             'life1: 'async_trait,
             Self: 'async_trait;
    fn keys<'life0, 'async_trait>(
        &'life0 self,
        table: PgTable,
    ) -> Pin<Box<dyn Future<Output = Result<Vec<String>, StoreError>> + Send + 'async_trait>>
       where 'life0: 'async_trait,
             Self: 'async_trait;
    fn keys_with_prefix<'life0, 'life1, 'async_trait>(
        &'life0 self,
        table: PgTable,
        prefix: &'life1 str,
    ) -> Pin<Box<dyn Future<Output = Result<Vec<String>, StoreError>> + Send + 'async_trait>>
       where 'life0: 'async_trait,
             'life1: 'async_trait,
             Self: 'async_trait;
    fn clear<'life0, 'async_trait>(
        &'life0 self,
        table: PgTable,
    ) -> Pin<Box<dyn Future<Output = Result<u64, StoreError>> + Send + 'async_trait>>
       where 'life0: 'async_trait,
             Self: 'async_trait;
    fn upsert_nar_chunk<'life0, 'life1, 'life2, 'async_trait>(
        &'life0 self,
        key: &'life1 str,
        seq: i32,
        value: &'life2 [u8],
    ) -> Pin<Box<dyn Future<Output = Result<(), StoreError>> + Send + 'async_trait>>
       where 'life0: 'async_trait,
             'life1: 'async_trait,
             'life2: 'async_trait,
             Self: 'async_trait;
    fn select_nar_chunk<'life0, 'life1, 'async_trait>(
        &'life0 self,
        key: &'life1 str,
        seq: i32,
    ) -> Pin<Box<dyn Future<Output = Result<Option<Vec<u8>>, StoreError>> + Send + 'async_trait>>
       where 'life0: 'async_trait,
             'life1: 'async_trait,
             Self: 'async_trait;
    fn delete_nar_chunks<'life0, 'life1, 'async_trait>(
        &'life0 self,
        key: &'life1 str,
    ) -> Pin<Box<dyn Future<Output = Result<(), StoreError>> + Send + 'async_trait>>
       where 'life0: 'async_trait,
             'life1: 'async_trait,
             Self: 'async_trait;
    fn clear_nar_chunks<'life0, 'async_trait>(
        &'life0 self,
    ) -> Pin<Box<dyn Future<Output = Result<u64, StoreError>> + Send + 'async_trait>>
       where 'life0: 'async_trait,
             Self: 'async_trait;
    fn select_nar_window<'life0, 'life1, 'async_trait>(
        &'life0 self,
        key: &'life1 str,
        offset: i64,
        len: i32,
    ) -> Pin<Box<dyn Future<Output = Result<Option<(Vec<u8>, i64)>, StoreError>> + Send + 'async_trait>>
       where 'life0: 'async_trait,
             'life1: 'async_trait,
             Self: 'async_trait;

    // Provided method
    fn ensure_schema<'life0, 'async_trait>(
        &'life0 self,
    ) -> Pin<Box<dyn Future<Output = Result<(), StoreError>> + Send + 'async_trait>>
       where 'life0: 'async_trait,
             Self: 'async_trait { ... }
}
Expand description

The minimal typed Postgres row-verb surface PgStorageBackend depends on.

This is the injectable Environment seam: a real implementation ([SqlxPgCacheConn], postgres feature) talks to a live Postgres pool; tests substitute an in-memory mock. Keeping the surface this small means the whole L2 mapping is proven against a mock, and the only unmocked code is the thin SQL translation.

Required Methods§

Source

fn select<'life0, 'life1, 'async_trait>( &'life0 self, table: PgTable, key: &'life1 str, ) -> Pin<Box<dyn Future<Output = Result<Option<Vec<u8>>, StoreError>> + Send + 'async_trait>>
where 'life0: 'async_trait, 'life1: 'async_trait, Self: 'async_trait,

SELECT value FROM <table> WHERE key = $1 — raw bytes, or Ok(None) on a missing row.

Source

fn upsert<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, table: PgTable, key: &'life1 str, value: &'life2 [u8], ) -> Pin<Box<dyn Future<Output = Result<(), StoreError>> + Send + 'async_trait>>
where 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait, Self: 'async_trait,

Upsert (INSERT … ON CONFLICT (key) DO UPDATE) — idempotent by key; a re-put of a content-addressed key overwrites with identical bytes.

Source

fn delete<'life0, 'life1, 'async_trait>( &'life0 self, table: PgTable, key: &'life1 str, ) -> Pin<Box<dyn Future<Output = Result<(), StoreError>> + Send + 'async_trait>>
where 'life0: 'async_trait, 'life1: 'async_trait, Self: 'async_trait,

DELETE FROM <table> WHERE key = $1 — idempotent; deleting an absent key is Ok(()).

Source

fn keys<'life0, 'async_trait>( &'life0 self, table: PgTable, ) -> Pin<Box<dyn Future<Output = Result<Vec<String>, StoreError>> + Send + 'async_trait>>
where 'life0: 'async_trait, Self: 'async_trait,

SELECT key FROM <table> — the authoritative full key set (this is a durable tier, not a partial hot cache).

Source

fn keys_with_prefix<'life0, 'life1, 'async_trait>( &'life0 self, table: PgTable, prefix: &'life1 str, ) -> Pin<Box<dyn Future<Output = Result<Vec<String>, StoreError>> + Send + 'async_trait>>
where 'life0: 'async_trait, 'life1: 'async_trait, Self: 'async_trait,

SELECT key FROM <table> WHERE starts_with(key, $1) — the key set under one prefix.

REQUIRED, not defaulted, and not “fetch keys and filter in Rust”: the reverse-index lookup runs once per delete, and filtering client-side would make it O(every edge in the cache) per call while the primary-key btree can answer it as a range scan.

Source

fn clear<'life0, 'async_trait>( &'life0 self, table: PgTable, ) -> Pin<Box<dyn Future<Output = Result<u64, StoreError>> + Send + 'async_trait>>
where 'life0: 'async_trait, Self: 'async_trait,

DELETE FROM <table> — clear the whole table, returning the row count removed. The typed whole-store wipe primitive (the inverse of a warm push); reaches NAR rows a per-key delete cannot.

Source

fn upsert_nar_chunk<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, key: &'life1 str, seq: i32, value: &'life2 [u8], ) -> Pin<Box<dyn Future<Output = Result<(), StoreError>> + Send + 'async_trait>>
where 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait, Self: 'async_trait,

Upsert one bounded chunk of a NAR. seq is 0..n, or [CHUNK_MARKER_SEQ] for the completeness marker.

Source

fn select_nar_chunk<'life0, 'life1, 'async_trait>( &'life0 self, key: &'life1 str, seq: i32, ) -> Pin<Box<dyn Future<Output = Result<Option<Vec<u8>>, StoreError>> + Send + 'async_trait>>
where 'life0: 'async_trait, 'life1: 'async_trait, Self: 'async_trait,

Read one chunk back. Ok(None) when that (key, seq) row is absent.

Source

fn delete_nar_chunks<'life0, 'life1, 'async_trait>( &'life0 self, key: &'life1 str, ) -> Pin<Box<dyn Future<Output = Result<(), StoreError>> + Send + 'async_trait>>
where 'life0: 'async_trait, 'life1: 'async_trait, Self: 'async_trait,

Delete every chunk (and the marker) of key. Idempotent.

Source

fn clear_nar_chunks<'life0, 'async_trait>( &'life0 self, ) -> Pin<Box<dyn Future<Output = Result<u64, StoreError>> + Send + 'async_trait>>
where 'life0: 'async_trait, Self: 'async_trait,

DELETE FROM sui_cache_nar_chunk — clear the chunk table, returning the row count removed.

Source

fn select_nar_window<'life0, 'life1, 'async_trait>( &'life0 self, key: &'life1 str, offset: i64, len: i32, ) -> Pin<Box<dyn Future<Output = Result<Option<(Vec<u8>, i64)>, StoreError>> + Send + 'async_trait>>
where 'life0: 'async_trait, 'life1: 'async_trait, Self: 'async_trait,

Read a bounded window of a legacy whole-value NAR row, returning (window_bytes, total_byte_length); Ok(None) when the row is absent.

offset is 1-based (Postgres substr semantics). This exists so rows written by the pre-streaming build — every NAR already in the production database — can be served without materializing them. Without it the read path would stay unbounded until the cache happened to turn over.

Provided Methods§

Source

fn ensure_schema<'life0, 'async_trait>( &'life0 self, ) -> Pin<Box<dyn Future<Output = Result<(), StoreError>> + Send + 'async_trait>>
where 'life0: 'async_trait, Self: 'async_trait,

Idempotently (re-)create every table this connection serves.

This is the self-heal verb. PgStorageBackend calls it when a row verb reports StoreError::SchemaMissing, then retries the verb once — so a durable tier that comes back on an empty volume repairs itself on the next request instead of erroring until someone restarts the process.

It must be safe to call at any time, any number of times (CREATE TABLE IF NOT EXISTS), including concurrently.

The default is a no-op, so a backend whose schema cannot go missing (an in-memory mock) needs no implementation. A backend that does return SchemaMissing must override this — otherwise the retry re-runs against the same absent schema and fails identically, which is still correct, just unhealed.

§Errors

Returns an error if the DDL cannot be executed.

Dyn Compatibility§

This trait is dyn compatible.

In older versions of Rust, dyn compatibility was called "object safety".

Implementors§