use std::{collections::HashMap, fmt::Display, sync::{mpsc::Sender, Arc}};
use anyhow::{bail, Error};
use aphomie_db_client::{AphomieDbClient, MetadataTrendDataJoinDb};
use chrono::{DateTime, Utc};
type Result<T> = core::result::Result<T, Error>;
async fn get_trend_data(
db_client: Arc<AphomieDbClient>,
sender: Sender<MetadataTrendDataJoinDb>,
) -> Result<()> {
let take_count = 1_000;
let mut count: i64 = 0;
loop {
let result = db_client
.get_metadata_join_trend_data_offset_limit(count, take_count)
.await;
if let Err(e) = result {
bail!("{e}");
}
let trends = result.unwrap();
let read: i64 = trends.len().try_into().unwrap();
count += read;
for t in trends {
if let Err(e) = sender.send(t) {
bail!("{e}");
}
}
if read == 0 {
break;
}
}
Ok(())
}
struct PromEntry<T>
where
T: Display,
{
name: String,
labels: HashMap<String, String>,
value: T,
stamp: DateTime<Utc>,
}
impl TryFrom<MetadataTrendDataJoinDb> for PromEntry<f64>
{
type Error = anyhow::Error;
fn try_from(value: MetadataTrendDataJoinDb) -> std::result::Result<Self, Self::Error> {
if value.value.is_none() {
bail!("value was null");
}
let mut s: Vec<&str> = value.source.split('/').collect();
let name = s.pop().unwrap().to_string();
let location = s.join("/");
let labels = HashMap::from([("location".to_string(), location)]);
let stamp = value.timestamp;
let value = value.value.unwrap();
Ok(PromEntry {
name,
labels,
stamp,
value
})
}
}
impl<T> PromEntry<T>
where
T: Display,
{
pub fn to_query(&self) -> String {
let parsed_labels: Vec<String> = self
.labels
.iter()
.map(|(k, v)| format!("{}=\"{}\"", k, v))
.collect();
let labels_string = parsed_labels.join(",");
let name = self.name.clone();
let value = self.value.to_string();
let stamp = (self.stamp.timestamp() * 1000).to_string();
format!("{name}{{{labels_string}}} {value} {stamp}")
}
}