From 6e401b03345a607e4f86fcb9303ac131662d56e0 Mon Sep 17 00:00:00 2001 From: Hoverbear Date: Thu, 6 Sep 2018 20:52:16 -0700 Subject: [PATCH] Improve examples in documentation. --- src/lib.rs | 74 ++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 61 insertions(+), 13 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 220f536a4..6ab025d19 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -39,16 +39,21 @@ use raft::{ }; // Select some defaults, then change what we need. -let id = 1; -let peers = vec![]; +let config = Config { + id: 1, + peers: vec![1], + ..Default::default() +}; let storage = MemStorage::default(); -let config = Config::new(id); // ... Make any configuration changes. // After, make sure it's valid! config.validate().unwrap(); // We'll use the built-in `MemStorage`, but you will likely want your own. // Finally, create our Raft node! -let mut node = RawNode::new(&config, storage, peers).unwrap(); +let mut node = RawNode::new(&config, storage, vec![]).unwrap(); +// We will coax it into being the lead of a single node cluster for exploration. +node.raft.become_candidate(); +node.raft.become_leader(); ``` ## Ticking the Raft node @@ -57,18 +62,20 @@ Use a timer to tick the Raft node at regular intervals. See the following exampl ```rust # use raft::{Config, storage::MemStorage, raw_node::RawNode}; -# let mut node = RawNode::new(&Config::new(1), MemStorage::default(), vec![]).unwrap(); +# let config = Config { id: 1, peers: vec![1], ..Default::default() }; +# let mut node = RawNode::new(&config, MemStorage::default(), vec![]).unwrap(); +# node.raft.become_candidate(); +# node.raft.become_leader(); use std::{sync::mpsc::{channel, RecvTimeoutError}, time::{Instant, Duration}}; // We're using a channel, but this could be any stream of events. let (tx, rx) = channel(); let timeout = Duration::from_millis(100); +let mut remaining_timeout = timeout; // Send the `tx` somewhere else... -let ticks = 5; // Only tick 5 times. -let mut remaining_timeout = timeout; -for _ in 0..ticks { +loop { let now = Instant::now(); match rx.recv_timeout(remaining_timeout) { @@ -79,6 +86,7 @@ for _ in 0..ticks { Err(RecvTimeoutError::Timeout) => (), Err(RecvTimeoutError::Disconnected) => unimplemented!(), } + let elapsed = now.elapsed(); if elapsed >= remaining_timeout { remaining_timeout = timeout; @@ -87,6 +95,7 @@ for _ in 0..ticks { } else { remaining_timeout -= elapsed; } +# break; } ``` @@ -102,18 +111,57 @@ You can call the `step` function when you receive the Raft messages from other n Here is a simple example to use `propose` and `step`: -```rust,ignore +```rust +# use raft::{Config, storage::MemStorage, raw_node::RawNode, eraftpb::Message}; +# use std::{ +# sync::mpsc::{channel, RecvTimeoutError}, +# time::{Instant, Duration}, +# collections::HashMap +# }; +# +# let config = Config { id: 1, peers: vec![1], ..Default::default() }; +# let mut node = RawNode::new(&config, MemStorage::default(), vec![]).unwrap(); +# node.raft.become_candidate(); +# node.raft.become_leader(); +# +# let (tx, rx) = channel(); +# let timeout = Duration::from_millis(100); +# let mut remaining_timeout = timeout; +# +enum Msg { + Propose { + id: u8, + callback: Box, + }, + Raft(Message), +} + +// Simulate a message coming down the stream. +tx.send(Msg::Propose { id: 1, callback: Box::new(|| ()) }); + let mut cbs = HashMap::new(); loop { - match receiver.recv_timeout(d) { + let now = Instant::now(); + + match rx.recv_timeout(remaining_timeout) { Ok(Msg::Propose { id, callback }) => { cbs.insert(id, callback); - node.propose(vec![id], false).unwrap(); + node.propose(vec![], vec![id]).unwrap(); } Ok(Msg::Raft(m)) => node.step(m).unwrap(), - // ... + Err(RecvTimeoutError::Timeout) => (), + Err(RecvTimeoutError::Disconnected) => unimplemented!(), + } + + let elapsed = now.elapsed(); + if elapsed >= remaining_timeout { + remaining_timeout = timeout; + // We drive Raft every 100ms. + node.tick(); + } else { + remaining_timeout -= elapsed; } - //... + break; } ```