multi_tier_cache/lib.rs
1//! Multi-Tier Cache
2//!
3//! A high-performance, production-ready multi-tier caching library for Rust featuring:
4//! - **L1 Cache**: In-memory caching with Moka (sub-millisecond latency)
5//! - **L2 Cache**: Distributed caching with Redis (persistent storage)
6//! - **Cache Stampede Protection**: DashMap + Mutex request coalescing
7//! - **Redis Streams**: Built-in support for event streaming
8//! - **Automatic L2-to-L1 Promotion**: Intelligent cache tier promotion
9//! - **Comprehensive Statistics**: Hit rates, promotions, in-flight tracking
10//!
11//! # Quick Start
12//!
13//! ```rust,no_run
14//! use multi_tier_cache::{CacheSystem, CacheStrategy};
15//!
16//! #[tokio::main]
17//! async fn main() -> anyhow::Result<()> {
18//! // Initialize cache system
19//! let cache = CacheSystem::new().await?;
20//!
21//! // Store data with cache strategy
22//! let data = serde_json::json!({"user": "alice", "score": 100});
23//! cache.cache_manager()
24//! .set_with_strategy("user:1", data, CacheStrategy::ShortTerm)
25//! .await?;
26//!
27//! // Retrieve data (L1 first, then L2 fallback)
28//! if let Some(cached) = cache.cache_manager().get("user:1").await? {
29//! println!("Cached data: {}", cached);
30//! }
31//!
32//! // Get statistics
33//! let stats = cache.cache_manager().get_stats();
34//! println!("Hit rate: {:.2}%", stats.hit_rate);
35//!
36//! Ok(())
37//! }
38//! ```
39//!
40//! # Features
41//!
42//! - **Multi-Tier Architecture**: Combines fast in-memory (L1) with persistent distributed (L2) caching
43//! - **Cache Stampede Protection**: Prevents duplicate computations during cache misses
44//! - **Redis Streams**: Publish/subscribe with automatic trimming
45//! - **Zero-Config**: Sensible defaults, works out of the box
46//! - **Production-Proven**: Battle-tested at 16,829+ RPS with 5.2ms latency
47//!
48//! # Architecture
49//!
50//! ```text
51//! Request → L1 Cache (Moka) → L2 Cache (Redis) → Compute/Fetch
52//! ↓ Hit (90%) ↓ Hit (75%) ↓ Miss (5%)
53//! Return Promote to L1 Store in L1+L2
54//! ```
55
56use std::sync::Arc;
57use anyhow::Result;
58
59pub mod backends;
60pub mod cache_manager;
61pub mod traits;
62pub mod builder;
63pub mod invalidation;
64pub mod redis_streams;
65
66// Re-export backend types (maintains backward compatibility)
67pub use backends::{
68 L1Cache, L2Cache, // Type aliases
69 MokaCache, RedisCache, // Default backends
70 DashMapCache, // Additional backends
71};
72
73// Optional backends (feature-gated)
74#[cfg(feature = "backend-memcached")]
75pub use backends::MemcachedCache;
76
77#[cfg(feature = "backend-quickcache")]
78pub use backends::QuickCacheBackend;
79pub use cache_manager::{
80 CacheManager, CacheStrategy, CacheManagerStats,
81 // Multi-tier support (v0.5.0+)
82 TierConfig, CacheTier, TierStats,
83};
84pub use traits::{CacheBackend, L2CacheBackend, StreamingBackend};
85pub use builder::CacheSystemBuilder;
86pub use invalidation::{
87 InvalidationConfig, InvalidationMessage, InvalidationStats,
88 InvalidationPublisher, InvalidationSubscriber,
89};
90pub use redis_streams::RedisStreams;
91
92// Re-export async_trait for user convenience
93pub use async_trait::async_trait;
94
95/// Main entry point for the Multi-Tier Cache system
96///
97/// Provides unified access to L1 (Moka) and L2 (Redis) caches with
98/// automatic failover, promotion, and stampede protection.
99///
100/// # Example
101///
102/// ```rust,no_run
103/// use multi_tier_cache::CacheSystem;
104///
105/// #[tokio::main]
106/// async fn main() -> anyhow::Result<()> {
107/// let cache = CacheSystem::new().await?;
108///
109/// // Use cache_manager for all operations
110/// let manager = cache.cache_manager();
111///
112/// Ok(())
113/// }
114/// ```
115#[derive(Clone)]
116pub struct CacheSystem {
117 /// Unified cache manager (primary interface)
118 pub cache_manager: Arc<CacheManager>,
119 /// L1 Cache (in-memory, Moka)
120 pub l1_cache: Arc<L1Cache>,
121 /// L2 Cache (distributed, Redis)
122 pub l2_cache: Arc<L2Cache>,
123}
124
125impl CacheSystem {
126 /// Create new cache system with default configuration
127 ///
128 /// # Configuration
129 ///
130 /// Redis connection is configured via `REDIS_URL` environment variable.
131 /// Default: `redis://127.0.0.1:6379`
132 ///
133 /// # Example
134 ///
135 /// ```rust,no_run
136 /// use multi_tier_cache::CacheSystem;
137 ///
138 /// #[tokio::main]
139 /// async fn main() -> anyhow::Result<()> {
140 /// // Set environment variable (optional)
141 /// std::env::set_var("REDIS_URL", "redis://localhost:6379");
142 ///
143 /// let cache = CacheSystem::new().await?;
144 /// Ok(())
145 /// }
146 /// ```
147 pub async fn new() -> Result<Self> {
148 println!("🏗️ Initializing Multi-Tier Cache System...");
149
150 // Initialize L1 cache (Moka)
151 let l1_cache = Arc::new(L1Cache::new().await?);
152
153 // Initialize L2 cache (Redis)
154 let l2_cache = Arc::new(L2Cache::new().await?);
155
156 // Initialize cache manager
157 let cache_manager = Arc::new(CacheManager::new(l1_cache.clone(), l2_cache.clone()).await?);
158
159 println!("✅ Multi-Tier Cache System initialized successfully");
160
161 Ok(Self {
162 cache_manager,
163 l1_cache,
164 l2_cache,
165 })
166 }
167
168 /// Create cache system with custom Redis URL
169 ///
170 /// # Arguments
171 ///
172 /// * `redis_url` - Redis connection string (e.g., "redis://localhost:6379")
173 ///
174 /// # Example
175 ///
176 /// ```rust,no_run
177 /// use multi_tier_cache::CacheSystem;
178 ///
179 /// #[tokio::main]
180 /// async fn main() -> anyhow::Result<()> {
181 /// let cache = CacheSystem::with_redis_url("redis://custom:6379").await?;
182 /// Ok(())
183 /// }
184 /// ```
185 pub async fn with_redis_url(redis_url: &str) -> Result<Self> {
186 // Temporarily set environment variable for L2Cache initialization
187 std::env::set_var("REDIS_URL", redis_url);
188 Self::new().await
189 }
190
191 /// Perform health check on all cache tiers
192 ///
193 /// Returns `true` if at least L1 is operational.
194 /// L2 failure is tolerated (graceful degradation).
195 ///
196 /// # Example
197 ///
198 /// ```rust,no_run
199 /// use multi_tier_cache::CacheSystem;
200 ///
201 /// #[tokio::main]
202 /// async fn main() -> anyhow::Result<()> {
203 /// let cache = CacheSystem::new().await?;
204 ///
205 /// if cache.health_check().await {
206 /// println!("Cache system healthy");
207 /// }
208 ///
209 /// Ok(())
210 /// }
211 /// ```
212 pub async fn health_check(&self) -> bool {
213 let l1_ok = self.l1_cache.health_check().await;
214 let l2_ok = self.l2_cache.health_check().await;
215
216 if l1_ok && l2_ok {
217 println!(" ✅ Multi-Tier Cache health check passed");
218 true
219 } else {
220 println!(" ⚠️ Multi-Tier Cache health check - L1: {}, L2: {}", l1_ok, l2_ok);
221 l1_ok // At minimum, L1 should work
222 }
223 }
224
225 /// Get reference to cache manager (primary interface)
226 ///
227 /// Use this for all cache operations: get, set, streams, etc.
228 pub fn cache_manager(&self) -> &Arc<CacheManager> {
229 &self.cache_manager
230 }
231}