use super::lys_http::{LysHttp, segment};
use super::{BudgetPolicy, BudgetSource, ServiceEffectError};
use std::sync::Arc;
pub struct LysBudgets {
http: Arc<dyn LysHttp>,
bearer: String,
}
impl std::fmt::Debug for LysBudgets {
fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
formatter
.debug_struct("LysBudgets")
.field("http", &self.http)
.finish_non_exhaustive()
}
}
impl LysBudgets {
#[must_use]
pub const fn new(http: Arc<dyn LysHttp>, bearer: String) -> Self {
Self { http, bearer }
}
}
fn budget_set(budgets: &serde_json::Value) -> Result<bool, ServiceEffectError> {
budgets
.get("version")
.and_then(serde_json::Value::as_u64)
.map(|version| version > 0)
.ok_or_else(|| {
ServiceEffectError(
"lys_could_not_be_asked: the budget answer carries no version".to_owned(),
)
})
}
fn stops_kept(stops: &serde_json::Value) -> Result<bool, ServiceEffectError> {
stops
.get("stops")
.and_then(serde_json::Value::as_array)
.map(|kept| !kept.is_empty())
.ok_or_else(|| {
ServiceEffectError(
"lys_could_not_be_asked: the stops answer carries no stops".to_owned(),
)
})
}
impl BudgetSource for LysBudgets {
fn read(&self, name: &str) -> Result<Option<BudgetPolicy>, ServiceEffectError> {
let id = segment(name);
let budget_route = format!("budgets/agent/{id}");
let budgets = self.http.get(&self.bearer, &budget_route)?;
if !budgets.succeeded() {
return Err(budgets.refused(&budget_route));
}
let stop_route = format!("agents/{id}/stops");
let stops = self.http.get(&self.bearer, &stop_route)?;
if !stops.succeeded() {
return Err(stops.refused(&stop_route));
}
if !budget_set(&budgets.body)? && !stops_kept(&stops.body)? {
return Ok(None);
}
Ok(Some(BudgetPolicy {
holder: format!("agent:{name}"),
budgets: budgets.body,
stops: stops.body,
}))
}
}