use chrono::{DateTime, Duration, Utc};
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum TimeHorizon {
Immediate,
ShortTerm,
MediumTerm,
LongTerm,
Permanent,
}
impl TimeHorizon {
pub fn duration(&self) -> Option<Duration> {
match self {
Self::Immediate => Some(Duration::minutes(5)),
Self::ShortTerm => Some(Duration::hours(1)),
Self::MediumTerm => Some(Duration::hours(24)),
Self::LongTerm => Some(Duration::weeks(1)),
Self::Permanent => None,
}
}
pub fn compression_level(&self) -> f64 {
match self {
Self::Immediate => 0.0, Self::ShortTerm => 0.2, Self::MediumTerm => 0.5, Self::LongTerm => 0.7, Self::Permanent => 0.9, }
}
pub fn contains(&self, timestamp: DateTime<Utc>) -> bool {
match self.duration() {
Some(d) => Utc::now() - timestamp <= d,
None => true,
}
}
pub fn for_depth(depth: u8) -> Self {
match depth {
0 => Self::LongTerm, 1 => Self::MediumTerm, 2 => Self::ShortTerm, _ => Self::Immediate, }
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct HorizonConfig {
pub horizon: TimeHorizon,
pub max_entries: usize,
pub auto_compress: bool,
pub auto_evict: bool,
}
impl Default for HorizonConfig {
fn default() -> Self {
Self {
horizon: TimeHorizon::MediumTerm,
max_entries: 100,
auto_compress: true,
auto_evict: true,
}
}
}
impl HorizonConfig {
pub fn for_depth(depth: u8) -> Self {
let horizon = TimeHorizon::for_depth(depth);
let max_entries = match horizon {
TimeHorizon::Immediate => 10,
TimeHorizon::ShortTerm => 25,
TimeHorizon::MediumTerm => 50,
TimeHorizon::LongTerm => 100,
TimeHorizon::Permanent => 500,
};
Self {
horizon,
max_entries,
auto_compress: true,
auto_evict: true,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_horizon_duration() {
assert!(TimeHorizon::Immediate.duration().is_some());
assert!(TimeHorizon::Permanent.duration().is_none());
}
#[test]
fn test_horizon_for_depth() {
assert_eq!(TimeHorizon::for_depth(0), TimeHorizon::LongTerm);
assert_eq!(TimeHorizon::for_depth(3), TimeHorizon::Immediate);
}
#[test]
fn test_contains() {
let now = Utc::now();
assert!(TimeHorizon::Immediate.contains(now));
}
}