Skip to main content

Store

Struct Store 

Source
pub struct Store { /* private fields */ }
Expand description

The embedded keyspace.

Store is Clone (since v1.1.0). A clone is a cheap Arc bump: every clone reaches the same underlying shards + AOF + reaper + pub/sub bus. The reaper thread is joined and each shard’s AOF is flushed exactly once, when the last clone is dropped.

use kevy_embedded::{Config, Store};

let s = Store::open(Config::default().with_ttl_reaper_manual())?;
let s2 = s.clone();
std::thread::spawn(move || {
    s2.set(b"from-thread", b"v").unwrap();
}).join().unwrap();
assert_eq!(s.get(b"from-thread")?, Some(b"v".to_vec()));

Every method takes &self. Sharding (see Config::with_shards) lets a multi-threaded consumer scale across cores; pub/sub is process-wide (handled on shard 0).

Implementations§

Source§

impl Store

Source

pub fn info(&self) -> KevyInfo

One-shot snapshot of the store’s introspection counters. See KevyInfo. Takes the embedded mutex once; safe to call from a health endpoint.

Source

pub fn expire_pending_count(&self) -> usize

Number of live keys that currently carry a TTL (the expire-set size, summed across shards).

Source

pub fn ttl(&self, key: &[u8]) -> Option<Duration>

Remaining TTL for key as a Duration, or None when the key is absent or has no TTL (persistent). For the raw Redis PTTL sentinels (-2 no key, -1 no TTL) use Store::ttl_ms.

Source§

impl Store

Source

pub fn set(&self, key: &[u8], value: &[u8]) -> Result<bool>

SET key value (no TTL, no NX/XX). Returns true always under the embedded API (Redis semantics: SET overwrites; NX/XX vetoes would return false but we don’t expose those here — use Store::with for the full surface).

Source

pub fn set_with_ttl( &self, key: &[u8], value: &[u8], ttl: Duration, ) -> Result<bool>

SET key value PX ms — overwrites + sets TTL. The AOF records an absolute PEXPIREAT deadline (not the relative ttl) so the key expires at the same wall-clock instant after a restart — a relative PEXPIRE would be re-anchored to replay-time, resetting the TTL to a fresh full duration on every restart (INC-2026-06-09).

Source

pub fn get(&self, key: &[u8]) -> Result<Option<Vec<u8>>>

GET keySome(bytes) on hit, None on miss or expired.

With eviction off (maxmemory == 0, the default) this takes the read lock and a non-mutating store lookup, so concurrent readers scale across cores — the path a read-heavy embed cache lives on. With eviction on it falls back to the exclusive lock + mutating get so each access still stamps the LRU clock.

Source

pub fn del(&self, keys: &[&[u8]]) -> Result<usize>

DEL key1 [key2 ...]. Returns the count of keys actually removed. Keys fan out to their owning shards.

Source

pub fn exists(&self, keys: &[&[u8]]) -> Result<usize>

EXISTS key1 [key2 ...]. Count of existing keys (duplicates counted multiple times, matching Redis).

Source

pub fn incr(&self, key: &[u8]) -> Result<i64>

INCR key. Returns the post-increment value.

Source

pub fn incr_by(&self, key: &[u8], delta: i64) -> Result<i64>

INCRBY key delta. Negative delta does DECR-style work.

Source

pub fn expire(&self, key: &[u8], ttl: Duration) -> Result<bool>

EXPIRE key seconds. Returns true if a key was touched. The AOF records an absolute PEXPIREAT deadline (see Self::set_with_ttl) so the TTL survives a restart unchanged.

Source

pub fn persist(&self, key: &[u8]) -> Result<bool>

PERSIST key. Returns true if a TTL was actually cleared.

Source

pub fn ttl_ms(&self, key: &[u8]) -> i64

Remaining TTL in ms (or Redis-style -1/-2 for no-TTL/no-key).

Source

pub fn type_of(&self, key: &[u8]) -> &'static str

TYPE key"string", "hash", "list", "set", "zset", or "none".

Source

pub fn dbsize(&self) -> usize

DBSIZE — total live keys across all shards.

Source

pub fn flushall(&self) -> Result<()>

FLUSHALL — empty every shard (each logs FLUSHALL so a replay reaches the same empty state).

Named flushallnot flush — to avoid colliding with Write::flush’s “sync buffered writes to disk” meaning. This call WIPES the store; durability needs no explicit call (each write appends to the AOF, the shard’s BufWriter lands per AppendFsync cadence and on drop).

Source

pub fn flush(&self) -> Result<()>

👎Deprecated since 1.2.0:

renamed to flushall: flush collides with Write::flush (sync-to-disk); this WIPES the store

Deprecated alias for Self::flushall. The old name read like Write::flush (sync-to-disk) but actually WIPES the store — a data-loss footgun.

Source

pub fn key_bytes(&self, key: &[u8]) -> Option<u64>

MEMORY USAGE for one key — Some(bytes) or None if absent.

Source

pub fn used_memory(&self) -> u64

Live used_memory estimate (summed across shards).

Source

pub fn evictions_total(&self) -> u64

INFO-style counter: total keys evicted by maxmemory (all shards).

Source

pub fn expired_keys_total(&self) -> u64

INFO-style counter: total keys expired (lazy + active reaper, all shards).

Source

pub fn hset(&self, key: &[u8], pairs: &[(&[u8], &[u8])]) -> Result<usize>

HSET key field value [field value ...]. Returns count newly added.

Source

pub fn hget(&self, key: &[u8], field: &[u8]) -> Result<Option<Vec<u8>>>

HGET key field. None if absent.

Source

pub fn hdel(&self, key: &[u8], fields: &[&[u8]]) -> Result<usize>

HDEL key field [field ...]. Returns count actually removed.

Source

pub fn lpush(&self, key: &[u8], values: &[&[u8]]) -> Result<usize>

LPUSH key value [value ...]. Returns the new list length.

Source

pub fn rpush(&self, key: &[u8], values: &[&[u8]]) -> Result<usize>

RPUSH key value [value ...]. Returns the new list length.

Source

pub fn lpop(&self, key: &[u8], count: usize) -> Result<Vec<Vec<u8>>>

LPOP key count. Returns popped values from the head.

Source

pub fn rpop(&self, key: &[u8], count: usize) -> Result<Vec<Vec<u8>>>

RPOP key count. Symmetric to LPOP from the tail.

Source

pub fn llen(&self, key: &[u8]) -> Result<usize>

LLEN key. Length of the list at key; 0 if absent.

Source

pub fn sadd(&self, key: &[u8], members: &[&[u8]]) -> Result<usize>

SADD key member [member ...]. Returns count newly added.

Source

pub fn srem(&self, key: &[u8], members: &[&[u8]]) -> Result<usize>

SREM key member [member ...]. Returns count actually removed.

Source

pub fn smembers(&self, key: &[u8]) -> Result<Vec<Vec<u8>>>

SMEMBERS key. Order implementation-defined; empty if absent.

Source

pub fn scard(&self, key: &[u8]) -> Result<usize>

SCARD key. Member count; 0 if absent.

Source

pub fn zadd(&self, key: &[u8], pairs: &[(f64, &[u8])]) -> Result<usize>

ZADD key score member [score member ...]. Returns count newly added.

Source

pub fn zrem(&self, key: &[u8], members: &[&[u8]]) -> Result<usize>

ZREM key member [member ...]. Returns count actually removed.

Source

pub fn zscore(&self, key: &[u8], member: &[u8]) -> Result<Option<f64>>

ZSCORE key member. Some(score) if present.

Source

pub fn zcard(&self, key: &[u8]) -> Result<usize>

ZCARD key. Member count; 0 if absent.

Source

pub fn publish(&self, channel: &[u8], payload: &[u8]) -> usize

PUBLISH channel payload. Delivers payload to every subscriber on channel (direct + pattern matches) inside this process. Returns the count of receivers the message reached.

Source

pub fn subscribe(&self, channels: &[&[u8]]) -> Subscription

Open a Subscription subscribed to channels. Drop the handle to unsubscribe from everything atomically. Pass &[] to start with no subscriptions and add some later via Subscription::subscribe / Subscription::psubscribe.

Source

pub fn psubscribe(&self, patterns: &[&[u8]]) -> Subscription

Convenience: open a Subscription starting on pattern subscriptions.

Source§

impl Store

Source

pub fn open(config: Config) -> Result<Self>

Open an embedded keyspace per config.

  • Pure in-memory when config.data_dir is None.
  • With persistence: each shard loads its snapshot then replays its AOF (config.shards > 1 re-shards a legacy single AOF on first open).
  • Spawns a background TTL reaper thread when config.ttl_reaper == Background (the default).
  • When config.replica_upstream = Some("host:port"), spawns a background thread that streams replication frames from the named primary and applies them to this store; local writes are rejected with READONLY (see Self::open_replica).
Source

pub fn open_replica(upstream: impl Into<String>) -> Result<Self>

Convenience constructor for an embed-as-read-replica store streaming writes from upstream ("host:port" of a kevy server’s replication listener).

The replica:

  • has its local AOF force-disabled (the upstream stream is the source of truth; replica AOF would diverge and double-apply on restart);
  • rejects every local write with a READONLY io::Error (you can still call read APIs concurrently);
  • reconnects with exponential backoff on disconnect, resuming from the last applied offset;
  • gets a process-unique replica_id so an open / drop / reopen cycle within the primary’s reconnect window does not look like the same slot from the primary’s POV (which would evict backlog frames the new embed still needs from offset 0). Override via Config::with_replica_id when you specifically want the slot to be re-claimed across restarts.

For full builder control (custom replica id, backoff bounds, snapshot dir, etc.) use Self::open with Config::with_replica_upstream + the related setters instead.

Source

pub fn is_replica(&self) -> bool

true when this store was opened against a replication upstream — local writes are rejected with READONLY.

Source

pub fn set_replica_upstream( &self, new_upstream: impl Into<String>, ) -> Result<()>

Retarget this replica at a new primary URL (host:port). The runner picks up the change on its next connect — which is forced now by shutdowning the current socket clone, so the retarget lands within Config::replica_reconnect_min (default 100 ms) of this call.

Returns Err with ErrorKind::InvalidInput when this store is not a replica (no upstream was configured at open). Application code typically drives this from a kevy-elect failover signal — see docs/cluster.md “embed-as-read-replica” / Phase 2 / T2.7. kevy-embedded itself stays elect-protocol-agnostic; the integration glue lives in the application.

Source

pub fn downgrade(&self) -> WeakStore

Get a weak handle that does not keep the keyspace alive.

Source

pub fn config(&self) -> &Config

The active config (a clone — modifying it has no effect on the running store). Useful for introspection / INFO-style telemetry.

Source

pub fn with<F, R>(&self, f: F) -> R
where F: FnOnce(&mut Store) -> R,

Run f against the underlying kevy_store::Store under its lock. Use for direct access to methods this crate hasn’t wrapped. The closure can mutate, but does not auto-log to the AOF — call Self::log yourself if the mutation must survive a crash.

Sharded stores: this targets shard 0 only. Use Self::with_key to reach the shard owning a specific key.

Source

pub fn with_key<F, R>(&self, key: &[u8], f: F) -> R
where F: FnOnce(&mut Store) -> R,

Like Self::with but targets the shard that owns key.

Source

pub fn collect_keys( &self, pattern: Option<&[u8]>, limit: Option<usize>, ) -> Vec<Vec<u8>>

KEYS / SCAN-glob across every shard — the cross-shard replacement for with(|s| s.collect_keys(pat, lim)), which only sees shard 0 once sharding is on. Behaves identically to with(...) when shard_count() == 1. limit bounds the total returned across shards. Takes a read lock per shard (concurrent-safe).

Source

pub fn for_each_shard<F: FnMut(&mut Store)>(&self, f: F)

Run f against each shard’s underlying kevy_store::Store (in shard-index order) — the cross-shard escape hatch. The caller assembles the merged result. Pairs with Self::shard_count. For a single key, prefer Self::with_key; for a glob scan, prefer Self::collect_keys.

Source

pub fn shard_count(&self) -> usize

Number of keyspace shards (== Config::shards).

Source

pub fn log(&self, parts: &[&[u8]]) -> Result<()>

Append a raw RESP-frame argument list to the shard owning its key’s AOF. No-op when persistence is disabled.

Source

pub fn tick(&self) -> ExpireStats

Run one TTL-reaper tick across every shard. Required call cadence in Manual mode (~10×/s to match Redis hz=10). Returns the summed stats.

Source§

impl Store

Source

pub fn rewrite_aof(&self) -> Result<Option<RewriteStats>>

BGREWRITEAOF: rebuild every shard’s AOF from current state. Synchronous. Returns the summed stats (None if persistence is off / no shard rewrote).

Source

pub fn save_snapshot(&self) -> Result<bool>

Snapshot every shard to its dump-{i}.rdb (single shard: the configured name), atomically. Ok(false) when persistence is disabled.

Trait Implementations§

Source§

impl Clone for Store

Source§

fn clone(&self) -> Store

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

Auto Trait Implementations§

§

impl !RefUnwindSafe for Store

§

impl !UnwindSafe for Store

§

impl Freeze for Store

§

impl Send for Store

§

impl Sync for Store

§

impl Unpin for Store

§

impl UnsafeUnpin for Store

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> 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> 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.