This is an attempt to create a layer on top of tikv/raft-rs, that is easier to use and implement. This is not supposed to be the most featureful raft, but instead a convenient interface to get started quickly, and have a working raft in no time.
The interface is strongly inspired by the one used by canonical/raft.
Getting started
In order to "raft" storage, we need to implement the Storage trait for it.
Bellow is an example with HashStore, which is a thread-safe wrapper around an
HashMap:
/// convienient data structure to pass Message in the raft #[derive(Serialize, Deserialize)] pub enum Message { Insert { key: u64, value: String }, } #[derive(Clone)] struct HashStore(Arc<RwLock<HashMap<u64, String>>>); impl Store for HashStore { type Error = RaftError; fn apply(&mut self, message: &[u8]) -> Result<Vec<u8>, Self::Error> { let message: Message = deserialize(message).unwrap(); let message: Vec<u8> = match message { Message::Insert { key, value } => { let mut db = self.0.write().unwrap(); db.insert(key, value.clone()); serialize(&value).unwrap() } }; Ok(message) } fn snapshot(&self) -> Vec<u8> { serialize(&self.0.read().unwrap().clone()).unwrap() } fn restore(&mut self, snapshot: &[u8]) -> Result<(), Self::Error> { let new: HashMap<u64, String> = deserialize(snapshot).unwrap(); let mut db = self.0.write().unwrap(); let _ = std::mem::replace(&mut *db, new); Ok(()) } }
Only 3 methods need to be implemented for the Store:
Store::apply: applies a commited entry to the store.Store::snapshot: returns snapshot data for the store.Store::restore: applies the snapshot passed as argument.
running the raft
#[tokio::main] fn main() { let store = HashStore::new(); let raft = Raft::new(options.raft_addr, store.clone()); let mailbox = Arc::new(raft.mailbox()); let (raft_handle, mailbox) = match options.peer_addr { Some(addr) => { info!("running in follower mode"); let handle = tokio::spawn(raft.join(addr)); (handle, mailbox) } None => { info!("running in leader mode"); let handle = tokio::spawn(raft.lead()); (handle, mailbox) } }; tokio::join!(raft); }
The mailbox gives you a way to interact with the raft, for sending a message, or leaving the cluster for example.
Credit
This work is based on raft-frp, but more adjustments and improvements have been made to the code .
License
This library is licensed under either of:
- MIT license LICENSE-MIT or http://opensource.org/licenses/MIT
- Apache License 2.0 LICENSE-APACHE or https://opensource.org/licenses/Apache-2.0
at your option.