1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
// This lint name differs across clippy versions; allow it without failing on
// toolchains that pre-date it (CI pins an older clippy than some local builds).
//! # theSix
//!
//! Policy-driven six-tier cache orchestration for Rust.
//!
//! ## Architecture
//!
//! theSix separates the cache system into a **control plane** and a **data plane**:
//!
//! ```text
//! Application
//! │
//! ▼
//! CacheManager ← API / orchestration
//! │
//! ▼
//! Policy Engine ← decides what should happen
//! │
//! ▼
//! Cachelito ← coordinates concurrent state (control plane)
//! │
//! ▼
//! Six-Tier Data Plane ← actual cache implementations
//! ├── L0 request-local
//! ├── L1 hot-local
//! ├── L2 local
//! ├── L3 distributed
//! ├── L4 persistent
//! └── L5 origin-fallback
//! ```
//!
//! The application should never need to know that L3 happens to be Redis.
//!
//! ## `CacheManager`
//!
//! `CacheManager` is the public API. It exposes cache operations
//! (`get`, `get_or_fetch`, `set`, `invalidate`, `remove`, `exists`,
//! `refresh`, `promote`, `demote`) and enforces authentication and
//! authorization before any state is touched.
//!
//! Tier selection is delegated to the policy engine; the application never
//! selects a tier directly.
//!
//! ## Cachelito
//!
//! Cachelito is the control-plane state registry. It uses a sharded
//! fixed-size slot map to track per-key control state (entry state, generation, tier,
//! population ownership, tier health) without storing application payloads.
//!
//! Key invariants:
//! - Control state does not store payload data.
//! - Control guards must not cross `.await` points.
//! - Control guards must not cross I/O.
//!
//! ## Policy Engine
//!
//! The policy engine determines tier selection based on operation type,
//! key metadata, entry metadata, cache state, tier health, and identity.
//!
//! The `CachePolicy` trait is the abstraction; `DefaultPolicy` is a basic
//! implementation. Custom policies can be supplied via the `P` type parameter
//! on `CacheManager`.
//!
//! ## Six Logical Tiers
//!
//! | Tier | Role | Scope | Persistent |
//! |------|------|-------|------------|
//! | L0 | Request-local | Request | No |
//! | L1 | Hot-local | Process | No |
//! | L2 | Local | Process | No |
//! | L3 | Distributed | Cluster | No |
//! | L4 | Persistent | Host | Yes |
//! | L5 | Origin-fallback | External | No |
//!
//! Backend implementations are configurable and not part of the core contract.
//!
//! ## Single-Flight Semantics
//!
//! For a given key, only one caller may populate the cache at a time.
//! Other callers wait for the population to complete. This prevents
//! cache stampedes on concurrent misses.
//!
//! Flow:
//! - First caller becomes population owner → fetches → publishes
//! - Other callers wait → join existing population
//! - Owner failure releases state; waiters receive the error
//!
//! ## Generation Invalidation
//!
//! Every population captures the current generation. If a newer generation
//! exists (due to invalidation), stale population results are rejected.
//!
//! ```text
//! generation 41 → population starts
//! generation 42 → invalidation
//! population 41 completes → rejected (stale)
//! ```
//!
//! ## Concurrency Guarantees
//!
//! - Multiple concurrent readers are supported.
//! - Concurrent reads and writes on unrelated keys do not block each other.
//! - Contention on the same key is coordinated via Cachelito's single-flight.
//! - No global lock around the entire cache hierarchy.
//! - No control guard held across await points.
//!
//! ## Failure Modes
//!
//! - **Tier unavailable**: Policy may route to next tier (fail-open) or fail fast (fail-closed).
//! - **Population failure**: Owner failure releases in-flight state; waiters receive error.
//! - **Stale generation**: Population result rejected if generation changed.
//! - **Timeout**: Waiter or owner timeout releases state and returns `CacheError::Timeout`.
//! - **Unauthenticated**: Request rejected if no identity provided.
//! - **Unauthorized**: Request rejected if policy denies access.
//!
//! ## Example
//!
//! ```no_run
//! use thesix::{CacheManager, CacheTier, CacheContext, MemoryPool, IdentityContext};
//! use std::sync::Arc;
//!
//! # async fn example() {
//! // Create tier stubs, cachelito, policy, registry, and the value pool.
//! let cachelito = thesix::Cachelito::new();
//! let policy = thesix::DefaultPolicy;
//! let registry = thesix::TierRegistry::new();
//! let tiers: Vec<Arc<dyn CacheTier<String>>> = vec![
//! Arc::new(thesix::L0Stub::<String>::new()),
//! Arc::new(thesix::L1Stub::<String>::new()),
//! Arc::new(thesix::L2Stub::<String>::new()),
//! Arc::new(thesix::L3Stub::<String>::new()),
//! Arc::new(thesix::L4Stub::<String>::new()),
//! Arc::new(thesix::L5Stub::<String>::new()),
//! ];
//! let pool = MemoryPool::<String>::new(1024).expect("pool allocation failed");
//!
//! let manager: CacheManager<String, String, thesix::DefaultPolicy> =
//! CacheManager::new(policy, cachelito, registry, tiers, pool);
//!
//! // Build a request context carrying the caller identity (builder pattern).
//! let ctx = CacheContext::new(IdentityContext::new(
//! "alice".to_string(),
//! vec!["reader".to_string()],
//! "tenant-1".to_string(),
//! ));
//!
//! // Application code never selects a tier:
//! let key = "my-key".to_string();
//! let value = manager
//! .get_or_fetch(&key, &ctx, || async { Ok("value".to_string()) })
//! .await;
//! # }
//! ```
//!
//! ## Crate Layout
//!
//! | Module | Purpose |
//! |--------|---------|
//! | `src/manager` | `CacheManager` — public API and orchestration |
//! | `src/control` | `Cachelito` — control-plane state registry |
//! | `src/policy` | Policy engine, operations, decisions |
//! | `src/tier` | Tier abstraction and L0–L5 implementations |
//! | `src/entry` | Entry state, generation, cache entry |
//! | `src/error` | Structured error types |
//! | `src/identity` | Authentication context |
//! | `src/key` | `Key` trait and `KeyRef` borrowed key view |
//! | `src/pool` | `MemoryPool` fixed-capacity value allocator |
pub use Cachelito;
pub use ;
pub use CacheError;
pub use ;
pub use ;
pub use CacheManager;
pub use ;
pub use MemoryPool;
pub use FixedTierStub;
pub use ;
pub use ;
pub use L3RedisBackend;
pub use L4SledBackend;
pub use L5OxigraphBackend;
pub use ;