pub trait PoolStateStore: Send + Sync {
// Required methods
fn load_all(&self) -> Result<Vec<LaneState>, StoreError>;
fn record(&self, state: &LaneState) -> Result<(), StoreError>;
fn forget(&self, key: LaneKey) -> Result<(), StoreError>;
fn get(&self, key: LaneKey) -> Result<Option<LaneState>, StoreError>;
// Provided methods
fn flush(&self) -> Result<(), StoreError> { ... }
fn set_registered_until(
&self,
key: LaneKey,
registered_until: u64,
) -> Result<(), StoreError> { ... }
fn set_paid_cumulative(
&self,
key: LaneKey,
paid_cumulative: U256,
) -> Result<(), StoreError> { ... }
}Expand description
Durable backing store for LaneState, keyed by LaneKey.
The trait is intentionally synchronous. record and forget mutate a working
set and MAY defer durability to flush; an
implementation is equally free to commit inside record instead, so the cost
of any one call is the implementation’s to document. A caller on a Tokio
runtime therefore decides per implementation what to run from
tokio::task::spawn_blocking: against the runtime’s redb store, record and
forget are map writes cheap enough to call inline, and flush is the one
that fsyncs.
Required Methods§
Sourcefn load_all(&self) -> Result<Vec<LaneState>, StoreError>
fn load_all(&self) -> Result<Vec<LaneState>, StoreError>
Load every persisted lane. Called once during node bring-up so the runtime can hydrate its in-memory map before the voucher-accepting handler starts.
§Errors
Returns a StoreError if the backing store is unreadable or contains
corrupt entries.
Sourcefn record(&self, state: &LaneState) -> Result<(), StoreError>
fn record(&self, state: &LaneState) -> Result<(), StoreError>
Record the post-acceptance state for one lane in the store’s working set.
A disk-backed store MAY buffer this in memory and make it durable later
via flush; it is not required to fsync before
returning Ok. Frontier state is safe to lose on a crash (an honest
client resumes forward; an un-redeemed replay is still on-chain-payable).
Implementations MUST NOT block: this is called inline on the per-stream open path, on a runtime worker, with no timeout around it. An implementation that does I/O here stalls a worker for the duration and the latency is attributed nowhere.
Callers MUST pass a LaneState whose last_* tuple is a non-strict
monotonic successor of any previously-recorded state for the same
LaneKey. The trait does not re-validate this —
LaneState::apply_voucher is the canonical caller and enforces
monotonicity upstream.
§Errors
Returns a StoreError if the write fails. Callers MUST NOT
advance their in-memory state on failure.
Sourcefn forget(&self, key: LaneKey) -> Result<(), StoreError>
fn forget(&self, key: LaneKey) -> Result<(), StoreError>
Drop the persisted entry for a settled lane. A no-op if the lane has no record.
A disk-backed store MAY buffer the removal and apply it on the next
flush; it is not required to fsync before
returning Ok.
§Errors
Returns a StoreError if the underlying delete fails.
Sourcefn get(&self, key: LaneKey) -> Result<Option<LaneState>, StoreError>
fn get(&self, key: LaneKey) -> Result<Option<LaneState>, StoreError>
Point-lookup the persisted state for one lane, or None if no record
exists. Used by the on-chain seller redemption path to read the latest
accepted voucher (last_amount / last_bytes_delivered /
last_signature) when deciding whether an accrued claim crosses the
redemption threshold — always the freshest committed voucher.
§Errors
Returns a StoreError if the backing store is unreadable or the record
is corrupt.
Provided Methods§
Sourcefn flush(&self) -> Result<(), StoreError>
fn flush(&self) -> Result<(), StoreError>
Force all buffered lane state durable (fsync, for disk-backed impls).
The default is a no-op: a volatile store (MemoryPoolStateStore) holds
nothing to flush, and a store that commits inside record has nothing
buffered. A disk-backed implementation MAY override this to buffer
record and forget in memory and make them durable here in one fsynced
transaction.
§Errors
Returns a StoreError if the durable write fails.
Sourcefn set_registered_until(
&self,
key: LaneKey,
registered_until: u64,
) -> Result<(), StoreError>
fn set_registered_until( &self, key: LaneKey, registered_until: u64, ) -> Result<(), StoreError>
Raise this lane’s observed on-chain registration expiry
(LaneState::registered_until) to registered_until, monotonically — a
lower or equal value is a no-op, and 0 (unknown) never lowers a known
value. Touches ONLY that field, never the replay-critical last_* tuple,
so the seller redeemer can record a fresh registration without racing a
concurrent voucher advance into a lost update. A no-op for a lane with no
record. Buffered like record; durability is the next flush’s job.
§Errors
Returns a StoreError if the backing store is unwritable.
Sourcefn set_paid_cumulative(
&self,
key: LaneKey,
paid_cumulative: U256,
) -> Result<(), StoreError>
fn set_paid_cumulative( &self, key: LaneKey, paid_cumulative: U256, ) -> Result<(), StoreError>
Raise this lane’s paid cumulative (LaneState::paid_cumulative) to
paid_cumulative, monotonically — a lower or equal value is a no-op.
Touches ONLY that field, never the replay-critical last_* tuple, so the
seller PoolRedeemed watcher can record an observed redemption without
racing a concurrent voucher advance into a lost update. A no-op for a lane
with no record. Buffered like record; durability is the next flush’s
job. Persisting it is what stops a restarted node from forgetting prior
redemptions and re-submitting already-redeemed lanes (#2052).
§Errors
Returns a StoreError if the backing store is unwritable.
Dyn Compatibility§
This trait is dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety".