Skip to content

Commit 34484a9

Browse files
committed
Add exchange-rate-max-age config option
1 parent 719aa40 commit 34484a9

File tree

3 files changed

+28
-10
lines changed

3 files changed

+28
-10
lines changed

cli/src/config.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ pub struct Config {
1212
pub max_history_size: usize,
1313
pub enable_internet_access: bool,
1414
pub exchange_rate_source: ExchangeRateSource,
15+
pub exchange_rate_max_age: u64,
1516
pub custom_units: Vec<CustomUnitDefinition>,
1617
pub decimal_separator: DecimalSeparatorStyle,
1718
unknown_settings: UnknownSettings,
@@ -80,6 +81,7 @@ impl<'de> serde::de::Visitor<'de> for ConfigVisitor {
8081
let mut seen_max_hist_size = false;
8182
let mut seen_enable_internet_access = false;
8283
let mut seen_exchange_rate_source = false;
84+
let mut seen_exchange_rate_max_age = false;
8385
let mut seen_custom_units = false;
8486
let mut seen_decimal_separator_style = false;
8587
while let Some(key) = map.next_key::<String>()? {
@@ -123,6 +125,13 @@ impl<'de> serde::de::Visitor<'de> for ConfigVisitor {
123125
result.exchange_rate_source = map.next_value()?;
124126
seen_exchange_rate_source = true;
125127
}
128+
"exchange-rate-max-age" => {
129+
if seen_exchange_rate_max_age {
130+
return Err(serde::de::Error::duplicate_field("exchange-rate-max-age"));
131+
}
132+
result.exchange_rate_max_age = map.next_value()?;
133+
seen_exchange_rate_max_age = true;
134+
}
126135
"colors" => {
127136
if seen_colors {
128137
return Err(serde::de::Error::duplicate_field("colors"));
@@ -205,6 +214,7 @@ impl<'de> serde::Deserialize<'de> for Config {
205214
"custom-units",
206215
"decimal-separator-style",
207216
"exchange-rate-source",
217+
"exchange-rate-max-age",
208218
];
209219
deserializer.deserialize_struct("Config", FIELDS, ConfigVisitor)
210220
}
@@ -221,6 +231,7 @@ impl Default for Config {
221231
enable_internet_access: true,
222232
unknown_settings: UnknownSettings::Warn,
223233
exchange_rate_source: ExchangeRateSource::EuropeanUnion,
234+
exchange_rate_max_age: 60 * 60 * 24 * 3,
224235
custom_units: vec![],
225236
decimal_separator: DecimalSeparatorStyle::Dot,
226237
unknown_keys: vec![],

cli/src/context.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ impl<'a> Context<'a> {
7474
let exchange_rate_handler = exchange_rates::ExchangeRateHandler {
7575
enable_internet_access: config.enable_internet_access,
7676
source: config.exchange_rate_source,
77+
max_age: config.exchange_rate_max_age,
7778
};
7879
ctx_borrow
7980
.core_ctx

cli/src/exchange_rates.rs

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
1+
use std::{error, fmt, fs, io::Write, time};
2+
13
use crate::Error;
24
use crate::config::{self, ExchangeRateSource};
35
use crate::file_paths;
4-
use std::{error, fmt, fs, io::Write, time};
5-
6-
const MAX_AGE: u64 = 86400 * 3;
76

87
fn get_current_timestamp() -> Result<u64, Error> {
98
Ok(time::SystemTime::now()
@@ -19,7 +18,7 @@ fn get_cache_filename(source: config::ExchangeRateSource) -> Result<&'static str
1918
})
2019
}
2120

22-
fn load_cached_data(source: config::ExchangeRateSource) -> Result<String, Error> {
21+
fn load_cached_data(source: config::ExchangeRateSource, max_age: u64) -> Result<String, Error> {
2322
let mut cache_file = file_paths::get_cache_dir(file_paths::DirMode::DontCreate)?;
2423
cache_file.push(get_cache_filename(source)?);
2524
let cache_contents = fs::read_to_string(cache_file)?;
@@ -30,7 +29,7 @@ fn load_cached_data(source: config::ExchangeRateSource) -> Result<String, Error>
3029
let age = current_timestamp
3130
.checked_sub(timestamp)
3231
.ok_or("invalid cache timestamp")?;
33-
if age > MAX_AGE {
32+
if age > max_age {
3433
return Err("cache expired".into());
3534
}
3635
Ok(cache_xml.to_string())
@@ -55,8 +54,11 @@ fn http_get(_url: &str) -> Result<String, Error> {
5554
Err("internet access has been disabled in this build of fend".into())
5655
}
5756

58-
fn load_exchange_rate_xml(source: config::ExchangeRateSource) -> Result<(String, bool), Error> {
59-
match load_cached_data(source) {
57+
fn load_exchange_rate_xml(
58+
source: config::ExchangeRateSource,
59+
max_age: u64,
60+
) -> Result<(String, bool), Error> {
61+
match load_cached_data(source, max_age) {
6062
Ok(xml) => return Ok((xml, true)),
6163
Err(_e) => {
6264
// failed to load cached data
@@ -152,8 +154,11 @@ fn parse_exchange_rates_un(exchange_rates: &str) -> Result<Vec<(String, f64)>, E
152154
Ok(result)
153155
}
154156

155-
fn get_exchange_rates(source: config::ExchangeRateSource) -> Result<Vec<(String, f64)>, Error> {
156-
let (xml, cached) = load_exchange_rate_xml(source)?;
157+
fn get_exchange_rates(
158+
source: config::ExchangeRateSource,
159+
max_age: u64,
160+
) -> Result<Vec<(String, f64)>, Error> {
161+
let (xml, cached) = load_exchange_rate_xml(source, max_age)?;
157162
let parsed_data = parse_exchange_rates(source, &xml)?;
158163
if !cached {
159164
store_cached_data(source, &xml)?;
@@ -195,6 +200,7 @@ impl error::Error for ExchangeRateSourceDisabledError {}
195200
pub struct ExchangeRateHandler {
196201
pub enable_internet_access: bool,
197202
pub source: ExchangeRateSource,
203+
pub max_age: u64,
198204
}
199205

200206
impl fend_core::ExchangeRateFn for ExchangeRateHandler {
@@ -205,7 +211,7 @@ impl fend_core::ExchangeRateFn for ExchangeRateHandler {
205211
if !self.enable_internet_access {
206212
return Err(InternetAccessDisabledError.into());
207213
}
208-
let exchange_rates = get_exchange_rates(self.source)?;
214+
let exchange_rates = get_exchange_rates(self.source, self.max_age)?;
209215
for (c, rate) in exchange_rates {
210216
if currency == c {
211217
return Ok(rate);

0 commit comments

Comments
 (0)