pub struct ValkeyStore { /* private fields */ }valkey only.Expand description
A SessionStore on Valkey or Redis.
Every write that touches more than one key runs as a Lua script, so it is atomic across any number of processes sharing the server. Requires Valkey 7.2+ or Redis 7.0+ in standalone or primary/replica mode; Cluster is not supported because the scripts derive key names from stored data.
§Data layout
All keys start with the key prefix (P, default sg:).
Timestamps are microseconds since the Unix epoch as decimal integers.
| Key | Type | Contents |
|---|---|---|
P s:{session id} | hash | subject, created, auth, seen, expires, step_up, baseline (JSON), origin (JSON, absent before 0.2), cur (current token), seq (token counter), exp_ms |
P t:{token hash hex} | hash | sid, seq (issue order), issued, used, sup (superseded) |
P k:{session id} | sorted set | the session’s token hashes, scored by seq |
P u:{subject} | set | session ids of a subject |
P x | sorted set | session ids scored by expires_at |
P i | sorted set | session ids scored by last_seen_at |
P e | sorted set | events as JSON, scored by at |
P c:{session id}:{kind} | string | time of the last session event claim |
P c:s:{subject}:{kind} | string | time of the last subject alert claim |
P cz | sorted set | {session id}:{kind} and s:{subject}:{kind} claims scored by claim time |
Session, token and per-session token-set keys expire at the session’s absolute expiry and
subject sets at their last session’s expiry, so Valkey cleans up even if
delete_expired never runs. Because those TTLs follow the
server’s wall clock, sessions whose expires_at is already in the past vanish immediately.
Claim keys expire after their window.
Subjects are passed to scripts as data, never as code.
Cheap to clone; clones share the connection.
Implementations§
Source§impl ValkeyStore
impl ValkeyStore
Sourcepub fn new(conn: ConnectionManager) -> Self
pub fn new(conn: ConnectionManager) -> Self
A store on an existing connection, with the default key prefix sg:.
Sourcepub async fn connect(url: &str) -> Result<Self, RedisError>
pub async fn connect(url: &str) -> Result<Self, RedisError>
Connects to url (redis://, rediss:// or valkey://), with the default key prefix
sg:.
§Errors
If the URL is invalid or the server is unreachable.
Sourcepub fn key_prefix(self, prefix: impl Into<String>) -> Self
pub fn key_prefix(self, prefix: impl Into<String>) -> Self
Prefixes every key with prefix, so several apps can share one server. Defaults to
sg:.
Trait Implementations§
Source§impl Clone for ValkeyStore
impl Clone for ValkeyStore
Source§impl Debug for ValkeyStore
impl Debug for ValkeyStore
Source§impl SessionStore for ValkeyStore
impl SessionStore for ValkeyStore
Source§async fn insert_session(
&self,
session: &SessionRecord,
token: &TokenHash,
) -> Result<(), StoreError>
async fn insert_session( &self, session: &SessionRecord, token: &TokenHash, ) -> Result<(), StoreError>
token as its current token (issued_at = created_at,
unused, not superseded).Source§async fn find_by_token(
&self,
token: &TokenHash,
) -> Result<Option<TokenLookup>, StoreError>
async fn find_by_token( &self, token: &TokenHash, ) -> Result<Option<TokenLookup>, StoreError>
token, current or superseded.Source§async fn apply(&self, update: &SessionUpdate) -> Result<bool, StoreError>
async fn apply(&self, update: &SessionUpdate) -> Result<bool, StoreError>
update atomically, in this order: Read moreSource§async fn delete_session(&self, session_id: Uuid) -> Result<bool, StoreError>
async fn delete_session(&self, session_id: Uuid) -> Result<bool, StoreError>
Source§async fn delete_subject_sessions(
&self,
subject: &str,
) -> Result<Vec<Uuid>, StoreError>
async fn delete_subject_sessions( &self, subject: &str, ) -> Result<Vec<Uuid>, StoreError>
subject (canonical JSON). Returns the ids it deleted.Source§async fn list_subject_sessions(
&self,
subject: &str,
) -> Result<Vec<SessionRecord>, StoreError>
async fn list_subject_sessions( &self, subject: &str, ) -> Result<Vec<SessionRecord>, StoreError>
subject (canonical JSON), including expired ones not yet purged.Source§async fn delete_expired(
&self,
now: DateTime<Utc>,
idle_cutoff: DateTime<Utc>,
) -> Result<u64, StoreError>
async fn delete_expired( &self, now: DateTime<Utc>, idle_cutoff: DateTime<Utc>, ) -> Result<u64, StoreError>
expires_at <= now or last_seen_at <= idle_cutoff. Returns how
many.Source§async fn record_event(&self, event: &SessionEvent) -> Result<(), StoreError>
async fn record_event(&self, event: &SessionEvent) -> Result<(), StoreError>
Source§async fn delete_events_before(
&self,
cutoff: DateTime<Utc>,
) -> Result<u64, StoreError>
async fn delete_events_before( &self, cutoff: DateTime<Utc>, ) -> Result<u64, StoreError>
at < cutoff. Returns how many. Also deletes event claims older
than cutoff.Source§async fn claim_event(
&self,
scope: ClaimScope<'_>,
kind: EventKind,
now: DateTime<Utc>,
window: TimeDelta,
) -> Result<bool, StoreError>
async fn claim_event( &self, scope: ClaimScope<'_>, kind: EventKind, now: DateTime<Utc>, window: TimeDelta, ) -> Result<bool, StoreError>
kind event for scope, for deduplication across
processes. Succeeds (true) unless a claim for the same scope and kind was made after
now - window, and records now as the new claim when it does. Session and subject
claims are independent. Must be atomic across processes. Read moreAuto Trait Implementations§
impl !RefUnwindSafe for ValkeyStore
impl !UnwindSafe for ValkeyStore
impl Freeze for ValkeyStore
impl Send for ValkeyStore
impl Sync for ValkeyStore
impl Unpin for ValkeyStore
impl UnsafeUnpin for ValkeyStore
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
Source§fn in_current_span(self) -> Instrumented<Self> ⓘ
fn in_current_span(self) -> Instrumented<Self> ⓘ
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
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 moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
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