RiteRaft - A raft framework, for regular people

Overview

RiteRaft - A raft framework, for regular people

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:

at your option.

Comments
  • [Solved] Need to upgrade to tokio-1, the example does not work.

    [Solved] Need to upgrade to tokio-1, the example does not work.

    I am trying to upgrade it to tokio 1. The current work is https://github.com/ritedb/riteraft/tree/tokio-1 .

    It seems that it has passed the compilation, but it cannot work with actix-web for the time being. Even if use actix-web 4 that has not been officially released.

    bug enhancement help wanted 
    opened by PsiACE 3
  • Crashed after 255 commit

    Crashed after 255 commit

    Hi all, I use this library in my project, and find it will crash after 255th commit. I also test the example code, it also crashes after subunit around 255 puts. Here is one log from my project, the crash occurs when the mailbox sends a message and receives an error result.

    log
    node2_1  | Jul 07 15:16:44.508 INFO [commit: 255] ignored snapshot [index: 245, term: 2], snapshot_term: 2, snapshot_index: 245, commit: 255, raft_id: 3, version: 1.0.0
    node3_1  | Jul 07 15:16:44.508 INFO [commit: 255] ignored snapshot [index: 245, term: 2], snapshot_term: 2, snapshot_index: 245, commit: 255, raft_id: 2, version: 1.0.0
    
    node1_1  | thread 'tokio-runtime-worker' panicked at 'called `Result::unwrap()` on an `Err` value: Unknown', src/main.rs:217:55
    
    

    Crash code line82 on example let result = data.0.send(message).await.unwrap();

    bug 
    opened by KunPengRen 2
  • How to implement the snapshot for persistent database?

    How to implement the snapshot for persistent database?

    I saw the snapshot interface is very simple now, only copy the mem data to the followers' node. Anyone knows how to implement a snapshot for the persistent database which is more suitable for the real-world use case.

    documentation 
    opened by KunPengRen 1
  • chore(deps): bump thread_local from 1.1.3 to 1.1.4 in /examples/riteraft-memstore

    chore(deps): bump thread_local from 1.1.3 to 1.1.4 in /examples/riteraft-memstore

    Bumps thread_local from 1.1.3 to 1.1.4.

    Commits

    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    • @dependabot use these labels will set the current labels as the default for future PRs for this repo and language
    • @dependabot use these reviewers will set the current reviewers as the default for future PRs for this repo and language
    • @dependabot use these assignees will set the current assignees as the default for future PRs for this repo and language
    • @dependabot use this milestone will set the current milestone as the default for future PRs for this repo and language

    You can disable automated security fix PRs for this repo from the Security Alerts page.

    dependencies 
    opened by dependabot[bot] 0
  • chore(deps): bump thread_local from 1.1.3 to 1.1.4 in /examples/riteraft-warp-memstore

    chore(deps): bump thread_local from 1.1.3 to 1.1.4 in /examples/riteraft-warp-memstore

    Bumps thread_local from 1.1.3 to 1.1.4.

    Commits

    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    • @dependabot use these labels will set the current labels as the default for future PRs for this repo and language
    • @dependabot use these reviewers will set the current reviewers as the default for future PRs for this repo and language
    • @dependabot use these assignees will set the current assignees as the default for future PRs for this repo and language
    • @dependabot use this milestone will set the current milestone as the default for future PRs for this repo and language

    You can disable automated security fix PRs for this repo from the Security Alerts page.

    dependencies 
    opened by dependabot[bot] 0
  • chore(deps): bump tokio from 0.2.25 to 1.8.4 in /examples/riteraft-warp-memstore

    chore(deps): bump tokio from 0.2.25 to 1.8.4 in /examples/riteraft-warp-memstore

    Bumps tokio from 0.2.25 to 1.8.4.

    Release notes

    Sourced from tokio's releases.

    Tokio v1.8.4

    1.8.4 (November 15, 2021)

    This release backports a bugfix for a data race when sending and receiving on a closed oneshot channel ([RUSTSEC-2021-0124]) from v1.13.1.

    Fixed

    • sync: fix a data race between oneshot::Sender::send and awaiting a oneshot::Receiver when the oneshot has been closed (#4226)

    Tokio v1.8.3

    1.8.3 (July 22, 2021)

    This release backports two fixes from 1.9.0

    Fixed

    • Fix leak if output of future panics on drop (#3967)
    • Fix leak in LocalSet (#3978)

    #3967: tokio-rs/tokio#3967 #3978: tokio-rs/tokio#3978

    Tokio 1.8.2

    Fixes a missed edge case from 1.8.1.

    Fixed

    • runtime: drop canceled future on next poll (#3965)

    Tokio 1.8.1

    Forward ports 1.5.1 fixes.

    Fixed

    • runtime: remotely abort tasks on JoinHandle::abort (#3934)

    #3934: tokio-rs/tokio#3934

    tokio-1.8.0

    1.8.0 (July 2, 2021)

    Added

    • io: add get_{ref,mut} methods to AsyncFdReadyGuard and AsyncFdReadyMutGuard (#3807)
    • io: efficient implementation of vectored writes for BufWriter (#3163)
    • net: add ready/try methods to NamedPipe{Client,Server} (#3866, #3899)
    • sync: add watch::Receiver::borrow_and_update (#3813)
    • sync: implement From<T> for OnceCell<T> (#3877)

    ... (truncated)

    Commits
    • 2273eb1 chore: fix CI on master (#4008)
    • 249f05c chore: fix output of macro after new rustc release (#4189)
    • 2bf6132 macros: fix type resolution error in #[tokio::main] (#4176)
    • c9228bf macros: make tokio-macros attributes more IDE friendly (#4162)
    • 441427c macros: fix wrong error messages (#4067)
    • cc7d9e1 chore: explicitly relaxed clippy lint for runtime entry macro (#4030)
    • f49b7fc tokio-macros: compat with clippy::unwrap_used (#3926)
    • ea87e4e net: fix the uds_datagram tests with the latest nightly stdlib (#3952)
    • e2e7b5e examples: replace time crate with httpdate (#4169)
    • 9a58f7f tests: update Nix to 0.22.0 (#3951)
    • Additional commits viewable in compare view

    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    • @dependabot use these labels will set the current labels as the default for future PRs for this repo and language
    • @dependabot use these reviewers will set the current reviewers as the default for future PRs for this repo and language
    • @dependabot use these assignees will set the current assignees as the default for future PRs for this repo and language
    • @dependabot use this milestone will set the current milestone as the default for future PRs for this repo and language

    You can disable automated security fix PRs for this repo from the Security Alerts page.

    dependencies 
    opened by dependabot[bot] 0
  • chore(deps): bump tokio from 0.2.25 to 1.8.4 in /examples/riteraft-memstore

    chore(deps): bump tokio from 0.2.25 to 1.8.4 in /examples/riteraft-memstore

    Bumps tokio from 0.2.25 to 1.8.4.

    Release notes

    Sourced from tokio's releases.

    Tokio v1.8.4

    1.8.4 (November 15, 2021)

    This release backports a bugfix for a data race when sending and receiving on a closed oneshot channel ([RUSTSEC-2021-0124]) from v1.13.1.

    Fixed

    • sync: fix a data race between oneshot::Sender::send and awaiting a oneshot::Receiver when the oneshot has been closed (#4226)

    Tokio v1.8.3

    1.8.3 (July 22, 2021)

    This release backports two fixes from 1.9.0

    Fixed

    • Fix leak if output of future panics on drop (#3967)
    • Fix leak in LocalSet (#3978)

    #3967: tokio-rs/tokio#3967 #3978: tokio-rs/tokio#3978

    Tokio 1.8.2

    Fixes a missed edge case from 1.8.1.

    Fixed

    • runtime: drop canceled future on next poll (#3965)

    Tokio 1.8.1

    Forward ports 1.5.1 fixes.

    Fixed

    • runtime: remotely abort tasks on JoinHandle::abort (#3934)

    #3934: tokio-rs/tokio#3934

    tokio-1.8.0

    1.8.0 (July 2, 2021)

    Added

    • io: add get_{ref,mut} methods to AsyncFdReadyGuard and AsyncFdReadyMutGuard (#3807)
    • io: efficient implementation of vectored writes for BufWriter (#3163)
    • net: add ready/try methods to NamedPipe{Client,Server} (#3866, #3899)
    • sync: add watch::Receiver::borrow_and_update (#3813)
    • sync: implement From<T> for OnceCell<T> (#3877)

    ... (truncated)

    Commits
    • 2273eb1 chore: fix CI on master (#4008)
    • 249f05c chore: fix output of macro after new rustc release (#4189)
    • 2bf6132 macros: fix type resolution error in #[tokio::main] (#4176)
    • c9228bf macros: make tokio-macros attributes more IDE friendly (#4162)
    • 441427c macros: fix wrong error messages (#4067)
    • cc7d9e1 chore: explicitly relaxed clippy lint for runtime entry macro (#4030)
    • f49b7fc tokio-macros: compat with clippy::unwrap_used (#3926)
    • ea87e4e net: fix the uds_datagram tests with the latest nightly stdlib (#3952)
    • e2e7b5e examples: replace time crate with httpdate (#4169)
    • 9a58f7f tests: update Nix to 0.22.0 (#3951)
    • Additional commits viewable in compare view

    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    • @dependabot use these labels will set the current labels as the default for future PRs for this repo and language
    • @dependabot use these reviewers will set the current reviewers as the default for future PRs for this repo and language
    • @dependabot use these assignees will set the current assignees as the default for future PRs for this repo and language
    • @dependabot use this milestone will set the current milestone as the default for future PRs for this repo and language

    You can disable automated security fix PRs for this repo from the Security Alerts page.

    dependencies 
    opened by dependabot[bot] 0
Owner
Rite Database
Rite Database
A flexible web framework that promotes stability, safety, security and speed.

A flexible web framework that promotes stability, safety, security and speed. Features Stability focused. All releases target stable Rust. This will n

Gotham 2.1k Jan 3, 2023
An Extensible, Concurrent Web Framework for Rust

Iron Extensible, Concurrency Focused Web Development in Rust. Response Timer Example Note: This example works with the current iron code in this repos

null 6.1k Dec 27, 2022
An expressjs inspired web framework for Rust

nickel.rs nickel.rs is a simple and lightweight foundation for web applications written in Rust. Its API is inspired by the popular express framework

null 3k Jan 3, 2023
[OUTDATED] A light HTTP framework for Rust

Rustful A light HTTP framework for Rust, with REST-like features. The main purpose of Rustful is to create a simple, modular and non-intrusive foundat

Erik Hedvall 873 Nov 12, 2022
A web framework for Rust.

Rocket Rocket is an async web framework for Rust with a focus on usability, security, extensibility, and speed. #[macro_use] extern crate rocket; #[g

Sergio Benitez 19.5k Jan 8, 2023
REST-like API micro-framework for Rust. Works with Iron.

Table of Contents What is Rustless? Usage warning Basic Usage Complex example Mounting Parameters validation and coercion Use JSON Schema Query string

Rustless 610 Jan 4, 2023
Fully async-await http server framework

Saphir is a fully async-await http server framework for rust The goal is to give low-level control to your web stack (as hyper does) without the time

Richer Archambault 83 Dec 19, 2022
A lightweight web framework built on hyper, implemented in Rust language.

Sapper Sapper, a lightweight web framework, written in Rust. Sapper focuses on ergonomic usage and rapid development. It can work with stable Rust. Sa

Daogang Tang 622 Oct 27, 2022
Web framework in Rust

Rouille, a Rust web micro-framework Rouille is a micro-web-framework library. It creates a listening socket and parses incoming HTTP requests from cli

Pierre Krieger 840 Jan 1, 2023
A fast, boilerplate free, web framework for Rust

Tower Web A web framework for Rust with a focus on removing boilerplate. API Documentation Tower Web is: Fast: Fully asynchronous, built on Tokio and

Carl Lerche 969 Dec 22, 2022
Sincere is a micro web framework for Rust(stable) based on hyper and multithreading

The project is no longer maintained! Sincere Sincere is a micro web framework for Rust(stable) based on hyper and multithreading. Style like koa. The

null 94 Oct 26, 2022
:zap: fast http framework for rust

zap ⚡ The mission of zap is, to deliver a basic, but fast rust web server library. Documentation About This code is based on tokio's minihttp project,

Daniel Oltmanns 51 Jun 7, 2022
A framework that allows anyone to create an Urbit Chatbot with only a few lines of code.

Urbit Chatbot Framework A framework that allows anyone to create an Urbit Chatbot with only a few lines of code. The Urbit Chatbot Framework takes car

Robert Kornacki 24 Oct 15, 2022
Node.js http server framework powered by Hyper native binding.

hnsjs POC project. Install this test package yarn add @hnsjs/core Support matrix node10 node12 node14 node15 Windows x64 ✓ ✓ ✓ ✓ Windows x32 ✓ ✓ ✓ ✓

LongYinan 18 Nov 23, 2022
simple static file server written in Rust based on axum framework

static-server simple static file server written in Rust based on axum framework I'm learning Rust and axum. My thought is simple. axum has a static-fi

null 27 Jan 1, 2023
Handlebars middleware for Iron web framework

handlebars-iron Handlebars middleware for the Iron web framework. This library, together with handlebars, iron and hyper, works on both stable and nig

Ning Sun 118 Jun 28, 2022
Salvo is a powerful and simplest web server framework in Rust world

Salvo is an extremely simple and powerful Rust web backend framework. Only basic Rust knowledge is required to develop backend services.

Salvo 1.2k Jan 5, 2023
A toy web framework inspired by gin-gonic/gin and expressjs/express.

Rum Framework A toy web framework inspired by gin-gonic/gin and expressjs/express. Installation Just add rum_framework to the dependencies of Cargo.to

Hidetomo Kou(YingZhi 2 Dec 20, 2022
The light web framework for Rust.

Rusty Web Rusty web is a simple to use, fully customizable lightweight web framework for rust developers. Learn rusty web Installation [dependencies]

Tej Magar 5 Feb 27, 2024