From a3ec6e2ff9c1b41ddddee33ebbebac5ba12a620d Mon Sep 17 00:00:00 2001 From: Lars Strojny Date: Thu, 12 Jan 2023 23:07:30 +0100 Subject: [PATCH] Refactor providers to have the HTTP client injected (#11) Instead of adapters creating their own HTTP client, create the clients when assembling tasks from the config. --- Cargo.lock | 2 +- src/config.rs | 3 +++ src/http.rs | 3 ++- src/main.rs | 18 +++++++++++++----- src/providers/cache.rs | 6 +++--- src/providers/deutscher_wetterdienst.rs | 9 ++++----- src/providers/meteoblue.rs | 7 ++++--- src/providers/mod.rs | 2 ++ src/providers/nogoodnik.rs | 2 ++ src/providers/open_weather.rs | 8 ++++---- src/providers/tomorrow.rs | 8 ++++---- 11 files changed, 42 insertions(+), 26 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e77957e8..33839549 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1614,7 +1614,7 @@ dependencies = [ [[package]] name = "prometheus-weathermen" -version = "0.2.1" +version = "0.3.0" dependencies = [ "anyhow", "assert-str", diff --git a/src/config.rs b/src/config.rs index 12ae708d..0529f998 100644 --- a/src/config.rs +++ b/src/config.rs @@ -8,6 +8,7 @@ use figment::{ Figment, }; use log::{debug, info, warn, Level}; +use reqwest::blocking::Client; use rocket::config::Ident; use rocket::figment::providers::Serialized; use rocket::serde::Serialize; @@ -103,6 +104,7 @@ pub type ProviderTasks = Vec; pub struct Task { pub provider: Arc, pub request: WeatherRequest, + pub client: Client, pub cache: HttpRequestBodyCache, } @@ -136,6 +138,7 @@ pub fn get_provider_tasks(config: Config) -> anyhow::Result { name: location.name.unwrap_or(name), query: location.coordinates, }, + client: Client::new(), cache: cache.clone(), }); } diff --git a/src/http.rs b/src/http.rs index eed130a2..3f93bf9b 100644 --- a/src/http.rs +++ b/src/http.rs @@ -50,7 +50,8 @@ async fn serve_metrics(unscheduled_tasks: &State) -> (Status, Str task.provider.id(), task.request.query, ); - task.provider.for_coordinates(&task.cache, &task.request) + task.provider + .for_coordinates(&task.client, &task.cache, &task.request) })); } diff --git a/src/main.rs b/src/main.rs index 5077f806..dc4c3270 100644 --- a/src/main.rs +++ b/src/main.rs @@ -13,6 +13,7 @@ use log::error; use rocket::{launch, routes}; use std::path::PathBuf; use std::process::exit; +use tokio::task; mod config; mod http; @@ -49,7 +50,7 @@ struct Args { } #[launch] -fn rocket() -> _ { +async fn rocket() -> _ { let args = Args::parse(); let log_level = args @@ -64,10 +65,17 @@ fn rocket() -> _ { exit(1); }); - let tasks = get_provider_tasks(config.clone()).unwrap_or_else(|e| { - error!("Fatal error: {e}"); - exit(1); - }); + let config_clone = config.clone(); + let tasks = task::spawn_blocking(move || get_provider_tasks(config_clone)) + .await + .unwrap_or_else(|e| { + error!("Fatal error: {e}"); + exit(1); + }) + .unwrap_or_else(|e| { + error!("Fatal error: {e}"); + exit(1); + }); rocket::custom(config.http) .manage(tasks) diff --git a/src/providers/cache.rs b/src/providers/cache.rs index 5f70292e..400aec69 100644 --- a/src/providers/cache.rs +++ b/src/providers/cache.rs @@ -25,7 +25,7 @@ pub fn reqwest_cached_body_json( cache: &HttpRequestBodyCache, client: &Client, method: Method, - url: Url, + url: &Url, charset: Option<&str>, ) -> anyhow::Result { let body = reqwest_cached_body(source, cache, client, method, url, charset)?; @@ -44,7 +44,7 @@ pub fn reqwest_cached_body( cache: &HttpRequestBodyCache, client: &Client, method: Method, - url: Url, + url: &Url, charset: Option<&str>, ) -> anyhow::Result { let key = (method.clone(), url.clone()); @@ -66,7 +66,7 @@ pub fn reqwest_cached_body( debug!("No cache item found for \"{method:#} {url:#}\". Requesting"); let body = client - .request(method, url) + .request(method, url.clone()) .send()? .text_with_charset(charset.unwrap_or("utf-8"))?; cache.insert(key, body.clone()); diff --git a/src/providers/deutscher_wetterdienst.rs b/src/providers/deutscher_wetterdienst.rs index e557914c..6628e3af 100644 --- a/src/providers/deutscher_wetterdienst.rs +++ b/src/providers/deutscher_wetterdienst.rs @@ -212,17 +212,16 @@ impl WeatherProvider for DeutscherWetterdienst { fn for_coordinates( &self, + client: &Client, cache: &HttpRequestBodyCache, request: &WeatherRequest, ) -> anyhow::Result { - let client = Client::new(); - let station_csv = reqwest_cached_body( SOURCE_URI, cache, - &client, + client, Method::GET, - Url::parse(STATION_LIST_URL)?, + &Url::parse(STATION_LIST_URL)?, Some("iso-8859-15"), )?; @@ -230,7 +229,7 @@ impl WeatherProvider for DeutscherWetterdienst { let closest_station = find_closest_weather_station(&request.query, &stations)?; trace!("Found closest weather station {:?}", closest_station); let measurement_csv = - reqwest_cached_measurement_csv(cache, &client, &closest_station.station_id)?; + reqwest_cached_measurement_csv(cache, client, &closest_station.station_id)?; let measurements = parse_measurement_data_csv(&measurement_csv); let latest_measurement = measurements.last().expect("Taking last measurement info"); diff --git a/src/providers/meteoblue.rs b/src/providers/meteoblue.rs index 586698a4..a9cde1aa 100644 --- a/src/providers/meteoblue.rs +++ b/src/providers/meteoblue.rs @@ -3,6 +3,7 @@ use crate::providers::units::{Celsius, Coordinates}; use crate::providers::{HttpRequestBodyCache, Weather, WeatherProvider, WeatherRequest}; use anyhow::Context; use hmac::{Hmac, Mac}; +use reqwest::blocking::Client; use reqwest::{Method, Url}; use serde::{Deserialize, Serialize}; use sha2::Sha256; @@ -45,6 +46,7 @@ impl WeatherProvider for Meteoblue { fn for_coordinates( &self, + client: &Client, cache: &HttpRequestBodyCache, request: &WeatherRequest, ) -> anyhow::Result { @@ -73,13 +75,12 @@ impl WeatherProvider for Meteoblue { let signed_url = Url::parse_with_params(url.as_str(), &[("sig", sig)])?; - let client = reqwest::blocking::Client::new(); let response: MeteoblueResponse = reqwest_cached_body_json::( SOURCE_URI, cache, - &client, + client, Method::GET, - signed_url, + &signed_url, None, )?; diff --git a/src/providers/mod.rs b/src/providers/mod.rs index 44b1f8bd..e0e40e11 100644 --- a/src/providers/mod.rs +++ b/src/providers/mod.rs @@ -12,6 +12,7 @@ use crate::providers::nogoodnik::Nogoodnik; use crate::providers::open_weather::OpenWeather; use crate::providers::tomorrow::Tomorrow; use crate::providers::units::{Celsius, Ratio}; +use reqwest::blocking::Client; use serde::{Deserialize, Serialize}; use std::sync::Arc; use std::time::Duration; @@ -79,6 +80,7 @@ pub trait WeatherProvider: std::fmt::Debug { fn for_coordinates( &self, + client: &Client, cache: &HttpRequestBodyCache, request: &WeatherRequest, ) -> anyhow::Result; diff --git a/src/providers/nogoodnik.rs b/src/providers/nogoodnik.rs index cc93e71e..2878811a 100644 --- a/src/providers/nogoodnik.rs +++ b/src/providers/nogoodnik.rs @@ -2,6 +2,7 @@ use crate::providers::units::Coordinates; use crate::providers::HttpRequestBodyCache; use crate::providers::{Weather, WeatherProvider, WeatherRequest}; use anyhow::format_err; +use reqwest::blocking::Client; use rocket::serde::Serialize; use serde::Deserialize; use std::time::Duration; @@ -18,6 +19,7 @@ impl WeatherProvider for Nogoodnik { fn for_coordinates( &self, + _client: &Client, _cache: &HttpRequestBodyCache, _request: &WeatherRequest, ) -> anyhow::Result { diff --git a/src/providers/open_weather.rs b/src/providers/open_weather.rs index bf348b72..bae2de88 100644 --- a/src/providers/open_weather.rs +++ b/src/providers/open_weather.rs @@ -1,6 +1,7 @@ use crate::providers::cache::{reqwest_cached_body_json, Configuration}; use crate::providers::units::{Coordinates, Kelvin, Ratio, ToCelsius}; use crate::providers::{HttpRequestBodyCache, Weather, WeatherProvider, WeatherRequest}; +use reqwest::blocking::Client; use reqwest::{Method, Url}; use rocket::serde::Deserialize; use serde::Serialize; @@ -37,6 +38,7 @@ impl WeatherProvider for OpenWeather { fn for_coordinates( &self, + client: &Client, cache: &HttpRequestBodyCache, request: &WeatherRequest, ) -> anyhow::Result { @@ -49,14 +51,12 @@ impl WeatherProvider for OpenWeather { ], )?; - let client = reqwest::blocking::Client::new(); - let response = reqwest_cached_body_json::( SOURCE_URI, cache, - &client, + client, Method::GET, - url, + &url, None, )?; diff --git a/src/providers/tomorrow.rs b/src/providers/tomorrow.rs index 6934e1ea..f344b4e5 100644 --- a/src/providers/tomorrow.rs +++ b/src/providers/tomorrow.rs @@ -1,6 +1,7 @@ use crate::providers::cache::{reqwest_cached_body_json, Configuration}; use crate::providers::units::{Celsius, Coordinates, Ratio}; use crate::providers::{HttpRequestBodyCache, Weather, WeatherProvider, WeatherRequest}; +use reqwest::blocking::Client; use reqwest::{Method, Url}; use serde::{Deserialize, Serialize}; use std::time::Duration; @@ -48,6 +49,7 @@ impl WeatherProvider for Tomorrow { fn for_coordinates( &self, + client: &Client, cache: &HttpRequestBodyCache, request: &WeatherRequest, ) -> anyhow::Result { @@ -67,14 +69,12 @@ impl WeatherProvider for Tomorrow { ], )?; - let client = reqwest::blocking::Client::new(); - let response = reqwest_cached_body_json::( SOURCE_URI, cache, - &client, + client, Method::GET, - url, + &url, None, )?;