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