use indexmap::IndexMap;
use meerkat_core::lifecycle::InputId;
use crate::input_state::InputState;
#[derive(Debug, Default, Clone)]
pub struct InputLedger {
states: IndexMap<InputId, InputState>,
}
impl InputLedger {
pub fn new() -> Self {
Self::default()
}
pub fn accept(&mut self, state: InputState) {
self.states.insert(state.input_id.clone(), state);
}
pub fn recover(&mut self, state: InputState) -> bool {
self.states.insert(state.input_id.clone(), state);
true
}
pub fn get(&self, input_id: &InputId) -> Option<&InputState> {
self.states.get(input_id)
}
pub fn remove(&mut self, input_id: &InputId) -> Option<InputState> {
self.states.shift_remove(input_id)
}
pub fn get_mut(&mut self, input_id: &InputId) -> Option<&mut InputState> {
self.states.get_mut(input_id)
}
pub fn iter(&self) -> impl Iterator<Item = (&InputId, &InputState)> {
self.states.iter()
}
pub fn len(&self) -> usize {
self.states.len()
}
pub fn is_empty(&self) -> bool {
self.states.is_empty()
}
}
#[cfg(test)]
#[allow(clippy::unwrap_used)]
mod tests {
use super::*;
#[test]
fn accept_and_retrieve() {
let mut ledger = InputLedger::new();
let id = InputId::new();
let state = InputState::new_accepted(id.clone());
ledger.accept(state);
assert_eq!(ledger.len(), 1);
assert!(!ledger.is_empty());
let retrieved = ledger.get(&id).unwrap();
assert_eq!(retrieved.input_id, id);
}
#[test]
fn accept_preserves_idempotency_key_as_metadata_only() {
let mut ledger = InputLedger::new();
let input_id = InputId::new();
let mut state = InputState::new_accepted(input_id.clone());
state.idempotency_key = Some(crate::identifiers::IdempotencyKey::new("req-123"));
ledger.accept(state);
assert_eq!(ledger.len(), 1);
assert_eq!(
ledger
.get(&input_id)
.and_then(|state| state.idempotency_key.as_ref()),
Some(&crate::identifiers::IdempotencyKey::new("req-123"))
);
}
#[test]
fn recover_does_not_interpret_durability() {
let mut ledger = InputLedger::new();
let mut state = InputState::new_accepted(InputId::new());
state.durability = Some(crate::input::InputDurability::Ephemeral);
assert!(
ledger.recover(state),
"the ledger inserts rows after machine authority has made the retention decision"
);
assert_eq!(ledger.len(), 1);
}
}