Skip to main content

Store

Struct Store 

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

The embedded keyspace.

Store is Clone. 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 tier_info(&self) -> Option<KevyTierInfo>

The # Tiering gauges summed across shards, or None when tiering is off (the section is absent, not zeroed — INFO stability for untiered stores).

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]) -> KevyResult<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, ) -> KevyResult<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 (seen as a production incident: cache keys never expired across restarts).

Source

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

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

The lock is policy-gated (see Self::reads_use_shared_lock): whenever the active eviction policy won’t consume a per-read LRU/LFU tick — maxmemory == 0 (the default), or the NoEviction / *Random / VolatileTtl policies — this takes the shared lock and a non-mutating get_shared lookup. That is a lock-correctness choice: a read-only GET has no business holding the exclusive lock and blocking a concurrent writer on its shard. It is not a throughput win — concurrent GETs still contend on the shard’s RwLock word (there is no lock-free read path), so read scaling is bounded by shard count, not core count. Expired keys still read as None here (lazy expire-skip; the reaper / next write reclaims them). Only the true LRU/LFU policies fall back to the exclusive lock + mutating get so each access stamps the clock the eviction scorer ranks by.

Source

pub fn get_shared_owned(&self, key: &[u8]) -> KevyResult<Option<GetShared>>

GET for the FFI zero-copy shared lane (kevy_get_shared). Bulk values come back as an Arc::cloneno byte copy — so the FFI can hand JS a buffer viewing the engine’s own storage (the win vs the plain Self::get, which into_owned-copies). The lookup is non-mutating; the lock is policy-gated like Self::get (Self::reads_use_shared_lock). This lane never stamps the LRU clock and never promotes a cold value.

Source

pub fn del(&self, keys: &[&[u8]]) -> KevyResult<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]]) -> KevyResult<usize>

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

Source

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

INCR key. Returns the post-increment value.

Source

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

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

Source

pub fn expire(&self, key: &[u8], ttl: Duration) -> KevyResult<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]) -> KevyResult<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.

Aggregates under each shard’s SHARED lock (the underlying dbsize is &self). This is a latency fix, not a scaling one: a full-keyspace count shouldn’t hold every shard’s write lock and stall concurrent writers while it sums.

Source

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

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 key_bytes(&self, key: &[u8]) -> Option<u64>

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

Read-only (estimate_key_bytes is &self), so it takes the shard’s SHARED lock rather than blocking a concurrent writer on that shard.

Source

pub fn used_memory(&self) -> u64

Live used_memory estimate (summed across shards).

Aggregates under each shard’s SHARED lock (latency fix — an INFO-time memory sum shouldn’t hold every shard’s write lock; see Self::dbsize).

Source

pub fn evictions_total(&self) -> u64

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

Read-only aggregation under each shard’s SHARED lock (see Self::dbsize).

Source

pub fn expired_keys_total(&self) -> u64

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

Read-only aggregation under each shard’s SHARED lock (see Self::dbsize).

Source

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

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

Source

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

HGET key field. None if absent.

Source

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

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

Source

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

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

Source

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

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

Source

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

LPOP key count. Returns popped values from the head.

Source

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

RPOP key count. Symmetric to LPOP from the tail.

Source

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

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

Source

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

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

Source

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

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

Source

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

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

Source

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

SCARD key. Member count; 0 if absent.

Source

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

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

Source

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

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

Source

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

ZSCORE key member. Some(score) if present.

Source

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

ZCARD key. Member count; 0 if absent.

Source

pub fn dispatch_argv(&self, argv: &[Vec<u8>], out: &mut Vec<u8>)

Dispatch one command as argv, appending the RESP-encoded reply to out — the full read+write verb surface (ESTORE_OPS plus the conn face). This is the generic entry the FFI layer builds every language binding on: one function reaches the whole engine. The read-only listener keeps its own narrower whitelist.

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 atomic<R>( &self, body: impl FnOnce(&mut AtomicCtx<'_>) -> KevyResult<R>, ) -> KevyResult<R>

Run body as a single-shard atomic transaction: it applies entirely, or not at all.

Inside the closure every read sees the closure’s own previous writes. On Ok, the queued AOF frames are committed as one group — under Fsync::Always that is a single fsync for the whole block, not one per mutation.

On Err, every write the closure made is rolled back and nothing is appended to the AOF. This is what lets the closure act as the enforcement point for an invariant: read, decide, write, and return Err to reject — the rejection leaves no trace. (Before 4.0 the writes stayed live in memory while their AOF frames were discarded, so a restarted process disagreed with the running one.)

Rollback restores each touched key to the value and TTL it had before the transaction — including deleting keys the closure created. It is a snapshot of the keys the closure touches, so the cost scales with the transaction, not the keyspace.

Constraint: every key touched inside the closure must hash to the same shard. The default embedded config uses 1 shard, so any key works.

Source§

impl Store

Source

pub fn atomic_all_shards<R>( &self, body: impl FnOnce(&mut AtomicAllShards<'_>) -> KevyResult<R>, ) -> KevyResult<R>

Run body as a transaction holding write locks on EVERY shard for the closure’s duration. Reads inside the closure see prior writes (full read-modify-write). On closure return, AOF writes commit with one fsync per shard.

Cost: blocks every other writer + reader on this Store for the closure body. Use when atomic multi-shard semantics are required; otherwise prefer the single-shard atomic.

Source§

impl Store

Source

pub fn getbit(&self, key: &[u8], offset: u64) -> KevyResult<u8>

GETBIT key offset — return the bit at offset (MSB-first). 0 for missing key or past-end.

Source

pub fn setbit(&self, key: &[u8], offset: u64, value: u8) -> KevyResult<u8>

SETBIT key offset value — set the bit at offset to value (0 or 1). Extends the underlying string with zero padding as needed. Returns the PREVIOUS bit value.

Source

pub fn bitcount(&self, key: &[u8], range: Option<(i64, i64)>) -> KevyResult<u64>

BITCOUNT key [start end] — count set bits over the optional byte-offset range (inclusive, negatives-from-tail like Redis). None for range = whole string.

Source

pub fn bitpos( &self, key: &[u8], bit: u8, range: Option<(i64, i64)>, ) -> KevyResult<Option<u64>>

BITPOS key bit [start [end]] — find first bit equal to bit (0 or 1) in the optional byte range. Returns None when not found (Redis would reply :-1).

Source

pub fn getrange(&self, key: &[u8], start: i64, end: i64) -> KevyResult<Vec<u8>>

GETRANGE key start end — substring with Redis negative indexing; [start, end] inclusive.

Source

pub fn setrange( &self, key: &[u8], offset: u64, value: &[u8], ) -> KevyResult<usize>

SETRANGE key offset value — overwrite bytes at offset; extends with zero padding if past current length. Returns the new total length.

Source

pub fn bitop(&self, op: BitOp, dst: &[u8], srcs: &[&[u8]]) -> KevyResult<usize>

BITOP AND|OR|XOR|NOT destkey srckey [srckey ...] — bitwise op across N source keys, stored at destkey. Returns the destination string length (= longest source length, with shorter sources zero-padded). For Not, exactly one source key (additional ones are rejected).

Source

pub fn time(&self) -> (u64, u32)

TIME(unix_seconds, microseconds) tuple. Useful for time-based embedded logic + tracing.

Source§

impl Store

Source

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

SETNX key value — set only if the key does not exist. Returns true when the SET succeeded; false when it was vetoed by an existing value.

Source

pub fn incrbyfloat(&self, key: &[u8], delta: f64) -> KevyResult<f64>

INCRBYFLOAT key delta — atomic float increment of a string value. Returns the post-increment value parsed as f64.

Source

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

DECR key — atomic decrement by 1.

Source

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

DECRBY key delta — atomic decrement by delta.

Source

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

STRLEN key — length of the string value at key; 0 if absent. Errors on wrong type.

Source

pub fn append(&self, key: &[u8], data: &[u8]) -> KevyResult<usize>

APPEND key data — append data to the string at key. Creates the key if absent. Returns the new total length.

Source

pub fn hsetnx(&self, key: &[u8], field: &[u8], value: &[u8]) -> KevyResult<bool>

HSETNX key field value — set the hash field only if it does not already exist. Returns true when set; false when the field existed.

Source

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

TTL key — TTL in seconds (truncated from ms). -1 when the key has no TTL; -2 when absent. Matches Redis wire semantics for the integer reply.

Source§

impl Store

Source

pub fn copy(&self, src: &[u8], dst: &[u8], replace: bool) -> KevyResult<bool>

COPY src dst [REPLACE] — copy src’s value (and TTL if any) to dst. Returns true when the copy happened.

Semantics:

  • false if src doesn’t exist.
  • false if dst exists and replace = false.
  • Preserves source TTL on the destination via pexpireat.
Source

pub fn randomkey(&self) -> Option<Vec<u8>>

RANDOMKEY — return a randomly-chosen existing key, or None when the keyspace is empty.

Implementation: snapshot all keys via collect_keys, then pick a uniform index. For large keyspaces this is O(N); a future ship can add a key_at(rank) Store method for O(1) random pick.

UNLINK key [key ...] — alias for Self::del. In Redis this is the async (non-blocking) variant; kevy is in-process so the sync del IS the unblocking semantic. Returns count actually removed.

Source

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

TOUCH key [key ...] — count keys that exist. Side effect: the existence check refreshes LRU/LFU bookkeeping on the touched shards, matching Redis semantics.

Source§

impl Store

Source

pub fn prefix_digest(&self, prefix: &[u8]) -> (u64, u64)

Order-insensitive prefix checksum for migration verification: (row_count, xor_of_row_digests). Matches the server’s PREFIX.DIGEST bit for bit (same canonicalization).

Source§

impl Store

Source

pub fn sismember(&self, key: &[u8], member: &[u8]) -> KevyResult<bool>

SISMEMBER key membertrue when member is in the set.

Source

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

SPOP key count — atomically remove + return up to count random members.

AOF form: logged as SREM key <popped…> (the members actually removed), not SPOP key count — a random pick replayed against a store whose internal layout differs (replica applying frames onto snapshot-loaded state) would remove different members. Redis propagates SPOP the same way.

Source

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

SRANDMEMBER key count — return up to count random members without removing them.

Source

pub fn zrank(&self, key: &[u8], member: &[u8]) -> KevyResult<Option<usize>>

ZRANK key member — rank (0-based, ascending) of member; None if not present.

Source

pub fn zcount(&self, key: &[u8], min: f64, max: f64) -> KevyResult<usize>

ZCOUNT key min max — count members whose score falls in [min, max] (inclusive). Pass ±INFINITY for open bounds.

Source

pub fn zpopmin( &self, key: &[u8], count: usize, ) -> KevyResult<Vec<(Vec<u8>, f64)>>

ZPOPMIN key count — atomically remove + return up to count members with the lowest scores. Pairs are (member, score).

Source

pub fn zremrangebyrank( &self, key: &[u8], start: i64, stop: i64, ) -> KevyResult<usize>

ZREMRANGEBYRANK key start stop — remove members in [start, stop] rank range (inclusive, Redis-style negative indexing). Returns count removed.

Source

pub fn zremrangebyscore( &self, key: &[u8], min: f64, max: f64, ) -> KevyResult<usize>

ZREMRANGEBYSCORE key min max — remove members with scores in [min, max] (inclusive). Returns count removed.

Source

pub fn zrev_range_by_score( &self, key: &[u8], max: f64, min: f64, ) -> KevyResult<Vec<(Vec<u8>, f64)>>

ZREVRANGEBYSCORE key max min — members with scores in [min, max] in DESCENDING score order. Inclusive bounds.

Source

pub fn lset(&self, key: &[u8], idx: i64, value: &[u8]) -> KevyResult<()>

LSET key idx value — set the element at idx (negative indexes count from tail). Errors NoSuchKey / OutOfRange matching Redis.

Source

pub fn ltrim(&self, key: &[u8], start: i64, stop: i64) -> KevyResult<()>

LTRIM key start stop — trim list to [start, stop] inclusive (Redis-style negative indexing).

Source

pub fn rename(&self, src: &[u8], dst: &[u8]) -> KevyResult<bool>

RENAME src dst — atomic rename. Returns true when the rename happened. Errors when src doesn’t exist (Redis would reply -ERR no such key, here Err(NoSuchKey)).

Source

pub fn renamenx(&self, src: &[u8], dst: &[u8]) -> KevyResult<bool>

RENAMENX src dst — rename only when dst doesn’t exist. Returns true when the rename happened.

Source§

impl Store

Source

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

HGETALL key — every (field, value) pair in key’s hash, in arbitrary order. Empty when key is absent. Errors on wrong type.

Source

pub fn hexists(&self, key: &[u8], field: &[u8]) -> KevyResult<bool>

HEXISTS key fieldtrue when field is present.

Source

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

HLEN key — number of fields; 0 when absent.

Source

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

HKEYS key — every field name in key’s hash.

Source

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

HVALS key — every value in key’s hash.

Source

pub fn hmget( &self, key: &[u8], fields: &[&[u8]], ) -> KevyResult<Vec<Option<Vec<u8>>>>

HMGET key field [field ...] — read multiple fields in one call. None per requested field that is absent.

Source

pub fn hincrby(&self, key: &[u8], field: &[u8], delta: i64) -> KevyResult<i64>

HINCRBY key field delta — atomic integer increment of a hash field. Returns the post-increment value.

Source

pub fn zrange( &self, key: &[u8], start: i64, stop: i64, ) -> KevyResult<Vec<(Vec<u8>, f64)>>

ZRANGE key start stop WITHSCORES — members in ascending score order between rank start..=stop (Redis-style inclusive indexing; negatives count from the tail). Returns (member, score) pairs.

Source

pub fn zrevrange( &self, key: &[u8], start: i64, stop: i64, ) -> KevyResult<Vec<(Vec<u8>, f64)>>

ZREVRANGE key start stop WITHSCORESzrange with the order reversed (highest score first). The start..=stop indexing is against the reversed list, matching Redis semantics.

Source

pub fn zrange_by_score( &self, key: &[u8], min: f64, max: f64, ) -> KevyResult<Vec<(Vec<u8>, f64)>>

ZRANGEBYSCORE — score-range read. min / max are inclusive; pass f64::NEG_INFINITY / f64::INFINITY for open bounds. Returns (member, score) pairs in ascending score order. Exclusive bounds are ZRANGEBYSCORE ( syntax in Redis; expose via the dedicated Self::zrange_by_score_excl.

Source

pub fn zrange_by_score_excl( &self, key: &[u8], min: ScoreBound, max: ScoreBound, ) -> KevyResult<Vec<(Vec<u8>, f64)>>

Same as Self::zrange_by_score but with explicit inclusive/exclusive control on each bound ((min / (max in Redis syntax).

Source

pub fn zrange_by_score_limit( &self, key: &[u8], min: f64, max: f64, offset: usize, count: usize, ) -> KevyResult<Vec<(Vec<u8>, f64)>>

ZRANGEBYSCORE key min max LIMIT offset count — score-range read with pagination (closes the embedded LIMIT gap — the server parser always had it).

Source

pub fn zrevrange_by_score_limit( &self, key: &[u8], max: f64, min: f64, offset: usize, count: usize, ) -> KevyResult<Vec<(Vec<u8>, f64)>>

ZREVRANGEBYSCORE key max min LIMIT offset count — descending score-range read with pagination.

Source

pub fn zpopmin_below( &self, key: &[u8], below: f64, count: usize, ) -> KevyResult<Vec<(Vec<u8>, f64)>>

zpopmin_below — pop up to count lowest members with score strictly < below (delayed-job “pop what’s due”). AOF logs the effect (ZREM of the popped members).

Source

pub fn zincrby(&self, key: &[u8], delta: f64, member: &[u8]) -> KevyResult<f64>

ZINCRBY key delta member — atomic float increment of a member’s score. Returns the post-increment score.

Source

pub fn lrange( &self, key: &[u8], start: i64, stop: i64, ) -> KevyResult<Vec<Vec<u8>>>

LRANGE key start stop — list slice. Negative indices count from the tail. Empty when absent.

Source

pub fn lindex(&self, key: &[u8], idx: i64) -> KevyResult<Option<Vec<u8>>>

LINDEX key idx — element at index idx; None out of range.

Source

pub fn lrem(&self, key: &[u8], count: i64, value: &[u8]) -> KevyResult<usize>

LREM key count value — remove up to |count| occurrences of value. count > 0 from head, count < 0 from tail, count == 0 all. Returns the count actually removed.

Source

pub fn getset(&self, key: &[u8], new: &[u8]) -> KevyResult<Option<Vec<u8>>>

GETSET key new — set key to new, return the previous value (or None when key was absent).

Source

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

GETDEL key — delete key, return the previous value (None when key was absent).

Source§

impl Store

Source

pub fn mset(&self, pairs: &[(&[u8], &[u8])]) -> KevyResult<()>

MSET key value [key value ...] — set every pair atomically per-key. Each pair is logged independently to its shard’s AOF (no cross-shard atomic guarantee — a crash mid-call may leave a prefix applied; matches Redis Cluster semantics).

Source

pub fn mget(&self, keys: &[&[u8]]) -> KevyResult<Vec<Option<Vec<u8>>>>

MGET key [key ...] — return Some(value) per requested key that’s present, None per absent / wrong-type.

Source

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

KEYS pattern — glob-match every key in the keyspace (across all shards). pattern = None matches everything. limit = None is unbounded; otherwise bounds the TOTAL returned across shards. Glob syntax matches Redis (* / ? / [abc] / escape).

Source

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

GETEX key TTL — get the value and update the TTL atomically (single lock cycle on the owning shard). Returns the value; None when absent. AOF-logged as an absolute PEXPIREAT — a relative frame re-anchors on every replay, handing the key its full TTL back at each restart (the incident class the absolute form exists to prevent; this was its last relative holdout).

Source

pub fn sinter(&self, keys: &[&[u8]]) -> KevyResult<Vec<Vec<u8>>>

SINTER key [key ...] — set intersection. Reads each key’s members, computes the intersection in BTreeSet order (sorted, no duplicates).

Source

pub fn sunion(&self, keys: &[&[u8]]) -> KevyResult<Vec<Vec<u8>>>

SUNION key [key ...] — set union over N sets.

Source

pub fn sdiff(&self, keys: &[&[u8]]) -> KevyResult<Vec<Vec<u8>>>

SDIFF key [key ...]keys[0] minus the union of every subsequent set.

Source

pub fn expireat(&self, key: &[u8], unix_secs: u64) -> KevyResult<bool>

EXPIREAT key unix_secs — schedule expiry for the given absolute UNIX wall-clock time. Returns true when the key existed and the deadline was set; false when absent.

Source

pub fn pexpireat(&self, key: &[u8], unix_ms: u64) -> KevyResult<bool>

PEXPIREAT key unix_ms — same as expireat but in milliseconds.

Source

pub fn pexpire(&self, key: &[u8], ms: u64) -> KevyResult<bool>

PEXPIRE key ms — relative TTL in milliseconds. (expire takes Duration; this is the integer-ms variant matching the Redis wire command.)

Source

pub fn hincrbyfloat( &self, key: &[u8], field: &[u8], delta: f64, ) -> KevyResult<f64>

HINCRBYFLOAT key field delta — atomic float increment of a hash field. Returns the post-increment value. Errors on NotFloat when the field is present but not parseable.

Source

pub fn linsert( &self, key: &[u8], before: bool, pivot: &[u8], value: &[u8], ) -> KevyResult<i64>

LINSERT key BEFORE|AFTER pivot value — insert value before or after the first occurrence of pivot in the list. Returns:

  • Ok(new_len) on success (>= 1);
  • Ok(0) when key does not exist;
  • Ok(-1) when pivot was not found in the list.

before = true matches Redis LINSERT … BEFORE, false matches LINSERT … AFTER.

Source

pub fn ping_ns(&self) -> u128

Store::ping_us() — return the round-trip duration of a shard-0 read-lock acquire + release in nanoseconds, for perfgate observability. Always returns immediately; the duration reflects current shard-0 contention (= shorter when idle, longer when many readers/writers compete).

Source§

impl Store

Source

pub fn pipeline(&self) -> Pipeline<'_>

Begin a Pipeline — fluent write queue. Add ops via .set(...).hset(...).zadd(...) then call .commit().

Source§

impl Store

Source

pub fn info_prefix(&self, prefix: &[u8]) -> PrefixInfo

info_prefix: count live keys (and TTL’d keys) under a byte prefix, across all shards. O(keyspace) — an ops/stats call, not a hot-path primitive.

Source

pub fn feed_shards(&self) -> usize

Number of independent change streams this store exposes (the embedded write path serializes all shards: always 1).

Source

pub fn changes_tail(&self) -> Result<(u64, u64), FeedError>

The current (generation, next_offset) cursor — where a consumer starting fresh (or resuming after a rebuild) begins.

Source

pub fn changes_since( &self, generation: u64, offset: u64, limit: usize, prefixes: &[&[u8]], ) -> Result<ChangeBatch, FeedError>

Deliver up to limit changes at cursor (generation, offset), optionally prefix-filtered (fail-open on multi-key verbs; the filter never affects the returned cursor). At-least-once: after a Resync rebuild, frames already applied may be seen again.

Source§

impl Store

Source

pub fn blpop( &self, keys: &[&[u8]], timeout: Option<Duration>, ) -> KevyResult<Option<(Vec<u8>, Vec<u8>)>>

BLPOP — block until one of keys has a head element (checked in argument order each round) or timeout passes (None = wait forever). Returns (key, value).

Source

pub fn brpop( &self, keys: &[&[u8]], timeout: Option<Duration>, ) -> KevyResult<Option<(Vec<u8>, Vec<u8>)>>

BRPOP — tail-end counterpart of Self::blpop.

Source

pub fn bzpopmin( &self, keys: &[&[u8]], timeout: Option<Duration>, ) -> KevyResult<Option<(Vec<u8>, Vec<u8>, f64)>>

BZPOPMIN — block until one of keys has a zset member; returns (key, member, score).

Source§

impl Store

Source

pub fn hexpire( &self, key: &[u8], fields: &[&[u8]], ttl: Duration, cond: HExpireCond, ) -> KevyResult<Vec<HExpireCode>>

HEXPIRE — set a relative per-field TTL. One Redis code per field (-2 missing, 0 condition failed, 1 set, 2 deleted).

Source

pub fn hpexpire_at( &self, key: &[u8], fields: &[&[u8]], deadline_ms: u64, cond: HExpireCond, ) -> KevyResult<Vec<HExpireCode>>

HPEXPIREAT — absolute unix-ms per-field deadline (the canonical form; also what the AOF carries).

Source

pub fn httl(&self, key: &[u8], fields: &[&[u8]]) -> KevyResult<Vec<i64>>

HTTL — remaining seconds per field (-2 missing, -1 no TTL).

Rounded to the nearest second, as the wire verb and Redis both do. For the unrounded value use [Db::hpttl]. Before 4.0 this method carried the HTTL name and returned milliseconds, which is a thousand-fold error waiting to happen in any caller that trusted the name.

Source

pub fn hpttl(&self, key: &[u8], fields: &[&[u8]]) -> KevyResult<Vec<i64>>

HPTTL — remaining milliseconds per field (-2 missing, -1 no TTL).

Source

pub fn hpersist( &self, key: &[u8], fields: &[&[u8]], ) -> KevyResult<Vec<HExpireCode>>

HPERSIST — clear per-field TTLs (-2 missing, -1 had no TTL, 1 cleared).

Source§

impl Store

Source

pub fn idx_match_with( &self, name: &[u8], query: &[u8], limit: usize, opts: MatchOpts<'_>, ) -> KevyResult<Vec<(Vec<u8>, f64, Vec<(Vec<u8>, Vec<(u32, u32)>)>)>>

Self::idx_match with every optional clause: highlight spans, a typo budget, an offset, and a field scope.

A scoped query is a field-scoped BM25 — frequency, length and document frequency all come from the named fields alone — so naming a field the index does not declare is an error rather than an empty result that would look like a working query.

Source

pub fn idx_match_faceted( &self, name: &[u8], query: &[u8], limit: usize, opts: MatchOpts<'_>, ) -> KevyResult<MatchPage>

Self::idx_match_with, additionally counting the values of the FACET fields over the whole match set — not just the page, which is why the counts cannot be derived from the hits.

Source§

impl Store

Source

pub fn idx_create_with_values( &self, name: &[u8], prefix: &[u8], field: &[u8], ty: ValType, kind: IndexKind, values: &[(&[u8], ValType)], ) -> KevyResult<()>

Store::idx_create with declared stored VALUES columns — the scalar kinds’ G1 capability (the catalog refuses the declaration on kinds that carry no stored-value column).

Source

pub fn idx_query_claused( &self, name: &[u8], min: &IndexValue, max: &IndexValue, cursor: Option<&Cursor>, limit: usize, opts: ScalarQueryOpts<'_>, ) -> KevyResult<ScalarPage>

Store::idx_query with the stored-value clauses — the scalar twin of Store::idx_match_faceted’s clause surface. Semantics are the wire’s: each shard selects with the clauses applied, the union merges in the page’s own order, DISTINCT re-collapses, OFFSET drains after the merge, facet counts sum by coerced identity. Only FILTER (with no other clause) is cursor-paged.

Source§

impl Store

Source

pub fn idx_create_text( &self, name: &[u8], prefix: &[u8], fields: &[(&[u8], f32)], positions: bool, values: &[(&[u8], ValType)], ) -> KevyResult<()>

A multi-field text index over several weighted hash fields — what the wire creates with ON FIELDS f1 f2 WEIGHTS 2 1, and what IN scopes to. A weight scales that field’s term frequencies; 1.0 is neutral.

positions records token offsets so phrase queries can verify adjacency, at the cost of the positional side-channel’s memory. values names hash fields stored per document with the type their bytes compare as — what FILTER reads. An index that never filters declares none.

Source§

impl Store

Source

pub fn idx_create( &self, name: &[u8], prefix: &[u8], field: &[u8], ty: ValType, kind: IndexKind, ) -> KevyResult<()>

IDX.CREATE equivalent. Builds synchronously; errors on duplicate name / cap / bad spec.

Source

pub fn idx_create_ann( &self, name: &[u8], prefix: &[u8], field: &[u8], params: AnnSpec, ) -> KevyResult<()>

Declare an ANN index (KIND ann, TYPE vector). params.m / params.ef of 0 select the defaults (16 / 200).

Source

pub fn idx_drop(&self, name: &[u8]) -> bool

IDX.DROP equivalent; false if absent. On a hit the catalog sidecar is re-persisted so the drop survives restart.

Source

pub fn idx_query( &self, name: &[u8], min: &IndexValue, max: &IndexValue, cursor: Option<&Cursor>, limit: usize, ) -> KevyResult<IndexPage>

Range / EQ query with cursor pagination: merged across shards in (value, key) order. cursor = None starts; the returned cursor resumes exclusively.

Source

pub fn idx_count( &self, name: &[u8], min: &IndexValue, max: &IndexValue, ) -> KevyResult<u64>

Count without materializing keys.

Source

pub fn idx_stats(&self, name: &[u8]) -> KevyResult<SegmentStats>

Summed segment stats (entries / bytes / coerce failures / unique-fence duplicates).

Source

pub fn idx_list(&self) -> Vec<(Vec<u8>, Vec<u8>, IndexKind)>

Declared indexes (name, prefix, kind), declaration order.

Source

pub fn idx_match( &self, name: &[u8], query: &[u8], limit: usize, ) -> KevyResult<Vec<(Vec<u8>, f64)>>

MATCH — BM25-ranked hits merged across shards, scored against global corpus statistics so a hit’s rank does not depend on which shard it landed on (see docs/text-search.md).

Two query-time passes: the first sums each shard’s n_docs, total_len and per-query-token df into one [CorpusStats]; the second scores every shard against it. Only the query’s tokens’ df is aggregated, not a whole-corpus table — the query narrows it.

Source

pub fn idx_create_agg( &self, name: &[u8], prefix: &[u8], field: &[u8], ty: ValType, group_by: &[u8], ) -> KevyResult<()>

Declare an aggregate index (KIND agg — write-time GROUP BY). ty must be numeric.

Source

pub fn idx_group(&self, name: &[u8], group: &[u8]) -> KevyResult<GroupStats>

One group’s merged stats across shards.

Source

pub fn idx_groups( &self, name: &[u8], by: AggBy, limit: usize, ) -> KevyResult<Vec<(Vec<u8>, GroupStats)>>

Top groups merged + ranked across shards.

Source

pub fn idx_knn( &self, name: &[u8], query: &[f32], k: usize, ef: usize, ) -> KevyResult<Vec<(Vec<u8>, f32)>>

KNN — nearest neighbors merged ascending across shards. ef = query beam width (0 = engine default; recall knob).

Source§

impl Store

Source

pub fn table_declare(&self, spec: TableSpec) -> KevyResult<()>

TABLE.DECLARE equivalent: admit the declaration, then build every compiled index synchronously. Atomic against catalog errors: names are dry-run against a catalog clone first, so a collision installs nothing.

Source

pub fn table_ensure(&self, spec: TableSpec) -> KevyResult<TableEnsure>

TABLE.ENSURE equivalent — the boot verb.

The dogfood report’s F8.2: declaring at boot is the steady state, and plain table_declare punishes it — a re-declare is an error, so the obvious code (declare, log the error at debug) keeps running against whatever shape the first boot declared, forever, silently. ensure gives the boot path its true verb: an identical spec is a no-op success, a changed spec is a named refusal carrying what changed — never a silent rebuild, because a rebuild is a full backfill and must be asked for by name (Self::table_replace).

Source

pub fn table_replace(&self, spec: TableSpec) -> KevyResult<()>

TABLE.REPLACE equivalent — drop and redeclare, rebuilding every compiled index from the rows. Explicitly named because it is a full backfill: the cost is asked for, not implied. The new spec is compiled (and therefore validated) before the old table is dropped, so a bad replacement leaves the old one standing.

Source

pub fn table_drop(&self, name: &[u8]) -> bool

TABLE.DROP equivalent — drops the table AND its compiled indexes; false if absent.

Source

pub fn table_list(&self) -> Vec<TableSpec>

Declared tables, declaration order.

Source

pub fn table_verify( &self, name: &[u8], ) -> KevyResult<(Vec<(Vec<u8>, [u64; 6])>, [u64; 2])>

👎Deprecated since 4.1.0:

use table_verify_report, whose fields are named

TABLE.VERIFY equivalent: each compiled index’s full drift recheck (the IDX.VERIFY discipline — composites re-derive their byte encoding) plus a bounded column-type spot check, both through the no-promote peek.

Source

pub fn table_verify_report(&self, name: &[u8]) -> KevyResult<TableVerify>

TABLE.VERIFY, with every counter named and its time semantics documented on the field (see IndexVerify).

Source§

impl Store

Source

pub fn view_create( &self, name: &[u8], tree: Tree, order_by: &[u8], desc: bool, mode: ViewMode, ) -> KevyResult<()>

Declare a view (typed tree; via is not supported embedded — read fields in-process). Builds synchronously.

Source

pub fn view_drop(&self, name: &[u8]) -> bool

Drop a view; false if absent.

Source

pub fn view_query( &self, name: &[u8], after: Option<&(IndexValue, Vec<u8>)>, limit: usize, ) -> KevyResult<ViewPage>

Ordered page across shards (after resumes exclusively; DESC views page from the large end).

Source

pub fn view_list(&self) -> Vec<(Vec<u8>, ViewMode, usize)>

Declared views (name, mode, leaves).

Source

pub fn view_count(&self, name: &[u8]) -> KevyResult<u64>

Summed member count across shards.

Source§

impl Store

Source

pub fn snapshot(&self) -> Snapshot

Freeze a consistent point-in-time Snapshot of the whole keyspace (see the module doc for the locking discipline).

Source§

impl Store

Source

pub fn zinterstore( &self, dst: &[u8], keys: &[&[u8]], weights: Option<&[f64]>, aggregate: ZAggregate, ) -> KevyResult<usize>

ZINTERSTORE dst keys… [WEIGHTS …] [AGGREGATE SUM|MIN|MAX] — returns the stored cardinality.

Source

pub fn zunionstore( &self, dst: &[u8], keys: &[&[u8]], weights: Option<&[f64]>, aggregate: ZAggregate, ) -> KevyResult<usize>

ZUNIONSTORE dst keys… [WEIGHTS …] [AGGREGATE …].

Source

pub fn zdiffstore(&self, dst: &[u8], keys: &[&[u8]]) -> KevyResult<usize>

ZDIFFSTORE dst keys… (no weights/aggregate — Redis 6.2).

Source

pub fn zintercard(&self, keys: &[&[u8]], limit: usize) -> KevyResult<usize>

ZINTERCARD keys… [LIMIT n]limit = 0 means unlimited.

Source

pub fn sinterstore(&self, dst: &[u8], keys: &[&[u8]]) -> KevyResult<usize>

SINTERSTORE dst keys… — set-algebra store form (members only).

Source

pub fn sunionstore(&self, dst: &[u8], keys: &[&[u8]]) -> KevyResult<usize>

SUNIONSTORE dst keys….

Source

pub fn sdiffstore(&self, dst: &[u8], keys: &[&[u8]]) -> KevyResult<usize>

SDIFFSTORE dst keys….

Source§

impl Store

Source

pub fn zadd_flags( &self, key: &[u8], pairs: &[(f64, &[u8])], flags: ZaddFlags, ) -> KevyResult<ZaddReport>

Flags-aware ZADD. See ZaddFlags; read ZaddReport::changed for the CH reply shape. The monotonic-heal idiom is zadd_flags(k, pairs, ZaddFlags { gt: true, ..Default::default() }).

Source

pub fn zadd_incr( &self, key: &[u8], delta: f64, member: &[u8], flags: ZaddFlags, ) -> KevyResult<Option<f64>>

ZADD … INCR — a conditional ZINCRBY; None when the flags veto the operation.

Source§

impl Store

Source

pub fn scan( &self, cursor: u64, pattern: Option<&[u8]>, count: usize, ) -> (u64, Vec<Vec<u8>>)

SCAN cursor [MATCH pattern] [COUNT n] — return up to count keys, plus the next cursor. cursor = 0 starts the walk; next_cursor = 0 means the walk completed.

count is the page size; pass usize::MAX to drain in one call.

Source

pub fn keys_iter(&self, pattern: Option<&[u8]>) -> IntoIter<Vec<u8>>

Iterator wrapper around Self::scan — emits every matching key as a Vec<u8>. Drains the keyspace in one snapshot at construction time; matches Rust idioms.

Source

pub fn hscan( &self, key: &[u8], cursor: u64, count: usize, ) -> KevyResult<(u64, Vec<(Vec<u8>, Vec<u8>)>)>

HSCAN key cursor [COUNT n] — return up to count (field, value) pairs from the hash at key, plus the next cursor. cursor = 0 starts; next_cursor = 0 means complete.

Source

pub fn hash_iter(&self, key: &[u8]) -> KevyResult<IntoIter<(Vec<u8>, Vec<u8>)>>

Iterator wrapper around Self::hscan.

Source

pub fn zscan( &self, key: &[u8], cursor: u64, count: usize, ) -> KevyResult<(u64, Vec<(Vec<u8>, f64)>)>

ZSCAN key cursor [COUNT n] — return up to count (member, score) pairs from the sorted set at key, in ascending score order, plus the next cursor.

Source

pub fn zset_iter(&self, key: &[u8]) -> KevyResult<IntoIter<(Vec<u8>, f64)>>

Iterator wrapper around Self::zscan.

Source§

impl Store

Source

pub fn writer_addr(&self) -> Option<SocketAddr>

The embed-writer replication listener’s actually-bound address, when this store was opened with Config::with_embed_writer. Open with port 0 to let the OS pick a free port and read the real one back here — the race-free way to run an ephemeral writer (tests, sidecars, one process per scope).

Source§

impl Store

Source

pub fn open(config: Config) -> KevyResult<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_report(&self) -> &OpenReport

What this open’s replay restored — and, crucially, what it could NOT: dropped_bytes > 0 or corrupt means the store recovered less than the files held (the dropped region was quarantined). Turn this into a startup health check / alert — the machine-readable twin of the boot WARN line.

Source

pub fn dispatch_readonly(&self, argv: &[Vec<u8>], out: &mut Vec<u8>)

Answer one RESP request against this store using the SAME read-only verb whitelist the embedded RESP listener serves (Config::with_resp_listener). The reply is appended to out as raw RESP bytes; write verbs answer -ERR like the listener does. This is the programmatic face of the listener — tooling (e.g. kevy-cli --embed) inspects a store without a socket.

Source

pub fn open_replica(upstream: impl Into<String>) -> KevyResult<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 shutdown(&self) -> Result<()>

Flush every shard’s AOF to disk (a real fsync), write the feed continuity marker, then refuse every later write (they fail with KevyError::Closed; reads stay available). Idempotent and clone-safe: any clone’s shutdown gates them all, so a signal handler’s teardown is two deterministic lines — store.shutdown()?; std::process::exit(0) — instead of praying every task’s Arc<Store> drops in time. Writes racing the call may land after the fsync; writes issued after it returns cannot.

Source

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

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. kevy-embedded itself stays elect-protocol-agnostic; the integration glue lives in the application.

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]]) -> KevyResult<()>

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

pub fn tier_counters(&self) -> (u64, u64)

Tiering counters summed across shards: (demotions_total, promotions_total) — the minimal counter pair (the full INFO gauge set is tier_info). Zeros when tiering is off.

Source§

impl Store

Source

pub fn downgrade(&self) -> WeakStore

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

Source§

impl Store

Source

pub fn downgradeable_to_v3(&self) -> Option<bool>

Whether a 3.x binary could still open this data directory — the downgrade window UPGRADING.md describes, as a readable state instead of an assumption.

Some(true): every shard’s AOF still speaks KEVYAOF1, so downgrading is a binary swap back. Some(false): at least one shard has upgraded to v2 (a rewrite ran), so a downgrade needs a keyspace export through a client. None: no AOF is configured — the question has no meaning for a memory-only store.

From an embedder’s dogfood report: their doctor command exists to tell users “where you are and what to do next”, and this state was pub(crate) — so their CHANGELOG had to declare the window closed unconditionally when it was open, observable, and per-directory.

Source

pub fn fsync_aof(&self) -> KevyResult<()>

Durability barrier: flush + fdatasync every shard’s AOF now, regardless of the configured appendfsync policy. On Ok(()), every write acknowledged before this call is on stable storage. The EverySec serving-store idiom:

store.atomic(|c| { /* critical write */ Ok(()) })?;
store.fsync_aof()?; // durable-on-ack for THIS block only

Cost: one fdatasync per dirty shard; a no-op on clean shards. Under appendfsync = always it is a no-op (already durable).

Source

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

BGREWRITEAOF: rebuild every shard’s AOF from current state. Synchronous (despite the RESP name). Returns the summed stats (None if persistence is off / no shard rewrote). Shards mid rewrite are skipped. Emits KevyMetric::Rewrite per shard.

Source

pub fn apply_frame(&self, args: &Argv)

Apply one AOF-format command frame directly to the keyspace — the programmatic face of AOF replay, for hosts that store the log themselves (targets without a filesystem, where the embedding host reads the log back and feeds it in frame by frame on open).

Speaks the same verb set Store::open replays from an on-disk AOF; unknown verbs are skipped (forward compatibility with logs written by a newer kevy). Keyed verbs route to the owning shard; FLUSHALL/FLUSHDB reach every shard. The frame is not re-appended to any AOF — this is the read-back half of the pump, so re-logging would double-apply on the next replay.

Source

pub fn dump_aof_buf(&self) -> Vec<u8>

Serialize the whole keyspace into an in-memory compacted AOF image (magic header + one command stream per key — the same bytes an AOF rewrite puts on disk). The write half of host-mediated persistence: hosts without a filesystem hand this buffer to their own storage, replacing the accumulated append log, and feed it back through Self::apply_frame on the next open.

Each shard is frozen copy-on-write and serialized off-lock, so concurrent readers and writers on other shards are not blocked for the duration of the dump.

Source

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

Snapshot every shard to its dump-{i}.rdb, 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.