mirror of
				https://github.com/lov3b/ecb-rates.git
				synced 2025-11-03 23:00:21 +01:00 
			
		
		
		
	Fix cache bug
Fix bug where a potentially incorrect resolution would be assumed.
This commit is contained in:
		
							
								
								
									
										45
									
								
								src/cache.rs → src/cache/cache.rs
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										45
									
								
								src/cache.rs → src/cache/cache.rs
									
									
									
									
										vendored
									
									
								
							@@ -3,22 +3,20 @@ use std::io::{BufReader, BufWriter};
 | 
			
		||||
use std::path::Path;
 | 
			
		||||
 | 
			
		||||
use anyhow::Context;
 | 
			
		||||
use chrono::serde::ts_seconds;
 | 
			
		||||
use chrono::{DateTime, Local, Utc};
 | 
			
		||||
use serde::{Deserialize, Serialize};
 | 
			
		||||
 | 
			
		||||
use crate::models::ExchangeRateResult;
 | 
			
		||||
use crate::cli::Resolution;
 | 
			
		||||
use crate::os::Os;
 | 
			
		||||
 | 
			
		||||
use super::CacheLine;
 | 
			
		||||
 | 
			
		||||
const FILE_NAME: &'static str = "cache.json";
 | 
			
		||||
 | 
			
		||||
#[derive(Serialize, Deserialize, Debug)]
 | 
			
		||||
pub struct Cache {
 | 
			
		||||
    #[serde(with = "ts_seconds")]
 | 
			
		||||
    date: DateTime<Utc>,
 | 
			
		||||
 | 
			
		||||
    #[serde(rename = "camelCase")]
 | 
			
		||||
    pub exchange_rate_results: Vec<ExchangeRateResult>,
 | 
			
		||||
    day: Option<CacheLine>,
 | 
			
		||||
    hist_90: Option<CacheLine>,
 | 
			
		||||
    hist_day: Option<CacheLine>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl Cache {
 | 
			
		||||
@@ -37,7 +35,11 @@ impl Cache {
 | 
			
		||||
        }
 | 
			
		||||
        config_path.push(FILE_NAME);
 | 
			
		||||
        if !config_path.try_exists().unwrap_or_default() {
 | 
			
		||||
            return None;
 | 
			
		||||
            return Some(Self {
 | 
			
		||||
                day: None,
 | 
			
		||||
                hist_90: None,
 | 
			
		||||
                hist_day: None,
 | 
			
		||||
            });
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        match Self::read_config(&config_path) {
 | 
			
		||||
@@ -49,11 +51,20 @@ impl Cache {
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub fn new(exchange_rate_results: Vec<ExchangeRateResult>) -> Self {
 | 
			
		||||
        let date = Local::now().to_utc();
 | 
			
		||||
        Self {
 | 
			
		||||
            exchange_rate_results,
 | 
			
		||||
            date,
 | 
			
		||||
    pub fn get_cache_line(&self, resolution: Resolution) -> Option<&CacheLine> {
 | 
			
		||||
        match resolution {
 | 
			
		||||
            Resolution::TODAY => self.day.as_ref(),
 | 
			
		||||
            Resolution::HistDays90 => self.hist_90.as_ref(),
 | 
			
		||||
            Resolution::HistDay => self.hist_day.as_ref(),
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub fn set_cache_line(&mut self, resolution: Resolution, cache_line: CacheLine) {
 | 
			
		||||
        let cache_line_opt = Some(cache_line);
 | 
			
		||||
        match resolution {
 | 
			
		||||
            Resolution::TODAY => self.day = cache_line_opt,
 | 
			
		||||
            Resolution::HistDays90 => self.hist_90 = cache_line_opt,
 | 
			
		||||
            Resolution::HistDay => self.hist_day = cache_line_opt,
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -77,12 +88,6 @@ impl Cache {
 | 
			
		||||
        Ok(())
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub fn validate(&self) -> bool {
 | 
			
		||||
        let today = Local::now().naive_local().date();
 | 
			
		||||
        let saved = self.date.naive_local().date();
 | 
			
		||||
        saved == today
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn read_config(path: &Path) -> anyhow::Result<Self> {
 | 
			
		||||
        let file = fs::File::open(path)?;
 | 
			
		||||
        let reader = BufReader::new(file);
 | 
			
		||||
							
								
								
									
										30
									
								
								src/cache/cache_line.rs
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								src/cache/cache_line.rs
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,30 @@
 | 
			
		||||
use chrono::serde::ts_seconds;
 | 
			
		||||
use chrono::{DateTime, Local, Utc};
 | 
			
		||||
use serde::{Deserialize, Serialize};
 | 
			
		||||
 | 
			
		||||
use crate::models::ExchangeRateResult;
 | 
			
		||||
 | 
			
		||||
#[derive(Serialize, Deserialize, Debug)]
 | 
			
		||||
pub struct CacheLine {
 | 
			
		||||
    #[serde(with = "ts_seconds")]
 | 
			
		||||
    date: DateTime<Utc>,
 | 
			
		||||
 | 
			
		||||
    #[serde(rename = "camelCase")]
 | 
			
		||||
    pub exchange_rate_results: Vec<ExchangeRateResult>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl CacheLine {
 | 
			
		||||
    pub fn validate(&self) -> bool {
 | 
			
		||||
        let today = Local::now().naive_local().date();
 | 
			
		||||
        let saved = self.date.naive_local().date();
 | 
			
		||||
        saved == today
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub fn new(exchange_rate_results: Vec<ExchangeRateResult>) -> Self {
 | 
			
		||||
        let date = Local::now().to_utc();
 | 
			
		||||
        Self {
 | 
			
		||||
            exchange_rate_results,
 | 
			
		||||
            date,
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										5
									
								
								src/cache/mod.rs
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								src/cache/mod.rs
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,5 @@
 | 
			
		||||
mod cache;
 | 
			
		||||
mod cache_line;
 | 
			
		||||
 | 
			
		||||
pub use cache::Cache;
 | 
			
		||||
pub use cache_line::CacheLine;
 | 
			
		||||
							
								
								
									
										31
									
								
								src/main.rs
									
									
									
									
									
								
							
							
						
						
									
										31
									
								
								src/main.rs
									
									
									
									
									
								
							@@ -1,12 +1,12 @@
 | 
			
		||||
use clap::Parser as _;
 | 
			
		||||
use ecb_rates::cache::Cache;
 | 
			
		||||
use ecb_rates::cache::{Cache, CacheLine};
 | 
			
		||||
use reqwest::{Client, IntoUrl};
 | 
			
		||||
use std::{borrow::BorrowMut, collections::HashMap, process::ExitCode};
 | 
			
		||||
 | 
			
		||||
use ecb_rates::cli::{Cli, FormatOption};
 | 
			
		||||
use ecb_rates::models::ExchangeRateResult;
 | 
			
		||||
use ecb_rates::parsing::parse;
 | 
			
		||||
use ecb_rates::table::{TableRef, TableTrait};
 | 
			
		||||
use ecb_rates::table::{TableRef, TableTrait as _};
 | 
			
		||||
 | 
			
		||||
async fn get_and_parse(url: impl IntoUrl) -> anyhow::Result<Vec<ExchangeRateResult>> {
 | 
			
		||||
    let client = Client::new();
 | 
			
		||||
@@ -40,10 +40,23 @@ async fn main() -> ExitCode {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    let use_cache = !cli.no_cache;
 | 
			
		||||
    let cache = if use_cache { Cache::load() } else { None };
 | 
			
		||||
    let cache_ok = cache.as_ref().map_or_else(|| false, |c| c.validate());
 | 
			
		||||
    let mut cache = if use_cache { Cache::load() } 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.validate())
 | 
			
		||||
        },
 | 
			
		||||
    );
 | 
			
		||||
    let mut parsed = if cache_ok {
 | 
			
		||||
        cache.as_ref().unwrap().exchange_rate_results.clone()
 | 
			
		||||
        // These are safe unwraps
 | 
			
		||||
        cache
 | 
			
		||||
            .as_ref()
 | 
			
		||||
            .unwrap()
 | 
			
		||||
            .get_cache_line(cli.resolution)
 | 
			
		||||
            .unwrap()
 | 
			
		||||
            .exchange_rate_results
 | 
			
		||||
            .clone()
 | 
			
		||||
    } else {
 | 
			
		||||
        let parsed = match get_and_parse(cli.resolution.to_ecb_url()).await {
 | 
			
		||||
            Ok(k) => k,
 | 
			
		||||
@@ -53,8 +66,12 @@ async fn main() -> ExitCode {
 | 
			
		||||
            }
 | 
			
		||||
        };
 | 
			
		||||
        if !cache_ok {
 | 
			
		||||
            if let Err(e) = Cache::new(parsed.clone()).save() {
 | 
			
		||||
                eprintln!("Failed to save to cache with: {:?}", e);
 | 
			
		||||
            if let Some(cache_safe) = cache.as_mut() {
 | 
			
		||||
                let cache_line = CacheLine::new(parsed.clone());
 | 
			
		||||
                cache_safe.set_cache_line(cli.resolution, cache_line);
 | 
			
		||||
                if let Err(e) = cache_safe.save() {
 | 
			
		||||
                    eprintln!("Failed to save to cache with: {:?}", e);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        parsed
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user