1use std::fs;
5use std::path::{Path, PathBuf};
6use std::time::{Duration, SystemTime};
7
8use super::error::{Result, SpsError};
9use crate::Config;
10
11const CACHE_TTL: Duration = Duration::from_secs(24 * 60 * 60); pub struct Cache {
16 cache_dir: PathBuf,
17 _config: Config, }
19
20impl Cache {
21 pub fn new(config: &Config) -> Result<Self> {
23 let cache_dir = config.cache_dir();
24 if !cache_dir.exists() {
25 fs::create_dir_all(&cache_dir)?;
26 }
27
28 Ok(Self {
29 cache_dir,
30 _config: config.clone(),
31 })
32 }
33
34 pub fn get_dir(&self) -> &Path {
36 &self.cache_dir
37 }
38
39 pub fn store_raw(&self, filename: &str, data: &str) -> Result<()> {
41 let path = self.cache_dir.join(filename);
42 tracing::debug!("Saving raw data to cache file: {:?}", path);
43 fs::write(&path, data)?;
44 Ok(())
45 }
46
47 pub fn load_raw(&self, filename: &str) -> Result<String> {
49 let path = self.cache_dir.join(filename);
50 tracing::debug!("Loading raw data from cache file: {:?}", path);
51
52 if !path.exists() {
53 return Err(SpsError::Cache(format!(
54 "Cache file {filename} does not exist"
55 )));
56 }
57
58 fs::read_to_string(&path).map_err(|e| SpsError::Cache(format!("IO error: {e}")))
59 }
60
61 pub fn is_cache_valid(&self, filename: &str) -> Result<bool> {
63 let path = self.cache_dir.join(filename);
64 if !path.exists() {
65 return Ok(false);
66 }
67
68 let metadata = fs::metadata(&path)?;
69 let modified_time = metadata.modified()?;
70 let age = SystemTime::now()
71 .duration_since(modified_time)
72 .map_err(|e| SpsError::Cache(format!("System time error: {e}")))?;
73
74 Ok(age <= CACHE_TTL)
75 }
76
77 pub fn clear_file(&self, filename: &str) -> Result<()> {
79 let path = self.cache_dir.join(filename);
80 if path.exists() {
81 fs::remove_file(&path)?;
82 }
83 Ok(())
84 }
85
86 pub fn clear_all(&self) -> Result<()> {
88 if self.cache_dir.exists() {
89 fs::remove_dir_all(&self.cache_dir)?;
90 fs::create_dir_all(&self.cache_dir)?;
91 }
92 Ok(())
93 }
94
95 pub fn config(&self) -> &Config {
97 &self._config
98 }
99}