Files
mytheclipse/crates/mytheclipse-cache/src/lib.rs
T
asepharyana 8106f8943e feat: add 4 new crates (queue, tracing, http, cli) + enhancements to existing crates
New crates:
- mytheclipse-queue: unified job queue with WorkerPool, retry/backoff, DLQ
  Backends: in-memory (default), Redis, NATS, PostgreSQL
- mytheclipse-tracing: tracing subscriber layers with env filter + OTLP/Jaeger export
- mytheclipse-http: HTTP client/server with timeout + tracing, axum server
- mytheclipse-cli: CLI framework with clap derive, built-in subcommands

Enhancements to existing crates:
- mytheclipse-core: SemaphorePool, LeaderElection, HealthRegistry/HealthCheck
- mytheclipse-cache: AutoRefreshCache (bg refresh on miss), CacheMetrics
- mytheclipse-config: ConfigSchema for JSON Schema generation
- mytheclipse-storage: MultipartUploadDriver trait
- mytheclipse-crypto: PASETO v4.local token support

All features compile with --all-features; tests + clippy pass clean.
2026-08-29 16:05:02 +07:00

85 lines
2.4 KiB
Rust

//! # mytheclipse-cache
//!
//! A unified multi-layer cache abstraction that keeps your application from
//! being locked to any single cache provider.
//!
//! - **L1 (in-process) caches**: [`memory::MemoryCache`] (zero-dependency,
//! default) or [`moka_cache::MokaL1`] (high-performance, TTL/max-capacity).
//! - **L2 (distributed) caches**: [`redis::RedisCache`] backed by Redis/Valkey.
//! - **Multi-layer composition**: [`multilayer::MultiLayerCache`] layers an L1
//! over an L2 behind one [`Cache`] face; reads fall through to L2 and
//! backfill L1.
//! - **Cache-aside / auto-refresh**: [`cache_aside::CacheAside`] reads through
//! to a data source on a miss and caches the result.
//!
//! The core [`Cache`] trait is byte-oriented; typed convenience (JSON) is
//! layered on top via [`memory::typed::TypedCache`].
//!
//! ## Example
//!
//! Multi-layer + cache-aside composition (default features):
//!
//! ```no_run
//! # #[cfg(all(feature = "l1-memory", feature = "cache-aside"))]
//! # async fn run() {
//! use mytheclipse_cache::{Cache, MemoryCache, MultiLayerCache, CacheAside};
//! let l1 = MemoryCache::new();
//! let l2 = MemoryCache::new(); // in a real app: a RedisCache
//! let cache = MultiLayerCache::new(l1, l2);
//!
//! cache.set("user:1", b"payload".to_vec(), None).await.unwrap();
//! assert_eq!(cache.get("user:1").await.unwrap(), Some(b"payload".to_vec()));
//!
//! // Cache-aside: fill misses from a source of truth.
//! let aside = CacheAside::new(
//! MemoryCache::new(),
//! |key| async move { Some(format!("data-for-{key}").into_bytes()) },
//! );
//! let _v = aside.get("orders:42").await.unwrap();
//! # }
//! # #[cfg(not(all(feature = "l1-memory", feature = "cache-aside")))]
//! # fn run() {}
//! ```
#![forbid(unsafe_code)]
pub mod traits;
#[cfg(feature = "l1-memory")]
pub mod memory;
#[cfg(feature = "l1-moka")]
pub mod moka_cache;
#[cfg(feature = "l2-redis")]
pub mod redis;
#[cfg(feature = "cache-aside")]
pub mod cache_aside;
#[cfg(feature = "cache-aside")]
pub mod multilayer;
#[cfg(feature = "cache-aside")]
pub mod auto_refresh;
#[cfg(feature = "cache-aside")]
pub mod metrics;
pub use traits::{Cache, CacheError};
#[cfg(feature = "l1-memory")]
pub use memory::MemoryCache;
#[cfg(feature = "l1-moka")]
pub use moka_cache::MokaL1;
#[cfg(feature = "l2-redis")]
pub use redis::RedisCache;
#[cfg(feature = "cache-aside")]
pub use cache_aside::CacheAside;
#[cfg(feature = "cache-aside")]
pub use multilayer::MultiLayerCache;