kevy_embedded/lib.rs
1//! kevy-embedded — kevy without the network.
2//!
3//! In-process Redis-compatible key–value store: load + reply directly from
4//! your own threads, no TCP, no shards, no reactor. Use this when you want
5//! kevy's data structures + persistence in the same address space as your
6//! app — caches, embedded databases, WASM blobs, sidecar tools.
7//!
8//! Zero crates.io dependencies: only `kevy-store` (the keyspace)
9//! and `kevy-persist` (snapshot + AOF). The whole network layer
10//! (`kevy-rt`, `kevy-sys`, `kevy-uring`) is intentionally NOT pulled in.
11//!
12//! # Quick start
13//!
14//! ```
15//! use kevy_embedded::{Store, Config};
16//!
17//! # fn main() -> std::io::Result<()> {
18//! let s = Store::open(Config::default())?;
19//! s.set(b"greeting", b"hello")?;
20//! assert_eq!(s.get(b"greeting")?, Some(b"hello".to_vec()));
21//! # Ok(())
22//! # }
23//! ```
24//!
25//! # With persistence
26//!
27//! `with_persist(dir)` enables AOF auto-append on every write and replays
28//! on `open` — restart-safe out of the box. Snapshot (`dump-0.rdb`) is
29//! loaded first if present; AOF (`aof-0.aof`) is replayed on top.
30//!
31//! ```no_run
32//! use kevy_embedded::{Store, Config};
33//!
34//! # fn main() -> std::io::Result<()> {
35//! let s = Store::open(Config::default().with_persist("./data"))?;
36//! s.set(b"counter", b"42")?;
37//! drop(s); // flushes AOF on drop
38//!
39//! // Next process: state survives.
40//! let s2 = Store::open(Config::default().with_persist("./data"))?;
41//! assert_eq!(s2.get(b"counter")?, Some(b"42".to_vec()));
42//! # Ok(())
43//! # }
44//! ```
45//!
46//! # When NOT to use this crate
47//!
48//! - You want a Redis-protocol TCP server → use the `kevy` crate's
49//! [`serve`](https://docs.rs/kevy/latest/kevy/fn.serve.html) instead.
50//! - You need cross-process concurrency → kevy-embedded is single-process
51//! (one mutex). Multi-process needs the network layer.
52#![forbid(unsafe_code)]
53#![warn(missing_docs)]
54
55mod config;
56mod info;
57mod metric;
58mod ops;
59mod ops_atomic;
60mod ops_atomic_all;
61mod ops_bitmap;
62mod ops_bonus;
63mod ops_keyspace;
64mod ops_more;
65mod ops_p2;
66mod ops_p3;
67mod ops_pipeline;
68#[cfg(not(target_arch = "wasm32"))]
69mod ops_feed;
70mod ops_blocking;
71mod ops_hash_ttl;
72mod ops_index;
73mod ops_index_sync;
74mod ops_view;
75#[cfg(not(target_arch = "wasm32"))]
76mod listener;
77mod ops_snapshot_view;
78mod ops_zset_algebra;
79mod ops_zset_flags;
80mod op_manifest;
81mod store_glue;
82mod ops_scan;
83pub use ops_atomic::AtomicCtx;
84pub use ops_atomic_all::AtomicAllShards;
85pub use ops_bitmap::BitOp;
86pub use ops_pipeline::Pipeline;
87mod pubsub;
88mod reaper;
89mod shard;
90mod pubsub_bus;
91mod replay;
92#[cfg(not(target_arch = "wasm32"))]
93mod replica_glue;
94#[cfg(not(target_arch = "wasm32"))]
95mod replica_runner;
96#[cfg(not(target_arch = "wasm32"))]
97mod replica_source;
98mod store;
99mod store_inner;
100mod store_persist;
101
102pub use config::{AppendFsync, Config, EvictionPolicy, TtlReaperMode};
103pub use info::KevyInfo;
104pub use metric::KevyMetric;
105pub use kevy_persist::RewriteStats;
106pub use kevy_store::{ExpireStats, HExpireCode, HExpireCond, ScoreBound, StoreError, ZAggregate, ZaddFlags, ZaddReport};
107#[cfg(not(target_arch = "wasm32"))]
108pub use ops_feed::{Change, ChangeBatch, FeedError, PrefixInfo};
109pub use ops_snapshot_view::{Snapshot, SnapshotEntry};
110pub use ops_index::IndexPage;
111pub use ops_view::ViewPage;
112pub use kevy_index::{AggBy, AnnSpec, GroupStats, Leaf as ViewLeaf, Tree as ViewTree, ViewMode};
113pub use kevy_index::{Cursor as IndexCursor, IndexKind, IndexValue, SegmentStats as IndexStats, ValType as IndexValType};
114pub use pubsub::{PubsubFrame, Subscription};
115pub use store::{Store, WeakStore};
116
117/// Feed kevy's clocks on `wasm32-unknown-unknown`, which has neither
118/// `Instant` nor `SystemTime`. Without a host-fed clock, TTL operations and
119/// the reaper would trap. Call [`set_clock_ns`] (monotonic ns, e.g.
120/// `Date.now() * 1e6`) before TTL-sensitive ops and once per `tick`, and
121/// [`set_wall_clock_ms`] (Unix-epoch millis) if you use `XADD` auto-IDs or
122/// `EXPIREAT`. No-ops conceptually on native targets — hence wasm-only.
123#[cfg(all(target_arch = "wasm32", target_os = "unknown"))]
124pub use kevy_store::{set_clock_ns, set_wall_clock_ms};