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 kevy_store::Store + AOF +
reaper + pub/sub bus. The reaper thread is joined and the 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. The internal Arc<Mutex<Inner>> is what
makes shared access safe under contention.
Implementations§
Source§impl Store
impl Store
Sourcepub fn set(&self, key: &[u8], value: &[u8]) -> Result<bool>
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).
Examples found in repository?
More examples
9fn main() -> std::io::Result<()> {
10 let s = Store::open(
11 Config::default()
12 .with_max_memory(200 * 1024)
13 .with_eviction(EvictionPolicy::AllKeysLru),
14 )?;
15
16 for i in 0..10_000 {
17 let key = format!("user:{i:05}");
18 let val = format!("user-payload-{i}");
19 s.set(key.as_bytes(), val.as_bytes())?;
20 }
21
22 println!("dbsize after insert flood: {}", s.dbsize());
23 println!("used_memory: {} bytes (limit 200 KiB)", s.used_memory());
24 println!("evictions_total: {}", s.evictions_total());
25
26 // Touch a recent key — it should still be live.
27 let recent = format!("user:0{}", 9999);
28 println!(
29 "user:09999 → {:?}",
30 s.get(recent.as_bytes())?.as_deref().map(String::from_utf8_lossy)
31 );
32
33 Ok(())
34}Sourcepub fn set_with_ttl(
&self,
key: &[u8],
value: &[u8],
ttl: Duration,
) -> Result<bool>
pub fn set_with_ttl( &self, key: &[u8], value: &[u8], ttl: Duration, ) -> Result<bool>
SET key value PX ms — overwrites + sets TTL.
Sourcepub fn get(&self, key: &[u8]) -> Result<Option<Vec<u8>>>
pub fn get(&self, key: &[u8]) -> Result<Option<Vec<u8>>>
GET key — Some(bytes) on hit, None on miss or expired.
Examples found in repository?
More examples
9fn main() -> std::io::Result<()> {
10 let s = Store::open(
11 Config::default()
12 .with_max_memory(200 * 1024)
13 .with_eviction(EvictionPolicy::AllKeysLru),
14 )?;
15
16 for i in 0..10_000 {
17 let key = format!("user:{i:05}");
18 let val = format!("user-payload-{i}");
19 s.set(key.as_bytes(), val.as_bytes())?;
20 }
21
22 println!("dbsize after insert flood: {}", s.dbsize());
23 println!("used_memory: {} bytes (limit 200 KiB)", s.used_memory());
24 println!("evictions_total: {}", s.evictions_total());
25
26 // Touch a recent key — it should still be live.
27 let recent = format!("user:0{}", 9999);
28 println!(
29 "user:09999 → {:?}",
30 s.get(recent.as_bytes())?.as_deref().map(String::from_utf8_lossy)
31 );
32
33 Ok(())
34}Sourcepub fn del(&self, keys: &[&[u8]]) -> Result<usize>
pub fn del(&self, keys: &[&[u8]]) -> Result<usize>
DEL key1 [key2 ...]. Returns the count of keys actually removed.
Sourcepub fn exists(&self, keys: &[&[u8]]) -> Result<usize>
pub fn exists(&self, keys: &[&[u8]]) -> Result<usize>
EXISTS key1 [key2 ...]. Count of existing keys (duplicates counted
multiple times, matching Redis).
Sourcepub fn incr_by(&self, key: &[u8], delta: i64) -> Result<i64>
pub fn incr_by(&self, key: &[u8], delta: i64) -> Result<i64>
INCRBY key delta. Negative delta does DECR-style work.
Sourcepub fn expire(&self, key: &[u8], ttl: Duration) -> Result<bool>
pub fn expire(&self, key: &[u8], ttl: Duration) -> Result<bool>
EXPIRE key seconds. Returns true if a key was touched.
Sourcepub fn persist(&self, key: &[u8]) -> Result<bool>
pub fn persist(&self, key: &[u8]) -> Result<bool>
PERSIST key. Returns true if a TTL was actually cleared.
Sourcepub fn ttl_ms(&self, key: &[u8]) -> i64
pub fn ttl_ms(&self, key: &[u8]) -> i64
Remaining TTL in ms (or Redis-style -1/-2 for no-TTL/no-key).
Sourcepub fn type_of(&self, key: &[u8]) -> &'static str
pub fn type_of(&self, key: &[u8]) -> &'static str
TYPE key — "string", "hash", "list", "set", "zset", or "none".
Sourcepub fn dbsize(&self) -> usize
pub fn dbsize(&self) -> usize
DBSIZE — total live keys.
Examples found in repository?
More examples
9fn main() -> std::io::Result<()> {
10 let s = Store::open(
11 Config::default()
12 .with_max_memory(200 * 1024)
13 .with_eviction(EvictionPolicy::AllKeysLru),
14 )?;
15
16 for i in 0..10_000 {
17 let key = format!("user:{i:05}");
18 let val = format!("user-payload-{i}");
19 s.set(key.as_bytes(), val.as_bytes())?;
20 }
21
22 println!("dbsize after insert flood: {}", s.dbsize());
23 println!("used_memory: {} bytes (limit 200 KiB)", s.used_memory());
24 println!("evictions_total: {}", s.evictions_total());
25
26 // Touch a recent key — it should still be live.
27 let recent = format!("user:0{}", 9999);
28 println!(
29 "user:09999 → {:?}",
30 s.get(recent.as_bytes())?.as_deref().map(String::from_utf8_lossy)
31 );
32
33 Ok(())
34}Sourcepub fn flush(&self) -> Result<()>
pub fn flush(&self) -> Result<()>
FLUSHALL — empty the keyspace (logged so a replay reaches the same
empty state).
Sourcepub fn key_bytes(&self, key: &[u8]) -> Option<u64>
pub fn key_bytes(&self, key: &[u8]) -> Option<u64>
MEMORY USAGE for one key — Some(bytes) or None if absent.
Sourcepub fn used_memory(&self) -> u64
pub fn used_memory(&self) -> u64
Live used_memory estimate (matches INFO memory’s field).
Examples found in repository?
9fn main() -> std::io::Result<()> {
10 let s = Store::open(
11 Config::default()
12 .with_max_memory(200 * 1024)
13 .with_eviction(EvictionPolicy::AllKeysLru),
14 )?;
15
16 for i in 0..10_000 {
17 let key = format!("user:{i:05}");
18 let val = format!("user-payload-{i}");
19 s.set(key.as_bytes(), val.as_bytes())?;
20 }
21
22 println!("dbsize after insert flood: {}", s.dbsize());
23 println!("used_memory: {} bytes (limit 200 KiB)", s.used_memory());
24 println!("evictions_total: {}", s.evictions_total());
25
26 // Touch a recent key — it should still be live.
27 let recent = format!("user:0{}", 9999);
28 println!(
29 "user:09999 → {:?}",
30 s.get(recent.as_bytes())?.as_deref().map(String::from_utf8_lossy)
31 );
32
33 Ok(())
34}Sourcepub fn evictions_total(&self) -> u64
pub fn evictions_total(&self) -> u64
INFO-style counter: total keys evicted by maxmemory so far.
Examples found in repository?
9fn main() -> std::io::Result<()> {
10 let s = Store::open(
11 Config::default()
12 .with_max_memory(200 * 1024)
13 .with_eviction(EvictionPolicy::AllKeysLru),
14 )?;
15
16 for i in 0..10_000 {
17 let key = format!("user:{i:05}");
18 let val = format!("user-payload-{i}");
19 s.set(key.as_bytes(), val.as_bytes())?;
20 }
21
22 println!("dbsize after insert flood: {}", s.dbsize());
23 println!("used_memory: {} bytes (limit 200 KiB)", s.used_memory());
24 println!("evictions_total: {}", s.evictions_total());
25
26 // Touch a recent key — it should still be live.
27 let recent = format!("user:0{}", 9999);
28 println!(
29 "user:09999 → {:?}",
30 s.get(recent.as_bytes())?.as_deref().map(String::from_utf8_lossy)
31 );
32
33 Ok(())
34}Sourcepub fn expired_keys_total(&self) -> u64
pub fn expired_keys_total(&self) -> u64
INFO-style counter: total keys expired (lazy + active reaper).
Sourcepub fn hset(&self, key: &[u8], pairs: &[(&[u8], &[u8])]) -> Result<usize>
pub fn hset(&self, key: &[u8], pairs: &[(&[u8], &[u8])]) -> Result<usize>
HSET key field value [field value ...]. Returns count newly added.
Sourcepub fn hget(&self, key: &[u8], field: &[u8]) -> Result<Option<Vec<u8>>>
pub fn hget(&self, key: &[u8], field: &[u8]) -> Result<Option<Vec<u8>>>
HGET key field. None if absent.
Sourcepub fn hdel(&self, key: &[u8], fields: &[&[u8]]) -> Result<usize>
pub fn hdel(&self, key: &[u8], fields: &[&[u8]]) -> Result<usize>
HDEL key field [field ...]. Returns count actually removed.
Sourcepub fn lpush(&self, key: &[u8], values: &[&[u8]]) -> Result<usize>
pub fn lpush(&self, key: &[u8], values: &[&[u8]]) -> Result<usize>
LPUSH key value [value ...]. Returns the new list length.
Sourcepub fn rpush(&self, key: &[u8], values: &[&[u8]]) -> Result<usize>
pub fn rpush(&self, key: &[u8], values: &[&[u8]]) -> Result<usize>
RPUSH key value [value ...]. Returns the new list length.
Sourcepub fn lpop(&self, key: &[u8], count: usize) -> Result<Vec<Vec<u8>>>
pub fn lpop(&self, key: &[u8], count: usize) -> Result<Vec<Vec<u8>>>
LPOP key count. Returns popped values from the head.
Sourcepub fn rpop(&self, key: &[u8], count: usize) -> Result<Vec<Vec<u8>>>
pub fn rpop(&self, key: &[u8], count: usize) -> Result<Vec<Vec<u8>>>
RPOP key count. Symmetric to LPOP from the tail.
Sourcepub fn llen(&self, key: &[u8]) -> Result<usize>
pub fn llen(&self, key: &[u8]) -> Result<usize>
LLEN key. Length of the list at key; 0 if absent.
Sourcepub fn sadd(&self, key: &[u8], members: &[&[u8]]) -> Result<usize>
pub fn sadd(&self, key: &[u8], members: &[&[u8]]) -> Result<usize>
SADD key member [member ...]. Returns count newly added.
Sourcepub fn srem(&self, key: &[u8], members: &[&[u8]]) -> Result<usize>
pub fn srem(&self, key: &[u8], members: &[&[u8]]) -> Result<usize>
SREM key member [member ...]. Returns count actually removed.
Sourcepub fn smembers(&self, key: &[u8]) -> Result<Vec<Vec<u8>>>
pub fn smembers(&self, key: &[u8]) -> Result<Vec<Vec<u8>>>
SMEMBERS key. Order implementation-defined; empty if absent.
Sourcepub fn zadd(&self, key: &[u8], pairs: &[(f64, &[u8])]) -> Result<usize>
pub fn zadd(&self, key: &[u8], pairs: &[(f64, &[u8])]) -> Result<usize>
ZADD key score member [score member ...]. Returns count newly added.
Sourcepub fn zrem(&self, key: &[u8], members: &[&[u8]]) -> Result<usize>
pub fn zrem(&self, key: &[u8], members: &[&[u8]]) -> Result<usize>
ZREM key member [member ...]. Returns count actually removed.
Sourcepub fn zscore(&self, key: &[u8], member: &[u8]) -> Result<Option<f64>>
pub fn zscore(&self, key: &[u8], member: &[u8]) -> Result<Option<f64>>
ZSCORE key member. Some(score) if present.
Sourcepub fn publish(&self, channel: &[u8], payload: &[u8]) -> usize
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.
Sourcepub fn subscribe(&self, channels: &[&[u8]]) -> Subscription
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.
Sourcepub fn psubscribe(&self, patterns: &[&[u8]]) -> Subscription
pub fn psubscribe(&self, patterns: &[&[u8]]) -> Subscription
Convenience: open a Subscription starting on pattern subscriptions.
Source§impl Store
impl Store
Sourcepub fn open(config: Config) -> Result<Self>
pub fn open(config: Config) -> Result<Self>
Open an embedded keyspace per config.
- Pure in-memory when
config.data_dirisNone. - With persistence: loads
<data_dir>/<snapshot_filename>first, then replays<data_dir>/<aof_filename>. Both are best-effort — missing files are fine, a truncated AOF tail is silently dropped. - Spawns a background TTL reaper thread when
config.ttl_reaper == Background(the default).
Examples found in repository?
More examples
9fn main() -> std::io::Result<()> {
10 let s = Store::open(
11 Config::default()
12 .with_max_memory(200 * 1024)
13 .with_eviction(EvictionPolicy::AllKeysLru),
14 )?;
15
16 for i in 0..10_000 {
17 let key = format!("user:{i:05}");
18 let val = format!("user-payload-{i}");
19 s.set(key.as_bytes(), val.as_bytes())?;
20 }
21
22 println!("dbsize after insert flood: {}", s.dbsize());
23 println!("used_memory: {} bytes (limit 200 KiB)", s.used_memory());
24 println!("evictions_total: {}", s.evictions_total());
25
26 // Touch a recent key — it should still be live.
27 let recent = format!("user:0{}", 9999);
28 println!(
29 "user:09999 → {:?}",
30 s.get(recent.as_bytes())?.as_deref().map(String::from_utf8_lossy)
31 );
32
33 Ok(())
34}Sourcepub fn downgrade(&self) -> WeakStore
pub fn downgrade(&self) -> WeakStore
Get a weak handle that does not keep the keyspace alive.
upgrade() returns None once the last strong Store is dropped.
Sourcepub fn config(&self) -> &Config
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.
Sourcepub fn with<F, R>(&self, f: F) -> R
pub fn with<F, R>(&self, f: F) -> R
Run f against the underlying kevy_store::Store under the
embedded mutex. Use for direct access to methods this crate hasn’t
wrapped (snapshot iteration, ZRANGE, raw collect_keys, …). The
closure can mutate, but does not auto-log to the AOF — call
Self::log yourself if the mutation must survive a crash.
Sourcepub fn log(&self, parts: &[&[u8]]) -> Result<()>
pub fn log(&self, parts: &[&[u8]]) -> Result<()>
Append a raw RESP-frame argument list to the AOF. Pairs with
Self::with when the closure performed a write you want to make
crash-safe. No-op when persistence is disabled.
Sourcepub fn tick(&self) -> ExpireStats
pub fn tick(&self) -> ExpireStats
Run one TTL-reaper tick. Required call cadence in Manual mode
(call ~10× per second to match Redis’s hz=10); no-op cost is
one mutex lock + map-emptiness check when nothing has TTL.
Sourcepub fn rewrite_aof(&self) -> Result<Option<RewriteStats>>
pub fn rewrite_aof(&self) -> Result<Option<RewriteStats>>
BGREWRITEAOF: rebuild the AOF from current state. Synchronous —
blocks until the rewrite + atomic rename completes. Returns
Ok(None) when persistence is disabled.
Sourcepub fn save_snapshot(&self) -> Result<bool>
pub fn save_snapshot(&self) -> Result<bool>
Snapshot the store to <data_dir>/<snapshot_filename>, atomically.
Ok(false) when persistence is disabled (caller can decide to
surface that or no-op).