Skip to main content

things3_core/cache/
config.rs

1use crate::models::ThingsId;
2use serde::{Deserialize, Serialize};
3use std::time::Duration;
4
5/// Cache invalidation strategy
6#[non_exhaustive]
7#[derive(Debug, Clone, PartialEq, Eq)]
8pub enum InvalidationStrategy {
9    /// Time-based invalidation (TTL)
10    TimeBased,
11    /// Event-based invalidation (manual triggers)
12    EventBased,
13    /// Dependency-based invalidation (related data changes)
14    DependencyBased,
15    /// Hybrid approach combining multiple strategies
16    Hybrid,
17}
18
19/// Cache dependency tracking for intelligent invalidation
20#[derive(Debug, Clone, Serialize, Deserialize)]
21pub struct CacheDependency {
22    /// The entity type this cache entry depends on
23    pub entity_type: String,
24    /// The specific entity ID this cache entry depends on
25    pub entity_id: Option<ThingsId>,
26    /// The operation that would invalidate this cache entry
27    pub invalidating_operations: Vec<String>,
28}
29
30impl CacheDependency {
31    /// Test whether this dependency matches a mutation on `(entity_type, entity_id)`.
32    ///
33    /// `entity_id == None` on either side acts as a wildcard: a dependency with
34    /// no specific id matches any concrete mutation of the same type, and a
35    /// caller passing `None` matches every dependency of that type.
36    #[must_use]
37    pub fn matches(&self, entity_type: &str, entity_id: Option<&ThingsId>) -> bool {
38        if self.entity_type != entity_type {
39            return false;
40        }
41        match (&self.entity_id, entity_id) {
42            (Some(dep_id), Some(req_id)) => dep_id == req_id,
43            _ => true,
44        }
45    }
46
47    /// Test whether this dependency lists `operation` as one of its invalidators.
48    #[must_use]
49    pub fn matches_operation(&self, operation: &str) -> bool {
50        self.invalidating_operations
51            .iter()
52            .any(|op| op == operation)
53    }
54}
55
56/// Enhanced cache configuration with intelligent invalidation
57#[derive(Debug, Clone)]
58pub struct CacheConfig {
59    /// Maximum number of entries in the cache
60    pub max_capacity: u64,
61    /// Time to live for cache entries
62    pub ttl: Duration,
63    /// Time to idle for cache entries
64    pub tti: Duration,
65    /// Invalidation strategy to use
66    pub invalidation_strategy: InvalidationStrategy,
67    /// Enable cache warming for frequently accessed data
68    pub enable_cache_warming: bool,
69    /// Cache warming interval
70    pub warming_interval: Duration,
71    /// Maximum cache warming entries
72    pub max_warming_entries: usize,
73}
74
75impl Default for CacheConfig {
76    fn default() -> Self {
77        Self {
78            max_capacity: 1000,
79            ttl: Duration::from_secs(300), // 5 minutes
80            tti: Duration::from_secs(60),  // 1 minute
81            invalidation_strategy: InvalidationStrategy::Hybrid,
82            enable_cache_warming: true,
83            warming_interval: Duration::from_secs(60), // 1 minute
84            max_warming_entries: 50,
85        }
86    }
87}