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
//! Read policies for controlling read operations across cache layers.
//!
//! This module defines the CompositionReadPolicy trait and its implementations.
//! Different strategies (sequential, race, parallel) can be used to optimize
//! read performance based on application requirements.
use async_trait;
use ;
use Future;
use crateCompositionLayer;
pub use ParallelReadPolicy;
pub use ;
pub use SequentialReadPolicy;
/// Result of a read operation including the value, source layer, and context.
/// Policy trait for controlling read operations across composition cache layers.
///
/// This trait encapsulates the **control flow strategy** (sequential, race, parallel)
/// for reading from multiple cache layers (L1/L2), while delegating the actual read
/// operations to provided closures. This design allows the same policy to be used at
/// both the `CacheBackend` level (typed data) and `Backend` level (raw bytes).
///
/// # Type Parameters
///
/// The policy is generic over:
/// * `T` - The return type (e.g., `CacheValue<User>` or `CacheValue<Raw>`)
/// * `E` - The error type (e.g., `BackendError`)
/// * `F1, F2` - Closures for reading from L1 and L2
/// * `O` - The offload type for background task execution
///
/// # Example
///
/// ```ignore
/// use hitbox_backend::composition::policy::CompositionReadPolicy;
///
/// let policy = SequentialReadPolicy::default();
///
/// // Use with CacheBackend level (key is cloned for each closure)
/// let result = policy.execute_with(
/// key.clone(),
/// |k| async move { (l1.get::<User>(&k, &mut ctx).await, ctx) },
/// |k| async move {
/// let value = l2.get::<User>(&k, &mut ctx).await?;
/// // Populate L1 on L2 hit
/// if let Some(ref v) = value {
/// l1.set::<User>(&k, v, v.ttl(), &mut ctx.clone_box()).await.ok();
/// }
/// Ok((value, ctx))
/// },
/// &offload,
/// ).await?;
/// ```