#[cfg(test)]
mod tests;
use crate::observatory::model::cost::{
CostCounterReading, CostInterval, CostIntervalIssue, CounterMovement, SignedCycleAmount,
};
pub(in crate::observatory) const fn interval(
start_ns: u64,
end_ns: u64,
) -> Result<CostInterval, CostIntervalIssue> {
if end_ns <= start_ns {
return Err(CostIntervalIssue::NonAdvancingWindow);
}
Ok(CostInterval { start_ns, end_ns })
}
pub(in crate::observatory) fn counter(
before: CostCounterReading,
after: CostCounterReading,
) -> Result<CounterMovement, CostIntervalIssue> {
if before.saturated || after.saturated {
return Err(CostIntervalIssue::SaturatedCounter);
}
if before.window_id != after.window_id {
return Err(CostIntervalIssue::CounterWindowChanged);
}
let interval = interval(before.observed_at_ns, after.observed_at_ns)?;
let amount = after
.value
.checked_sub(before.value)
.ok_or(CostIntervalIssue::CounterDecreased)?;
Ok(CounterMovement { interval, amount })
}
pub(in crate::observatory) const fn difference(left: u128, right: u128) -> SignedCycleAmount {
SignedCycleAmount {
negative: left < right,
magnitude: left.abs_diff(right),
}
}
pub(in crate::observatory) fn grant_adjusted_decrease(
opening: u128,
closing: u128,
incoming: u128,
outgoing: u128,
) -> Result<SignedCycleAmount, CostIntervalIssue> {
let balance = difference(opening, closing);
let grants = difference(incoming, outgoing);
if balance.negative == grants.negative {
Ok(SignedCycleAmount {
negative: balance.negative,
magnitude: balance
.magnitude
.checked_add(grants.magnitude)
.ok_or(CostIntervalIssue::Overflow)?,
})
} else if balance.magnitude >= grants.magnitude {
let magnitude = balance.magnitude - grants.magnitude;
Ok(SignedCycleAmount {
negative: magnitude != 0 && balance.negative,
magnitude,
})
} else {
Ok(SignedCycleAmount {
negative: grants.negative,
magnitude: grants.magnitude - balance.magnitude,
})
}
}