spacedb_consistency/outcome.rs
1//! The honesty contract โ every op reports the consistency it *actually* achieved.
2//!
3//! SpaceDB never presents stale-as-fresh or partition-blocked-as-committed. An
4//! [`Outcome`] tells the caller exactly what happened, so an app can show
5//! "saved locally ยท syncing" vs "saved", or refuse to oversell a seat, truthfully.
6
7use crate::tier::Tier;
8
9/// Why a (strong) op could not be served.
10#[derive(Clone, Copy, Debug, PartialEq, Eq)]
11pub enum UnavailableReason {
12 /// The network is partitioned.
13 Partition,
14 /// A quorum could not be reached (too few members responded).
15 QuorumUnreachable,
16}
17
18/// The consistency a read or write actually achieved.
19#[derive(Clone, Debug, PartialEq, Eq)]
20pub enum Outcome {
21 /// The op was committed at this tier (a strong commit, or a causal/convergent
22 /// read that is up to date with what the session has observed).
23 Committed(Tier),
24 /// Written locally and offline-durable, but not yet propagated to peers.
25 Local,
26 /// Served from a replica that is behind the session's frontier by `lag_ops`
27 /// operations โ honestly stale, not silently so.
28 Stale { lag_ops: usize },
29 /// A strong op could not be served and was **not** committed divergently.
30 Unavailable(UnavailableReason),
31}
32
33impl Outcome {
34 /// Whether the op committed at some tier.
35 pub fn is_committed(&self) -> bool {
36 matches!(self, Outcome::Committed(_))
37 }
38
39 /// Whether the op was served at all (anything but `Unavailable`).
40 pub fn is_available(&self) -> bool {
41 !matches!(self, Outcome::Unavailable(_))
42 }
43
44 /// The tier committed at, if any.
45 pub fn tier(&self) -> Option<Tier> {
46 match self {
47 Outcome::Committed(tier) => Some(*tier),
48 _ => None,
49 }
50 }
51}