pub struct Balance {
pub started: usize,
pub closed: usize,
pub open: usize,
pub unaccounted: i64,
pub agrees: bool,
pub note: String,
}Expand description
What the ledger says about episode lifecycle against what the store holds.
The invariant ADR 0052 asks for, stated as arithmetic a person can check: every episode
that started either closed or is still open. When started exceeds closed + open, the
difference is episodes whose close was never recorded — the shape of the outage that ADR
describes, where events kept arriving and the records they should have produced did not.
The sign matters and the two directions mean opposite things. Positive unaccounted is
the outage: episodes that started, are not open, and produced no closed record — work
that happened and left nothing behind. Negative is ordinary bookkeeping: the ledger was
rotated, or a record was committed from a checkout whose ledger lines are not in this
one, so there are more records than started lines to account for them.
use majordomus_cli::capability::builtin::lifecycle::Balance;
use serde_json::json;
let of = |started, closed, open, unaccounted, agrees| -> Balance {
serde_json::from_value(json!({
"started": started, "closed": closed, "open": open,
"unaccounted": unaccounted, "agrees": agrees, "note": "as measured",
})).unwrap()
};
// the good case: every episode that started either closed or is still open
let sound = of(40, 37, 3, 0, true);
assert_eq!(sound.started as i64 - sound.closed as i64 - sound.open as i64, sound.unaccounted);
assert!(sound.agrees);
// the outage ADR 0052 describes: four closes that were never recorded
let lost = of(40, 33, 3, 4, false);
assert!(lost.unaccounted > 0 && !lost.agrees);
// and a rotated ledger, which is not a fault in either half
let rotated = of(2, 37, 3, -38, false);
assert!(rotated.unaccounted < 0, "more records than lines to account for them");Fields§
§started: usizesession.started lines in the ledger.
closed: usizesession.closed lines.
open: usizeOpen records in the store.
unaccounted: i64started - closed - open. Zero is the good case; negative means the ledger was
rotated under the records, which is ordinary.
agrees: boolWhether the three agree.
note: StringWhat the numbers mean, in words.
Trait Implementations§
Source§impl<'de> Deserialize<'de> for Balance
impl<'de> Deserialize<'de> for Balance
Source§fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
impl Eq for Balance
Source§impl JsonSchema for Balance
impl JsonSchema for Balance
Source§fn schema_id() -> Cow<'static, str>
fn schema_id() -> Cow<'static, str>
Source§fn json_schema(generator: &mut SchemaGenerator) -> Schema
fn json_schema(generator: &mut SchemaGenerator) -> Schema
Source§fn inline_schema() -> bool
fn inline_schema() -> bool
$ref keyword. Read moreimpl StructuralPartialEq for Balance
Auto Trait Implementations§
impl Freeze for Balance
impl RefUnwindSafe for Balance
impl Send for Balance
impl Sync for Balance
impl Unpin for Balance
impl UnsafeUnpin for Balance
impl UnwindSafe for Balance
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> DeserializeOwned for Twhere
T: for<'de> Deserialize<'de>,
§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
§fn equivalent(&self, key: &K) -> bool
fn equivalent(&self, key: &K) -> bool
key and return true if they are equal.