quickleaf/lib.rs
1//! # Quickleaf Cache
2//!
3//! Quickleaf Cache is a Rust library that provides a simple and efficient in-memory cache with support for filtering, ordering, limiting results, TTL (Time To Live), event notifications, and optional persistent storage. It is designed to be lightweight and easy to use.
4//!
5//! ## Features
6//!
7//! - Insert and remove key-value pairs
8//! - Retrieve values by key
9//! - Clear the cache
10//! - List cache entries with support for filtering, ordering, and limiting results
11//! - **TTL (Time To Live) support** with lazy cleanup
12//! - **Persistent storage** using SQLite (optional feature)
13//! - Custom error handling
14//! - Event notifications for cache operations
15//! - Support for generic values using [valu3](https:
16//!
17//! ## Installation
18//!
19//! Add the following to your `Cargo.toml`:
20//!
21//! ```toml
22//! [dependencies]
23//! quickleaf = "0.4"
24//!
25//! # For persistence support (optional)
26//! quickleaf = { version = "0.4", features = ["persist"] }
27//! ```
28//!
29//! ## Usage
30//!
31//! Here's a basic example of how to use Quickleaf Cache:
32//!
33//! ```rust
34//! use quickleaf::{Quickleaf, ListProps, Order, Filter, prelude::*};
35//! use quickleaf::valu3::value::Value;
36//!
37//! fn main() {
38//! let mut cache = Quickleaf::new(2);
39//! cache.insert("key1", 1);
40//! cache.insert("key2", 2);
41//! cache.insert("key3", 3);
42//!
43//! assert_eq!(cache.get("key1"), None);
44//! assert_eq!(cache.get("key2"), Some(&2.to_value()));
45//! assert_eq!(cache.get("key3"), Some(&3.to_value()));
46//!
47//! let list_props = ListProps::default()
48//! .order(Order::Asc);
49//!
50//! let result = cache.list(list_props).unwrap();
51//! for (key, value) in result {
52//! println!("{}: {}", key, value);
53//! }
54//! }
55//! ```
56//!
57//! ### Using Filters
58//!
59//! You can use filters to narrow down the results when listing cache entries. Here are some examples:
60//!
61//! #### Filter by Start With
62//!
63//! ```rust
64//! use quickleaf::{Quickleaf, ListProps, Order, Filter};
65//!
66//!
67//! fn main() {
68//! let mut cache = Quickleaf::new(10);
69//! cache.insert("apple", 1);
70//! cache.insert("banana", 2);
71//! cache.insert("apricot", 3);
72//!
73//! let list_props = ListProps::default()
74//! .order(Order::Asc)
75//! .filter(Filter::StartWith("ap".to_string()));
76//!
77//! let result = cache.list(list_props).unwrap();
78//! for (key, value) in result {
79//! println!("{}: {}", key, value);
80//! }
81//! }
82//! ```
83//!
84//! #### Filter by End With
85//!
86//! ```rust
87//! use quickleaf::{Quickleaf, ListProps, Order, Filter};
88//!
89//! fn main() {
90//! let mut cache = Quickleaf::new(10);
91//! cache.insert("apple", 1);
92//! cache.insert("banana", 2);
93//! cache.insert("pineapple", 3);
94//!
95//! let list_props = ListProps::default()
96//! .order(Order::Asc)
97//! .filter(Filter::EndWith("apple".to_string()));
98//!
99//! let result = cache.list(list_props).unwrap();
100//! for (key, value) in result {
101//! println!("{}: {}", key, value);
102//! }
103//! }
104//! ```
105//!
106//! #### Filter by Start And End With
107//!
108//! ```rust
109//! use quickleaf::{Quickleaf, ListProps, Order, Filter};
110//!
111//! fn main() {
112//! let mut cache = Quickleaf::new(10);
113//! cache.insert("applemorepie", 1);
114//! cache.insert("banana", 2);
115//! cache.insert("pineapplepie", 3);
116//!
117//! let list_props = ListProps::default()
118//! .order(Order::Asc)
119//! .filter(Filter::StartAndEndWith("apple".to_string(), "pie".to_string()));
120//!
121//! let result = cache.list(list_props).unwrap();
122//! for (key, value) in result {
123//! println!("{}: {}", key, value);
124//! }
125//! }
126//! ```
127//!
128//! ### Using TTL (Time To Live)
129//!
130//! You can set TTL for cache entries to automatically expire them after a certain duration:
131//!
132//! ```rust
133//! use quickleaf::{Quickleaf, Duration};
134//!
135//! fn main() {
136//! let mut cache = Quickleaf::new(10);
137//!
138//!
139//! cache.insert_with_ttl("session", "user_data", Duration::from_secs(5));
140//!
141//!
142//! let mut cache_with_default = Quickleaf::with_default_ttl(10, Duration::from_secs(60));
143//! cache_with_default.insert("key", "value");
144//!
145//!
146//! let removed_count = cache.cleanup_expired();
147//! println!("Removed {} expired items", removed_count);
148//! }
149//! ```
150//!
151//! ### Using Events
152//!
153//! You can use events to get notified when cache entries are inserted, removed, or cleared. Here is an example:
154//!
155//! ```rust
156//! use quickleaf::{Quickleaf, Event, prelude::*};
157//! use std::sync::mpsc::channel;
158//! use quickleaf::valu3::value::Value;
159//!
160//! fn main() {
161//! let (tx, rx) = channel();
162//! let mut cache = Quickleaf::with_sender(10, tx);
163//!
164//! cache.insert("key1", 1);
165//! cache.insert("key2", 2);
166//! cache.insert("key3", 3);
167//!
168//! let mut items = Vec::new();
169//!
170//! for data in rx {
171//! items.push(data);
172//!
173//! if items.len() == 3 {
174//! break;
175//! }
176//! }
177//!
178//! assert_eq!(items.len(), 3);
179//! assert_eq!(
180//! items[0],
181//! Event::insert("key1".to_string(), 1.to_value())
182//! );
183//! assert_eq!(
184//! items[1],
185//! Event::insert("key2".to_string(), 2.to_value())
186//! );
187//! assert_eq!(
188//! items[2],
189//! Event::insert("key3".to_string(), 3.to_value())
190//! );
191//! }
192//! ```
193//!
194//! ### Event Types
195//!
196//! There are three types of events:
197//!
198//! 1. `Insert`: Triggered when a new entry is inserted into the cache.
199//! 2. `Remove`: Triggered when an entry is removed from the cache.
200//! 3. `Clear`: Triggered when the cache is cleared.
201//!
202//! ## Persistent Storage (Optional)
203//!
204//! Quickleaf supports optional persistent storage using SQLite as a backing store. This feature
205//! provides durability across application restarts while maintaining high-performance in-memory operations.
206//!
207//! ### Enabling Persistence
208//!
209//! Add the `persist` feature to your `Cargo.toml`:
210//!
211//! ```toml
212//! [dependencies]
213//! quickleaf = { version = "0.4", features = ["persist"] }
214//! ```
215//!
216//! ### Basic Persistent Cache
217//!
218//! ```rust,no_run
219//! # #[cfg(feature = "persist")]
220//! # {
221//! use quickleaf::Cache;
222//!
223//! fn main() -> Result<(), Box<dyn std::error::Error>> {
224//! let mut cache = Cache::with_persist("cache.db", 1000)?;
225//!
226//! cache.insert("user:123", "Alice");
227//! cache.insert("user:456", "Bob");
228//!
229//! drop(cache);
230//!
231//! let mut cache = Cache::with_persist("cache.db", 1000)?;
232//!
233//! println!("{:?}", cache.get("user:123"));
234//!
235//! Ok(())
236//! }
237//! # }
238//! ```
239//!
240//! ### Persistent Cache with TTL
241//!
242//! ```rust,no_run
243//! # #[cfg(feature = "persist")]
244//! # {
245//! use quickleaf::{Cache, Duration};
246//!
247//! fn main() -> Result<(), Box<dyn std::error::Error>> {
248//! let mut cache = Cache::with_persist("cache.db", 1000)?;
249//!
250//!
251//! cache.insert_with_ttl(
252//! "session:abc",
253//! "temp_data",
254//! Duration::from_secs(3600)
255//! );
256//!
257//! Ok(())
258//! }
259//! # }
260//! ```
261//!
262//! ### Persistence with Events
263//!
264//! ```rust,no_run
265//! # #[cfg(feature = "persist")]
266//! # {
267//! use quickleaf::Cache;
268//! use std::sync::mpsc::channel;
269//!
270//! fn main() -> Result<(), Box<dyn std::error::Error>> {
271//! let (tx, rx) = channel();
272//!
273//! let mut cache = Cache::with_persist_and_sender("cache.db", 1000, tx)?;
274//!
275//! cache.insert("key1", "value1");
276//!
277//! for event in rx.try_iter() {
278//! println!("Event: {:?}", event);
279//! }
280//!
281//! Ok(())
282//! }
283//! # }
284//! ```
285//!
286//! ### Complete Persistence Stack (SQLite + Events + TTL)
287//!
288//! ```rust,no_run
289//! # #[cfg(feature = "persist")]
290//! # {
291//! use quickleaf::Cache;
292//! use std::sync::mpsc::channel;
293//! use std::time::Duration;
294//!
295//! fn main() -> Result<(), Box<dyn std::error::Error>> {
296//! let (tx, rx) = channel();
297//!
298//! let mut cache = Cache::with_persist_and_sender_and_ttl(
299//! "full_featured_cache.db",
300//! 1000,
301//! tx,
302//! Duration::from_secs(3600)
303//! )?;
304//!
305//! cache.insert("session", "user_data");
306//!
307//! cache.insert_with_ttl("temp", "data", Duration::from_secs(60));
308//!
309//! for event in rx.try_iter() {
310//! println!("Event: {:?}", event);
311//! }
312//!
313//! Ok(())
314//! }
315//! # }
316//! ```
317//!
318//! ### Persistence Features
319//!
320//! - **Automatic Persistence**: All cache operations are automatically persisted to SQLite
321//! - **Background Writer**: Non-blocking write operations using a background thread
322//! - **Crash Recovery**: Automatic recovery from unexpected shutdowns
323//! - **TTL Preservation**: TTL values are preserved across restarts
324//! - **Efficient Storage**: Uses SQLite with optimized indexes for performance
325//! - **Seamless Integration**: Works with all existing Quickleaf features
326
327mod cache;
328mod error;
329mod event;
330mod filter;
331pub mod filters;
332mod list_props;
333#[cfg(test)]
334#[cfg(feature = "persist")]
335mod persist_tests;
336pub mod prelude;
337mod quickleaf;
338#[cfg(feature = "persist")]
339mod sqlite_store;
340#[cfg(test)]
341mod tests;
342#[cfg(test)]
343mod ttl_tests;
344
345pub use cache::{Cache, CacheItem};
346pub use error::Error;
347pub use event::{Event, EventData};
348pub use filter::Filter;
349pub use list_props::{ListProps, Order, StartAfter};
350pub use quickleaf::Quickleaf;
351pub use std::time::Duration;
352pub use valu3;
353pub use valu3::value::Value;