manifold/src/models/fueltank.rs

107 lines
2.9 KiB
Rust
Raw Normal View History

2023-08-30 15:53:24 +00:00
use std::fmt::Debug;
2023-08-24 21:39:38 +00:00
use std::fs;
use std::path::PathBuf;
use dirs::home_dir;
use std::io::{SeekFrom, Seek};
use reqwest::Client;
2023-08-30 17:44:39 +00:00
use reqwest::header::{ACCEPT, CONTENT_TYPE};
2023-08-30 15:53:24 +00:00
use serde::de::DeserializeOwned;
use serde::Serialize;
2023-08-24 21:39:38 +00:00
use crate::error::{ManifoldError, ManifoldResult};
const CACHE_VERSION: &'static str = "1";
pub trait Pump<V> {
2023-08-30 15:53:24 +00:00
fn pump(&mut self) -> Option<V>;
fn len(&self) -> usize;
2023-08-24 21:39:38 +00:00
}
2023-08-30 15:53:24 +00:00
#[derive(Clone, Debug, Serialize, Deserialize)]
2023-08-24 21:39:38 +00:00
pub struct FuelTank {
2023-08-30 15:53:24 +00:00
pub(crate) source_uri: String,
cache_name: Option<String>,
pub(crate) api_key: Option<String>,
cache_mode: TankMode,
2023-08-24 21:39:38 +00:00
}
2023-08-30 15:53:24 +00:00
#[derive(Copy, Clone, Debug, Serialize, Deserialize)]
pub enum TankMode {
2023-08-24 21:39:38 +00:00
Cache,
2023-08-30 15:53:24 +00:00
NoCache,
2023-08-24 21:39:38 +00:00
}
impl FuelTank {
2023-08-30 15:53:24 +00:00
pub async fn next_or_fill<T: Debug, U: Debug>(&self) -> ManifoldResult<T>
where T: DeserializeOwned,
U: Serialize,
U: DeserializeOwned, U: Pump<T>
{
2023-08-24 21:39:38 +00:00
debug!("Filling tank!");
let mut cache = {
let mut path = PathBuf::new();
path.push(home_dir().ok_or(ManifoldError::from("No home dir"))?);
path.push(".local");
2023-08-30 15:53:24 +00:00
path.push(format!("manifold-{}-cache-{}.json", self.cache_name.clone().unwrap(), CACHE_VERSION));
2023-08-24 21:39:38 +00:00
debug!("Cache path: {:?}", &path);
fs::OpenOptions::new()
.read(true)
.write(true)
.create(true)
.open(path)
.map_err(|e| {
error!("Error creating cache file: {}", e);
ManifoldError::from("CACHE ERROR")
})?
};
debug!("Cache: {:?}", &cache);
2023-08-30 15:53:24 +00:00
let json: Result<U, serde_json::Error> = serde_json::from_reader(&mut cache);
2023-08-24 21:39:38 +00:00
debug!("Json: {:?}", &json);
2023-08-30 15:53:24 +00:00
let mut fuel = match json {
2023-08-24 21:39:38 +00:00
Ok(contents) => {
match contents.len() {
2023-08-30 15:53:24 +00:00
0 => self.emit().await?,
2023-08-24 21:39:38 +00:00
_ => contents,
}
}
2023-08-30 15:53:24 +00:00
_ => self.emit().await?,
2023-08-24 21:39:38 +00:00
};
2023-08-30 15:53:24 +00:00
debug!("Got tips: {:?}", &fuel);
let single = fuel.pump().ok_or(ManifoldError::from("CACHE ERROR"))?;
2023-08-24 21:39:38 +00:00
2023-08-30 15:53:24 +00:00
debug!("Got single tip: {:?}", &single);
2023-08-24 21:39:38 +00:00
cache
.set_len(0)
.and_then(|_| cache.seek(SeekFrom::Start(0)))?;
debug!("Writing cache");
2023-08-30 15:53:24 +00:00
serde_json::to_writer(cache, &fuel)?;
return Ok(single)
}
pub async fn emit<U: Debug>(&self) -> ManifoldResult<U>
where U: DeserializeOwned
{
debug!("Getting new tips");
let result: U;
let mut client = Client::new().get(&self.source_uri)
2023-08-30 17:44:39 +00:00
.header(CONTENT_TYPE, "application/json")
.header(ACCEPT, "application/json");
2023-08-30 15:53:24 +00:00
if let Some(api_key) = &self.api_key {
client = client.header("X-API-KEY", api_key);
}
2023-08-30 17:44:39 +00:00
2023-08-30 15:53:24 +00:00
result = client.send().await?.json().await?;
debug!("Result: {:?}", &result);
2023-08-24 21:39:38 +00:00
2023-08-30 15:53:24 +00:00
Ok(result)
2023-08-24 21:39:38 +00:00
}
}