mirror of
https://github.com/Horizontal42/summarum.git
synced 2026-11-11 02:12:00 +03:00
Merge da0c8edb8c into 37cfd2144b
This commit is contained in:
commit
c6937f8de4
1 changed files with 64 additions and 29 deletions
|
|
@ -628,42 +628,77 @@ async fn fetch_historical_rates_batch(
|
||||||
.unwrap_or_default()
|
.unwrap_or_default()
|
||||||
});
|
});
|
||||||
|
|
||||||
let mut futures = Vec::new();
|
let mut parsed_dates: Vec<chrono::NaiveDate> = missing_dates
|
||||||
|
.iter()
|
||||||
|
.filter_map(|d| chrono::NaiveDate::parse_from_str(d, "%Y-%m-%d").ok())
|
||||||
|
.collect();
|
||||||
|
|
||||||
for date in missing_dates {
|
if parsed_dates.is_empty() {
|
||||||
let url = format!("https://api.frankfurter.dev/v1/{}?from=USD", date);
|
return Ok(results);
|
||||||
let client_clone = client.clone();
|
}
|
||||||
let app_clone = app.clone();
|
|
||||||
|
|
||||||
futures.push(async move {
|
parsed_dates.sort();
|
||||||
let mut rate_map = None;
|
|
||||||
if let Ok(resp) = client_clone.get(&url).send().await {
|
let min_date = parsed_dates.first().unwrap();
|
||||||
if let Ok(bytes) = read_body_capped(resp, RATES_RESPONSE_LIMIT).await {
|
let max_date = parsed_dates.last().unwrap();
|
||||||
|
|
||||||
|
// Request from min_date - 7 days to cover weekends/holidays before the earliest requested date
|
||||||
|
let start_date = *min_date - chrono::Duration::days(7);
|
||||||
|
|
||||||
|
let url = format!(
|
||||||
|
"https://api.frankfurter.dev/v1/{}..{}?from=USD",
|
||||||
|
start_date.format("%Y-%m-%d"),
|
||||||
|
max_date.format("%Y-%m-%d")
|
||||||
|
);
|
||||||
|
|
||||||
|
if let Ok(resp) = client.get(&url).send().await {
|
||||||
|
if let Ok(bytes) = read_body_capped(resp, RATES_RESPONSE_LIMIT * 50).await {
|
||||||
if let Ok(body) = serde_json::from_slice::<serde_json::Value>(&bytes) {
|
if let Ok(body) = serde_json::from_slice::<serde_json::Value>(&bytes) {
|
||||||
if let Some(rates_obj) = body["rates"].as_object() {
|
if let Some(rates_obj) = body["rates"].as_object() {
|
||||||
let daily_rates = parse_rate_map(rates_obj);
|
let mut available_dates: Vec<chrono::NaiveDate> = rates_obj
|
||||||
|
.keys()
|
||||||
|
.filter_map(|d| chrono::NaiveDate::parse_from_str(d, "%Y-%m-%d").ok())
|
||||||
|
.collect();
|
||||||
|
available_dates.sort();
|
||||||
|
|
||||||
|
for req_date_str in missing_dates {
|
||||||
|
if let Ok(req_date) =
|
||||||
|
chrono::NaiveDate::parse_from_str(&req_date_str, "%Y-%m-%d")
|
||||||
|
{
|
||||||
|
// Find the exact date or the closest preceding date
|
||||||
|
let matched_date_str = match available_dates.binary_search(&req_date) {
|
||||||
|
Ok(idx) => {
|
||||||
|
Some(available_dates[idx].format("%Y-%m-%d").to_string())
|
||||||
|
}
|
||||||
|
Err(idx) => {
|
||||||
|
if idx > 0 {
|
||||||
|
Some(
|
||||||
|
available_dates[idx - 1].format("%Y-%m-%d").to_string(),
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Some(matched_date) = matched_date_str {
|
||||||
|
if let Some(matched_rates_obj) =
|
||||||
|
rates_obj.get(&matched_date).and_then(|r| r.as_object())
|
||||||
|
{
|
||||||
|
let daily_rates = parse_rate_map(matched_rates_obj);
|
||||||
let cache_path =
|
let cache_path =
|
||||||
data_dir(&app_clone).join(format!("rates-{}.json", date));
|
data_dir(&app).join(format!("rates-{}.json", req_date_str));
|
||||||
if let Ok(serialized) = serde_json::to_string(&daily_rates) {
|
if let Ok(serialized) = serde_json::to_string(&daily_rates) {
|
||||||
write_atomic_async(cache_path, serialized).await;
|
write_atomic_async(cache_path, serialized).await;
|
||||||
}
|
}
|
||||||
rate_map = Some((date, daily_rates));
|
results.insert(req_date_str, daily_rates);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
rate_map
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
use futures::stream::StreamExt;
|
|
||||||
let fetched_results = futures::stream::iter(futures)
|
|
||||||
.buffer_unordered(5)
|
|
||||||
.collect::<Vec<_>>()
|
|
||||||
.await;
|
|
||||||
|
|
||||||
for (date, rates) in fetched_results.into_iter().flatten() {
|
|
||||||
results.insert(date, rates);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(results)
|
Ok(results)
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue