linkrs_query/cache/cte_cache/
decision.rs1use std::sync::Arc;
2
3use crate::cache::config::CachePriority;
4
5use super::manager::CteCacheManager;
6
7#[derive(Debug, Clone)]
11pub struct CteCacheDecision {
12 pub should_cache: bool,
14 pub reason: String,
16 pub reuse_probability: f64,
18 pub estimated_benefit: f64,
20 pub suggested_priority: CachePriority,
22}
23
24#[derive(Debug)]
26pub struct CteCacheDecisionMaker {
27 cache_manager: Arc<CteCacheManager>,
29 min_reuse_probability: f64,
31 min_benefit: f64,
33}
34
35impl CteCacheDecisionMaker {
36 pub fn new(cache_manager: Arc<CteCacheManager>) -> Self {
38 Self {
39 cache_manager,
40 min_reuse_probability: 0.3,
41 min_benefit: 1.0,
42 }
43 }
44
45 pub fn with_params(mut self, min_reuse_probability: f64, min_benefit: f64) -> Self {
47 self.min_reuse_probability = min_reuse_probability;
48 self.min_benefit = min_benefit;
49 self
50 }
51
52 pub fn decide(
54 &self,
55 cte_definition: &str,
56 estimated_rows: u64,
57 compute_cost: f64,
58 ) -> CteCacheDecision {
59 if !self.cache_manager.is_enabled() {
60 return CteCacheDecision {
61 should_cache: false,
62 reason: "Cache disabled".to_string(),
63 reuse_probability: 0.0,
64 estimated_benefit: 0.0,
65 suggested_priority: CachePriority::Low,
66 };
67 }
68
69 let config = self.cache_manager.config();
70
71 if estimated_rows < config.min_row_count {
72 return CteCacheDecision {
73 should_cache: false,
74 reason: format!(
75 "Row count {} below minimum {}",
76 estimated_rows, config.min_row_count
77 ),
78 reuse_probability: 0.0,
79 estimated_benefit: 0.0,
80 suggested_priority: CachePriority::Low,
81 };
82 }
83
84 if estimated_rows > config.max_row_count {
85 return CteCacheDecision {
86 should_cache: false,
87 reason: format!(
88 "Row count {} above maximum {}",
89 estimated_rows, config.max_row_count
90 ),
91 reuse_probability: 0.0,
92 estimated_benefit: 0.0,
93 suggested_priority: CachePriority::Low,
94 };
95 }
96
97 let reuse_prob = self.cache_manager.predict_reuse_probability(cte_definition);
98
99 if reuse_prob < self.min_reuse_probability {
100 return CteCacheDecision {
101 should_cache: false,
102 reason: format!(
103 "Reuse probability {:.2} below threshold {:.2}",
104 reuse_prob, self.min_reuse_probability
105 ),
106 reuse_probability: reuse_prob,
107 estimated_benefit: 0.0,
108 suggested_priority: CachePriority::Low,
109 };
110 }
111
112 let estimated_benefit = compute_cost * reuse_prob;
113
114 let priority = if compute_cost > 1000.0 {
115 CachePriority::High
116 } else if compute_cost > 100.0 {
117 CachePriority::Normal
118 } else {
119 CachePriority::Low
120 };
121
122 CteCacheDecision {
123 should_cache: estimated_benefit >= self.min_benefit,
124 reason: if estimated_benefit >= self.min_benefit {
125 format!("Estimated benefit {:.2} meets threshold", estimated_benefit)
126 } else {
127 format!(
128 "Estimated benefit {:.2} below threshold {:.2}",
129 estimated_benefit, self.min_benefit
130 )
131 },
132 reuse_probability: reuse_prob,
133 estimated_benefit,
134 suggested_priority: priority,
135 }
136 }
137}