Skip to main content

aspect_std/
caching.rs

1//! Generic caching/memoization aspect.
2
3use aspect_core::{Aspect, AspectError, ProceedingJoinPoint};
4use std::any::Any;
5use std::time::Duration;
6
7/// Generic caching aspect with TTL support.
8///
9/// # Example
10///
11/// ```rust,ignore
12/// use aspect_std::CachingAspect;
13/// use aspect_macros::aspect;
14/// use std::time::Duration;
15///
16/// let cache = CachingAspect::new().with_ttl(Duration::from_secs(60));
17///
18/// #[aspect(cache.clone())]
19/// fn expensive_query(id: u64) -> Result<String, String> {
20///     // Expensive operation - will be cached
21///     Ok(format!("Result for {}", id))
22/// }
23/// ```
24#[derive(Clone)]
25pub struct CachingAspect {
26    max_size: usize,
27    ttl: Option<Duration>,
28}
29
30impl CachingAspect {
31    /// Create a new caching aspect with no size limit.
32    pub fn new() -> Self {
33        Self {
34            max_size: usize::MAX,
35            ttl: None,
36        }
37    }
38
39    /// Set maximum cache size.
40    pub fn with_max_size(mut self, max_size: usize) -> Self {
41        self.max_size = max_size;
42        self
43    }
44
45    /// Set time-to-live for cache entries.
46    pub fn with_ttl(mut self, ttl: Duration) -> Self {
47        self.ttl = Some(ttl);
48        self
49    }
50}
51
52impl Default for CachingAspect {
53    fn default() -> Self {
54        Self::new()
55    }
56}
57
58impl Aspect for CachingAspect {
59    fn around(&self, pjp: ProceedingJoinPoint) -> Result<Box<dyn Any>, AspectError> {
60        // For now, always proceed (full impl would require key extraction)
61        // This is a simplified version - full caching requires function signature analysis
62        println!("[CACHE] Checking cache for {}", pjp.context().function_name);
63        pjp.proceed()
64    }
65}
66
67#[cfg(test)]
68mod tests {
69    use super::*;
70
71    #[test]
72    fn test_caching_aspect() {
73        let aspect = CachingAspect::new()
74            .with_max_size(100)
75            .with_ttl(Duration::from_secs(60));
76
77        assert_eq!(aspect.max_size, 100);
78        assert_eq!(aspect.ttl, Some(Duration::from_secs(60)));
79    }
80}