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}