1use std::path::Path;
12use std::sync::Arc;
13use std::time::{SystemTime, UNIX_EPOCH};
14
15use async_trait::async_trait;
16
17use crate::cmd::{Cmd, CmdResult};
18use crate::state_machine::{StateMachine, StateMachineError};
19
20#[derive(Debug, thiserror::Error)]
22pub enum ControlError {
23 #[error(transparent)]
24 StateMachine(#[from] StateMachineError),
25 #[error("raft: {0}")]
26 Raft(String),
27 #[error("config: {0}")]
28 Config(String),
29}
30
31#[async_trait]
33pub trait ControlPlane: Send + Sync {
34 async fn set(&self, key: &[u8], value: &[u8]) -> Result<(), ControlError>;
35 async fn get(&self, key: &[u8]) -> Result<Option<Vec<u8>>, ControlError>;
36 async fn delete(&self, key: &[u8]) -> Result<(), ControlError>;
37 async fn cas(
39 &self,
40 key: &[u8],
41 expect: Option<&[u8]>,
42 value: &[u8],
43 ) -> Result<bool, ControlError>;
44 async fn acquire_lock(
46 &self,
47 key: &str,
48 holder: &str,
49 ttl_ms: u64,
50 ) -> Result<Option<u64>, ControlError>;
51 async fn renew_lock(&self, key: &str, holder: &str, ttl_ms: u64) -> Result<bool, ControlError>;
52 async fn release_lock(&self, key: &str, holder: &str) -> Result<(), ControlError>;
53}
54
55fn now_ms() -> u64 {
56 SystemTime::now()
57 .duration_since(UNIX_EPOCH)
58 .map(|d| d.as_millis() as u64)
59 .unwrap_or(0)
60}
61
62#[derive(Clone)]
65pub struct LocalControlPlane {
66 sm: Arc<StateMachine>,
67}
68
69impl LocalControlPlane {
70 pub fn new(sm: Arc<StateMachine>) -> Self {
71 Self { sm }
72 }
73
74 pub fn open(path: impl AsRef<Path>) -> Result<Self, ControlError> {
76 Ok(Self {
77 sm: Arc::new(StateMachine::open(path)?),
78 })
79 }
80}
81
82#[async_trait]
83impl ControlPlane for LocalControlPlane {
84 async fn set(&self, key: &[u8], value: &[u8]) -> Result<(), ControlError> {
85 self.sm.apply(&Cmd::Set {
86 key: key.to_vec(),
87 value: value.to_vec(),
88 })?;
89 Ok(())
90 }
91
92 async fn get(&self, key: &[u8]) -> Result<Option<Vec<u8>>, ControlError> {
93 Ok(self.sm.get(key)?)
94 }
95
96 async fn delete(&self, key: &[u8]) -> Result<(), ControlError> {
97 self.sm.apply(&Cmd::Delete { key: key.to_vec() })?;
98 Ok(())
99 }
100
101 async fn cas(
102 &self,
103 key: &[u8],
104 expect: Option<&[u8]>,
105 value: &[u8],
106 ) -> Result<bool, ControlError> {
107 match self.sm.apply(&Cmd::Cas {
108 key: key.to_vec(),
109 expect: expect.map(|e| e.to_vec()),
110 value: value.to_vec(),
111 })? {
112 CmdResult::Bool(b) => Ok(b),
113 _ => Ok(false),
114 }
115 }
116
117 async fn acquire_lock(
118 &self,
119 key: &str,
120 holder: &str,
121 ttl_ms: u64,
122 ) -> Result<Option<u64>, ControlError> {
123 match self.sm.apply(&Cmd::AcquireLock {
124 key: key.to_string(),
125 holder: holder.to_string(),
126 now_ms: now_ms(),
127 ttl_ms,
128 })? {
129 CmdResult::Fencing(t) => Ok(t),
130 _ => Ok(None),
131 }
132 }
133
134 async fn renew_lock(&self, key: &str, holder: &str, ttl_ms: u64) -> Result<bool, ControlError> {
135 match self.sm.apply(&Cmd::RenewLock {
136 key: key.to_string(),
137 holder: holder.to_string(),
138 now_ms: now_ms(),
139 ttl_ms,
140 })? {
141 CmdResult::Bool(b) => Ok(b),
142 _ => Ok(false),
143 }
144 }
145
146 async fn release_lock(&self, key: &str, holder: &str) -> Result<(), ControlError> {
147 self.sm.apply(&Cmd::ReleaseLock {
148 key: key.to_string(),
149 holder: holder.to_string(),
150 })?;
151 Ok(())
152 }
153}