pub fn admission_conflicts<'a>(
state: &'a CooperationState,
session: &str,
scope: &[String],
mode: ClaimMode,
) -> Vec<&'a ClaimView>Expand description
The live exclusive claims of other sessions a new exclusive claim of session over
scope would meet: empty means admissible. An advisory claim is always admissible.
This is the difference between refusing a claim and reporting a conflict after the fact. Admission is checked against the folded state before anything is written, so a claim that could have been refused is refused; what is left — genuinely concurrent claims from two sides of a partition — is what the fold ranks afterwards, and both runtimes name the same winner.
use std::sync::Arc;
use majordomus_cli::mesh::identity::NodeIdentity;
use majordomus_cli::mesh::journal::{ClaimMode, EventBody, Journal, StreamLiveness};
use majordomus_cli::mesh::state::{admission_conflicts, fold};
let j = Journal::open(Arc::new(NodeIdentity::ephemeral().unwrap()), "0000000000000001",
"repo".into(), None).unwrap();
j.append_own(EventBody::ClaimAcquired { claim: "c1".into(), session: "s1".into(),
scope: vec!["apps".into()], intent: None, mode: ClaimMode::Exclusive, issue: None })
.unwrap();
let state = fold(&j.events(), &|_| StreamLiveness::Own);
let held = &state.claims[0];
// another session cannot take a scope inside one already held exclusively
let met = admission_conflicts(&state, "s2", &["apps/majordomus-cli".into()],
ClaimMode::Exclusive);
assert_eq!(met.len(), 1);
assert_eq!(met[0].key, held.key, "the refusal names what it met");
// the holder is not in its own way, and an advisory claim is never refused
assert!(admission_conflicts(&state, &held.session, &["apps".into()], ClaimMode::Exclusive)
.is_empty());
assert!(admission_conflicts(&state, "s2", &["apps".into()], ClaimMode::Advisory).is_empty());