{"id":20271693,"url":"https://github.com/eipi1/almost-raft","last_synced_at":"2025-04-11T04:32:42.406Z","repository":{"id":48036848,"uuid":"350451162","full_name":"eipi1/almost-raft","owner":"eipi1","description":"A rust implementation of raft election process","archived":false,"fork":false,"pushed_at":"2024-07-27T08:27:15.000Z","size":19,"stargazers_count":8,"open_issues_count":1,"forks_count":1,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-03-25T02:39:48.936Z","etag":null,"topics":["concensus","distributed-systems","raft"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/eipi1.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-03-22T18:37:23.000Z","updated_at":"2025-01-09T12:43:07.000Z","dependencies_parsed_at":"2024-11-14T12:44:04.701Z","dependency_job_id":"c69b43cb-b8f4-4691-85a0-0f4a1c222515","html_url":"https://github.com/eipi1/almost-raft","commit_stats":{"total_commits":7,"total_committers":2,"mean_commits":3.5,"dds":0.2857142857142857,"last_synced_commit":"0a5e475be58c222edbaa9b5c2cc77bbb859fa5c9"},"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eipi1%2Falmost-raft","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eipi1%2Falmost-raft/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eipi1%2Falmost-raft/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eipi1%2Falmost-raft/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/eipi1","download_url":"https://codeload.github.com/eipi1/almost-raft/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248345202,"owners_count":21088231,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["concensus","distributed-systems","raft"],"created_at":"2024-11-14T12:39:06.902Z","updated_at":"2025-04-11T04:32:42.367Z","avatar_url":"https://github.com/eipi1.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"![Build](https://github.com/eipi1/almost-raft/actions/workflows/rust.yml/badge.svg)\n[![Crates.io][crates-badge]][crates-url]\n[![MIT licensed][mit-badge]][mit-url]\n\n# almost-raft\nConsensus or agreeing on some value is a fundamental issue in a distributed system. \nWhile there are algorithms like Paxos exists since long back, the complexity of those \nmake implementation complicated.\n\nSo Raft was designed to solve the problem while keeping the algorithm understandable.\n\nRaft tackles the problem in two steps -\n* Leader Election - Elect a node as a leader on startup or when the existing one fails\n* Log Replication - Maintain the log consistency among nodes \n  \nFor more on Raft [https://raft.github.io](https://raft.github.io).\n\n## Why almost-raft\nThere is already an implementation of Raft in Rust by awesome people at tikv. If the complete \nraft is the requirement, check out the [tikv/raft-rs](https://github.com/tikv/raft-rs).\n\n*almost-raft* was written with a few things in mind -\n* Personal necessity, of course\n* Minimalism\n* Offloading the inter-node communication mechanism to implementing crates\n* Users don't need to know or care about the inner workings of Raft \n\n*almost-raft* handles only the first step of the algorithm, the election, hence the name.\nIt's up to the developer on how to handle the log replication, if necessary.\n\n## Usage\n*almost-raft* uses a closed loop, the only way to communicate is to use mpsc channel and control\nmessages.\n\nFirst step is to implement `trait Node`. \nFor example - a simple node that uses mpsc channel to communicate with others\n```rust\nuse tokio::sync::mpsc::Sender;\nuse almost_raft::{Message, Node};\n#[derive(Debug, Clone)]\nstruct NodeMPSC {\n    id: String,\n    sender: Sender\u003cMessage\u003cNodeMPSC\u003e\u003e,\n}\n\n#[async_trait]\nimpl Node for NodeMPSC {\n    type NodeType = NodeMPSC;\n    async fn send_message(\u0026self, msg: Message\u003cSelf::NodeType\u003e) {\n        self.sender.send(msg).await;\n    }\n\n    fn node_id(\u0026self) -\u003e \u0026String {\n        \u0026self.id\n    }\n}\n```\nTo initiate `RaftElectionState`\n```rust\nlet (heartbeat_interval, message_timeout, timeout, max_node, min_node) =\n    (1000, 20, 5000, 5, 3);\nlet (tx, mut from_raft) = mpsc::channel(10);\nlet self_id = uuid::Uuid::new_v4().to_string();\nlet nodes = vec![]; // we'll add node later\nlet (state, tx_to_raft) = RaftElectionState::init(\n    self_id,\n    timeout,\n    heartbeat_interval,\n    message_timeout,\n    nodes,\n    tx.clone(),\n    max_node,\n    min_node,\n);\n```\n\nNow we can start the election process using the `state`. But this will not necessarily start the\nelection, it'll wait as long as there isn't enough node (`min_node`).\n\n```rust\ntokio::spawn(raft_election(state));\n```\n\nLet's add nodes\n```rust\nlet (tx,rx) = mpsc::channel(10);\ntx_to_raft\n    .send(Message::ControlAddNode(NodeMPSC {\n        id: uuid::Uuid::new_v4().to_string(),\n        sender: tx,\n    }))\n    .await;\n```\n\nRaft will notify through mpsc channel if there's any change in leadership. To receive the event\n```rust\n// let (tx, mut from_raft) = mpsc::channel(10);\n// tx was used to initialize RaftElectionState\nfrom_raft.recv().await;\n```\n\n[crates-badge]: https://img.shields.io/crates/v/almost-raft.svg\n[crates-url]: https://crates.io/crates/cluster-mode\n[mit-badge]: https://img.shields.io/badge/license-MIT-blue.svg\n[mit-url]: https://github.com/tokio-rs/tokio/blob/master/LICENSE","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Feipi1%2Falmost-raft","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Feipi1%2Falmost-raft","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Feipi1%2Falmost-raft/lists"}