/ src / server / state.rs
state.rs
 1  use crate::{
 2      Args, Metrics, PushMetrics, Sun, ambient_weather::AmbientWeatherReport, metrics::PushError,
 3  };
 4  use http::header::CONTENT_TYPE;
 5  use reqwest_middleware::{Extension, RequestBuilder};
 6  use reqwest_tracing::{OtelName, TracingMiddleware};
 7  use std::{fmt::Debug, sync::RwLock, time::Duration};
 8  use tracing::{debug, error};
 9  
10  const OPENMETRICS_TEXT: &str = "application/openmetrics-text";
11  
12  pub struct ServerState {
13      client: reqwest_middleware::ClientWithMiddleware,
14      conditions_interval: Duration,
15      latest: RwLock<Option<AmbientWeatherReport>>,
16      metrics: Metrics,
17      push_url: reqwest::Url,
18      sun: Sun,
19  }
20  
21  impl ServerState {
22      pub fn new(args: &Args, metrics: Metrics) -> Self {
23          let push_url = args.push_url();
24          let sun = args.into();
25  
26          let client = reqwest::ClientBuilder::new()
27              .user_agent("ambient-weather-local")
28              .build()
29              .expect("Unable to build HTTP client");
30  
31          let client = reqwest_middleware::ClientBuilder::new(client)
32              .with_init(Extension(OtelName("report push".into())))
33              .with(TracingMiddleware::default())
34              .build();
35  
36          Self {
37              client,
38              conditions_interval: Duration::from_secs(5 * 60),
39              latest: Default::default(),
40              metrics,
41              push_url,
42              sun,
43          }
44      }
45  
46      pub fn conditions_interval(&self) -> Duration {
47          self.conditions_interval
48      }
49  
50      pub fn latest(&self) -> Option<AmbientWeatherReport> {
51          let guard = self.latest.read().unwrap();
52  
53          (*guard).clone()
54      }
55  
56      pub async fn push(&self, report: AmbientWeatherReport) {
57          {
58              let mut guard = self.latest.write().unwrap();
59  
60              *guard = Some(report.clone());
61          }
62  
63          let request_builder = self.client.post(self.push_url.clone());
64      }
65  }
66  
67  impl Debug for ServerState {
68      fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
69          f.debug_struct("ServerState")
70              .field("client", &"...")
71              .field("metrics", &"...")
72              .field("push_url", &self.push_url)
73              .finish()
74      }
75  }