pub struct SqliteSessionStore { /* private fields */ }sqlite only.Expand description
SQLite-backed session store with AES-256-GCM encryption at rest.
Wrap an existing SqlitePool and call init_schema once at startup.
Production deployments must also schedule cleanup of expired session
rows: either by calling spawn_cleanup_task
at startup or by running an external job that invokes
cleanup_expired. Without one of these, the
sessions table grows unbounded.
§Encryption
The primary constructor new requires a
SessionCrypto key; session data
is encrypted before storage and decrypted on load.
For local development or testing where encryption is not needed, use
plaintext instead. This is an
explicit opt-out so that production code never accidentally stores
sessions unencrypted.
use axess::session::SessionCrypto;
// Production: encrypted (required).
let store = SqliteSessionStore::new(pool, SessionCrypto::new(key));
// Development only: plaintext (explicit opt-out).
let store = SqliteSessionStore::plaintext(pool);Implementations§
Source§impl SqliteSessionStore
impl SqliteSessionStore
Sourcepub fn new(pool: SqlitePool, crypto: SessionCrypto) -> Self
pub fn new(pool: SqlitePool, crypto: SessionCrypto) -> Self
Create an encrypted store (recommended for production).
Sourcepub fn plaintext(pool: SqlitePool) -> Self
pub fn plaintext(pool: SqlitePool) -> Self
Create a plaintext store (development/testing only).
Sourcepub fn with_clock(self, clock: Arc<dyn Clock>) -> Self
pub fn with_clock(self, clock: Arc<dyn Clock>) -> Self
Inject a Clock for deterministic-simulation testing.
Sourcepub async fn init_schema(&self) -> Result<(), Error>
pub async fn init_schema(&self) -> Result<(), Error>
Create the sessions table if it doesn’t already exist.
Sourcepub async fn cleanup_expired(&self) -> Result<u64, Error>
pub async fn cleanup_expired(&self) -> Result<u64, Error>
Delete all sessions whose expires_at is in the past.
Sourcepub fn spawn_cleanup_task(&self, interval: Duration) -> JoinHandle<()>
pub fn spawn_cleanup_task(&self, interval: Duration) -> JoinHandle<()>
Spawn a background task that calls cleanup_expired on a fixed interval.
SQL stores accumulate expired session rows forever unless something
removes them. Production deployments must either call this helper
once at startup, run an external scheduled job, or accept unbounded
table growth. The returned tokio::task::JoinHandle aborts the
loop when dropped, so store it for the lifetime of the application
(typically alongside your shutdown signal).
Errors from cleanup_expired are logged at warn and swallowed;
the loop keeps running so a single transient DB blip does not
silently halt cleanup forever.
let store = SqliteSessionStore::new(pool, crypto);
store.init_schema().await?;
let _cleanup = store.spawn_cleanup_task(std::time::Duration::from_secs(3600));Trait Implementations§
Source§impl Clone for SqliteSessionStore
impl Clone for SqliteSessionStore
Source§fn clone(&self) -> SqliteSessionStore
fn clone(&self) -> SqliteSessionStore
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreSource§impl HealthCheck for SqliteSessionStore
impl HealthCheck for SqliteSessionStore
Source§impl SessionStore for SqliteSessionStore
impl SessionStore for SqliteSessionStore
Source§type Error = SqlStoreError
type Error = SqlStoreError
Source§async fn load(&self, id: &SessionId) -> Result<Option<SessionData>, Self::Error>
async fn load(&self, id: &SessionId) -> Result<Option<SessionData>, Self::Error>
None if the session
does not exist or has expired.Source§async fn save(
&self,
id: &SessionId,
data: &SessionData,
ttl: Duration,
) -> Result<(), Self::Error>
async fn save( &self, id: &SessionId, data: &SessionData, ttl: Duration, ) -> Result<(), Self::Error>
Source§async fn delete(&self, id: &SessionId) -> Result<(), Self::Error>
async fn delete(&self, id: &SessionId) -> Result<(), Self::Error>
Source§async fn cycle(
&self,
old_id: &SessionId,
new_id: &SessionId,
data: &SessionData,
ttl: Duration,
) -> Result<(), Self::Error>
async fn cycle( &self, old_id: &SessionId, new_id: &SessionId, data: &SessionData, ttl: Duration, ) -> Result<(), Self::Error>
Source§impl Store<SessionId, SessionData> for SqliteSessionStore
impl Store<SessionId, SessionData> for SqliteSessionStore
Source§type Error = SqlStoreError
type Error = SqlStoreError
StoreError enum for
new backends; legacy wrappers may continue to surface
SqlStoreError / ValkeyStoreError / PostgresStoreError
until each is consolidated.Source§fn get(
&self,
key: &SessionId,
) -> impl Future<Output = Result<Option<SessionData>, Self::Error>> + Send
fn get( &self, key: &SessionId, ) -> impl Future<Output = Result<Option<SessionData>, Self::Error>> + Send
key. Ok(None) when the key is absent
(including TTL-expired); Err only on backend failure.Source§fn put(
&self,
key: &SessionId,
value: &SessionData,
ttl: Duration,
) -> impl Future<Output = Result<(), Self::Error>> + Send
fn put( &self, key: &SessionId, value: &SessionData, ttl: Duration, ) -> impl Future<Output = Result<(), Self::Error>> + Send
key with the given TTL.Source§fn delete(
&self,
key: &SessionId,
) -> impl Future<Output = Result<(), Self::Error>> + Send
fn delete( &self, key: &SessionId, ) -> impl Future<Output = Result<(), Self::Error>> + Send
key. Idempotent; does not error if absent.Source§fn prune_expired(&self) -> impl Future<Output = Result<u64, Self::Error>> + Send
fn prune_expired(&self) -> impl Future<Output = Result<u64, Self::Error>> + Send
Ok(0); backends owning their own
row table (SQLite, Postgres, in-memory) actually delete.Auto Trait Implementations§
impl Freeze for SqliteSessionStore
impl !RefUnwindSafe for SqliteSessionStore
impl Send for SqliteSessionStore
impl Sync for SqliteSessionStore
impl Unpin for SqliteSessionStore
impl UnsafeUnpin for SqliteSessionStore
impl !UnwindSafe for SqliteSessionStore
Blanket Implementations§
Source§impl<T> ArchivePointee for T
impl<T> ArchivePointee for T
Source§type ArchivedMetadata = ()
type ArchivedMetadata = ()
Source§fn pointer_metadata(
_: &<T as ArchivePointee>::ArchivedMetadata,
) -> <T as Pointee>::Metadata
fn pointer_metadata( _: &<T as ArchivePointee>::ArchivedMetadata, ) -> <T as Pointee>::Metadata
Source§impl<'a, T, E> AsTaggedExplicit<'a, E> for Twhere
T: 'a,
impl<'a, T, E> AsTaggedExplicit<'a, E> for Twhere
T: 'a,
Source§impl<'a, T, E> AsTaggedExplicit<'a, E> for Twhere
T: 'a,
impl<'a, T, E> AsTaggedExplicit<'a, E> for Twhere
T: 'a,
Source§impl<'a, T, E> AsTaggedImplicit<'a, E> for Twhere
T: 'a,
impl<'a, T, E> AsTaggedImplicit<'a, E> for Twhere
T: 'a,
Source§impl<'a, T, E> AsTaggedImplicit<'a, E> for Twhere
T: 'a,
impl<'a, T, E> AsTaggedImplicit<'a, E> for Twhere
T: 'a,
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 moreSource§impl<T> LayoutRaw for T
impl<T> LayoutRaw for T
Source§fn layout_raw(_: <T as Pointee>::Metadata) -> Result<Layout, LayoutError>
fn layout_raw(_: <T as Pointee>::Metadata) -> Result<Layout, LayoutError>
Source§impl<T, N1, N2> Niching<NichedOption<T, N1>> for N2
impl<T, N1, N2> Niching<NichedOption<T, N1>> for N2
Source§unsafe fn is_niched(niched: *const NichedOption<T, N1>) -> bool
unsafe fn is_niched(niched: *const NichedOption<T, N1>) -> bool
Source§fn resolve_niched(out: Place<NichedOption<T, N1>>)
fn resolve_niched(out: Place<NichedOption<T, N1>>)
out indicating that a T is niched.