Skip to main content

mocra_cluster/
cmd.rs

1//! State machine commands and results.
2//!
3//! `Cmd` is **serializable**: it will be replicated to a majority through the Raft log and then
4//! applied deterministically by every node. That is why time (`now_ms`) is carried inside the
5//! command by the caller rather than read from the clock inside `apply` — that is what keeps
6//! `apply` deterministic.
7
8use serde::{Deserialize, Serialize};
9
10/// A replicated state machine command.
11#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
12pub enum Cmd {
13    /// Write a key/value pair.
14    Set { key: Vec<u8>, value: Vec<u8> },
15    /// Delete a key.
16    Delete { key: Vec<u8> },
17    /// Compare-and-swap: write `value` only if the current value equals `expect`. Returns whether
18    /// the swap succeeded.
19    Cas {
20        key: Vec<u8>,
21        expect: Option<Vec<u8>>,
22        value: Vec<u8>,
23    },
24    /// Acquire a lock: granted if it is free, expired, or already held by the same holder; returns
25    /// a monotonically increasing fencing token.
26    AcquireLock {
27        key: String,
28        holder: String,
29        now_ms: u64,
30        ttl_ms: u64,
31    },
32    /// Lease renewal: extend the deadline if the caller still holds the lock and it has not expired.
33    RenewLock {
34        key: String,
35        holder: String,
36        now_ms: u64,
37        ttl_ms: u64,
38    },
39    /// Release a lock (only the holder may release it).
40    ReleaseLock { key: String, holder: String },
41}
42
43/// The result of an `apply`.
44#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
45pub enum CmdResult {
46    /// Success with no return value (set/delete/release).
47    Ok,
48    /// Whether a cas / renew succeeded.
49    Bool(bool),
50    /// The fencing token from acquire_lock (`None` = the lock was not acquired).
51    Fencing(Option<u64>),
52}
53
54/// A lock record (stored in the state machine). The fencing token increases monotonically and
55/// prevents an expired holder from processing the same work again after coming back to life.
56#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
57pub struct Lock {
58    pub holder: String,
59    pub expire_at_ms: u64,
60    pub fencing_token: u64,
61}