mirror of
				https://github.com/lov3b/ecb-rates.git
				synced 2025-11-04 07:10:18 +01:00 
			
		
		
		
	Keep caches in different files
This commit is contained in:
		
							
								
								
									
										61
									
								
								src/cache/cache.rs
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										61
									
								
								src/cache/cache.rs
									
									
									
									
										vendored
									
									
								
							@@ -1,26 +1,19 @@
 | 
				
			|||||||
use std::fs;
 | 
					use std::fs;
 | 
				
			||||||
use std::io::{BufReader, BufWriter};
 | 
					use std::io::{BufReader, BufWriter};
 | 
				
			||||||
use std::path::Path;
 | 
					use std::path::{Path, PathBuf};
 | 
				
			||||||
 | 
					 | 
				
			||||||
use anyhow::Context;
 | 
					 | 
				
			||||||
use serde::{Deserialize, Serialize};
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use super::CacheLine;
 | 
				
			||||||
use crate::cli::View;
 | 
					use crate::cli::View;
 | 
				
			||||||
use crate::os::Os;
 | 
					use crate::os::Os;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use super::CacheLine;
 | 
					#[derive(Debug)]
 | 
				
			||||||
 | 
					 | 
				
			||||||
const FILE_NAME: &'static str = "cache.json";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#[derive(Serialize, Deserialize, Debug)]
 | 
					 | 
				
			||||||
pub struct Cache {
 | 
					pub struct Cache {
 | 
				
			||||||
    day: Option<CacheLine>,
 | 
					    cache_line: Option<CacheLine>,
 | 
				
			||||||
    hist_90: Option<CacheLine>,
 | 
					    config_path: PathBuf,
 | 
				
			||||||
    hist_day: Option<CacheLine>,
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl Cache {
 | 
					impl Cache {
 | 
				
			||||||
    pub fn load() -> Option<Self> {
 | 
					    pub fn load(view: View) -> Option<Self> {
 | 
				
			||||||
        let config_opt = Os::get_current()?.get_config_path();
 | 
					        let config_opt = Os::get_current()?.get_config_path();
 | 
				
			||||||
        let mut config_path = match config_opt {
 | 
					        let mut config_path = match config_opt {
 | 
				
			||||||
            Ok(k) => k,
 | 
					            Ok(k) => k,
 | 
				
			||||||
@@ -33,17 +26,19 @@ impl Cache {
 | 
				
			|||||||
            eprintln!("Failed to create config dir: {:?}", e);
 | 
					            eprintln!("Failed to create config dir: {:?}", e);
 | 
				
			||||||
            return None;
 | 
					            return None;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        config_path.push(FILE_NAME);
 | 
					        config_path.push(format!("{}.json", view.get_name()));
 | 
				
			||||||
        if !config_path.try_exists().unwrap_or_default() {
 | 
					        if !config_path.try_exists().unwrap_or_default() {
 | 
				
			||||||
            return Some(Self {
 | 
					            return Some(Self {
 | 
				
			||||||
                day: None,
 | 
					                cache_line: None,
 | 
				
			||||||
                hist_90: None,
 | 
					                config_path,
 | 
				
			||||||
                hist_day: None,
 | 
					 | 
				
			||||||
            });
 | 
					            });
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        match Self::read_config(&config_path) {
 | 
					        match Self::read_config(&config_path) {
 | 
				
			||||||
            Ok(k) => Some(k),
 | 
					            Ok(cache_line) => Some(Self {
 | 
				
			||||||
 | 
					                cache_line: Some(cache_line),
 | 
				
			||||||
 | 
					                config_path,
 | 
				
			||||||
 | 
					            }),
 | 
				
			||||||
            Err(e) => {
 | 
					            Err(e) => {
 | 
				
			||||||
                eprintln!("Config path is invalid, or cannot be created: {:?}", e);
 | 
					                eprintln!("Config path is invalid, or cannot be created: {:?}", e);
 | 
				
			||||||
                None
 | 
					                None
 | 
				
			||||||
@@ -51,44 +46,28 @@ impl Cache {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pub fn get_cache_line(&self, resolution: View) -> Option<&CacheLine> {
 | 
					    pub fn get_cache_line(&self) -> Option<&CacheLine> {
 | 
				
			||||||
        match resolution {
 | 
					        self.cache_line.as_ref()
 | 
				
			||||||
            View::TODAY => self.day.as_ref(),
 | 
					 | 
				
			||||||
            View::HistDays90 => self.hist_90.as_ref(),
 | 
					 | 
				
			||||||
            View::HistDaysAll => self.hist_day.as_ref(),
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pub fn set_cache_line(&mut self, resolution: View, cache_line: CacheLine) {
 | 
					    pub fn set_cache_line(&mut self, cache_line: CacheLine) {
 | 
				
			||||||
        let cache_line_opt = Some(cache_line);
 | 
					        self.cache_line = Some(cache_line);
 | 
				
			||||||
        match resolution {
 | 
					 | 
				
			||||||
            View::TODAY => self.day = cache_line_opt,
 | 
					 | 
				
			||||||
            View::HistDays90 => self.hist_90 = cache_line_opt,
 | 
					 | 
				
			||||||
            View::HistDaysAll => self.hist_day = cache_line_opt,
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pub fn save(&self) -> anyhow::Result<()> {
 | 
					    pub fn save(&self) -> anyhow::Result<()> {
 | 
				
			||||||
        let mut config_path = Os::get_current()
 | 
					 | 
				
			||||||
            .context("Failed to get config home")?
 | 
					 | 
				
			||||||
            .get_config_path()?;
 | 
					 | 
				
			||||||
        fs::create_dir_all(&config_path)?;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        config_path.push(FILE_NAME);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        let file = fs::File::options()
 | 
					        let file = fs::File::options()
 | 
				
			||||||
            .write(true)
 | 
					            .write(true)
 | 
				
			||||||
            .create(true)
 | 
					            .create(true)
 | 
				
			||||||
            .truncate(true)
 | 
					            .truncate(true)
 | 
				
			||||||
            .open(&config_path)?;
 | 
					            .open(&self.config_path)?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let writer = BufWriter::new(file);
 | 
					        let writer = BufWriter::new(file);
 | 
				
			||||||
        serde_json::to_writer(writer, self)?;
 | 
					        serde_json::to_writer(writer, &self.cache_line)?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        Ok(())
 | 
					        Ok(())
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn read_config(path: &Path) -> anyhow::Result<Self> {
 | 
					    fn read_config(path: &Path) -> anyhow::Result<CacheLine> {
 | 
				
			||||||
        let file = fs::File::open(path)?;
 | 
					        let file = fs::File::open(path)?;
 | 
				
			||||||
        let reader = BufReader::new(file);
 | 
					        let reader = BufReader::new(file);
 | 
				
			||||||
        Ok(serde_json::from_reader(reader)?)
 | 
					        Ok(serde_json::from_reader(reader)?)
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										12
									
								
								src/cli.rs
									
									
									
									
									
								
							
							
						
						
									
										12
									
								
								src/cli.rs
									
									
									
									
									
								
							@@ -46,8 +46,8 @@ pub struct Cli {
 | 
				
			|||||||
    pub max_decimals: u8,
 | 
					    pub max_decimals: u8,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// Amount of data
 | 
					    /// Amount of data
 | 
				
			||||||
    #[arg(value_enum, default_value_t = View::TODAY, long="resolution", short='r')]
 | 
					    #[arg(value_enum, default_value_t = View::TODAY, long="view", short='v')]
 | 
				
			||||||
    pub resolution: View,
 | 
					    pub view: View,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[derive(Debug, Clone, Copy, ValueEnum)]
 | 
					#[derive(Debug, Clone, Copy, ValueEnum)]
 | 
				
			||||||
@@ -74,6 +74,14 @@ impl View {
 | 
				
			|||||||
            View::HistDaysAll => ecb_url::hist::DAYS_ALL,
 | 
					            View::HistDaysAll => ecb_url::hist::DAYS_ALL,
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    pub fn get_name(&self) -> &'static str {
 | 
				
			||||||
 | 
					        match self {
 | 
				
			||||||
 | 
					            View::TODAY => "today",
 | 
				
			||||||
 | 
					            View::HistDays90 => "last-90-days",
 | 
				
			||||||
 | 
					            View::HistDaysAll => "all-days",
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl SortBy {
 | 
					impl SortBy {
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										19
									
								
								src/main.rs
									
									
									
									
									
								
							
							
						
						
									
										19
									
								
								src/main.rs
									
									
									
									
									
								
							@@ -25,25 +25,26 @@ async fn main() -> ExitCode {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    let mut header_description = HeaderDescription::new();
 | 
					    let mut header_description = HeaderDescription::new();
 | 
				
			||||||
    let use_cache = !cli.no_cache;
 | 
					    let use_cache = !cli.no_cache;
 | 
				
			||||||
    let mut cache = if use_cache { Cache::load() } else { None };
 | 
					    let mut cache = if use_cache {
 | 
				
			||||||
 | 
					        Cache::load(cli.view)
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        None
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
    let cache_ok = cache.as_ref().map_or_else(
 | 
					    let cache_ok = cache.as_ref().map_or_else(
 | 
				
			||||||
        || false,
 | 
					        || false,
 | 
				
			||||||
        |c| {
 | 
					        |c| c.get_cache_line().map_or_else(|| false, |cl| cl.is_valid()),
 | 
				
			||||||
            c.get_cache_line(cli.resolution)
 | 
					 | 
				
			||||||
                .map_or_else(|| false, |cl| cl.is_valid())
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
    let mut parsed = if cache_ok {
 | 
					    let mut parsed = if cache_ok {
 | 
				
			||||||
        // These are safe unwraps
 | 
					        // These are safe unwraps
 | 
				
			||||||
        cache
 | 
					        cache
 | 
				
			||||||
            .as_ref()
 | 
					            .as_ref()
 | 
				
			||||||
            .unwrap()
 | 
					            .unwrap()
 | 
				
			||||||
            .get_cache_line(cli.resolution)
 | 
					            .get_cache_line()
 | 
				
			||||||
            .unwrap()
 | 
					            .unwrap()
 | 
				
			||||||
            .exchange_rate_results
 | 
					            .exchange_rate_results
 | 
				
			||||||
            .clone()
 | 
					            .clone()
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
        let parsed = match get_and_parse(cli.resolution.to_ecb_url()).await {
 | 
					        let parsed = match get_and_parse(cli.view.to_ecb_url()).await {
 | 
				
			||||||
            Ok(k) => k,
 | 
					            Ok(k) => k,
 | 
				
			||||||
            Err(e) => {
 | 
					            Err(e) => {
 | 
				
			||||||
                eprintln!("Failed to get/parse data from ECB: {}", e);
 | 
					                eprintln!("Failed to get/parse data from ECB: {}", e);
 | 
				
			||||||
@@ -56,7 +57,7 @@ async fn main() -> ExitCode {
 | 
				
			|||||||
                || true,
 | 
					                || true,
 | 
				
			||||||
                |cache_local| {
 | 
					                |cache_local| {
 | 
				
			||||||
                    cache_local
 | 
					                    cache_local
 | 
				
			||||||
                        .get_cache_line(cli.resolution)
 | 
					                        .get_cache_line()
 | 
				
			||||||
                        .map_or_else(|| true, |cache_line| cache_line == &parsed)
 | 
					                        .map_or_else(|| true, |cache_line| cache_line == &parsed)
 | 
				
			||||||
                },
 | 
					                },
 | 
				
			||||||
            );
 | 
					            );
 | 
				
			||||||
@@ -64,7 +65,7 @@ async fn main() -> ExitCode {
 | 
				
			|||||||
            if not_equal_cache {
 | 
					            if not_equal_cache {
 | 
				
			||||||
                if let Some(cache_safe) = cache.as_mut() {
 | 
					                if let Some(cache_safe) = cache.as_mut() {
 | 
				
			||||||
                    let cache_line = CacheLine::new(parsed.clone());
 | 
					                    let cache_line = CacheLine::new(parsed.clone());
 | 
				
			||||||
                    cache_safe.set_cache_line(cli.resolution, cache_line);
 | 
					                    cache_safe.set_cache_line(cache_line);
 | 
				
			||||||
                    if let Err(e) = cache_safe.save() {
 | 
					                    if let Err(e) = cache_safe.save() {
 | 
				
			||||||
                        eprintln!("Failed to save to cache with: {:?}", e);
 | 
					                        eprintln!("Failed to save to cache with: {:?}", e);
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user