{"id":28759016,"url":"https://github.com/cocky-punch/raft","last_synced_at":"2025-08-10T21:04:33.810Z","repository":{"id":299150287,"uuid":"1001488987","full_name":"cocky-punch/raft","owner":"cocky-punch","description":"Raft Consensus Algorithm implementation in Zig","archived":false,"fork":false,"pushed_at":"2025-08-02T05:26:04.000Z","size":101,"stargazers_count":9,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"master","last_synced_at":"2025-08-02T08:18:53.634Z","etag":null,"topics":["distributed-systems","raft","raft-consensus-algorithm","zig","ziglang"],"latest_commit_sha":null,"homepage":"","language":"Zig","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/cocky-punch.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,"zenodo":null}},"created_at":"2025-06-13T13:19:18.000Z","updated_at":"2025-08-02T05:26:08.000Z","dependencies_parsed_at":"2025-06-16T04:29:11.515Z","dependency_job_id":"c9144f9a-01f3-4a09-b2b8-a2406f7af0e9","html_url":"https://github.com/cocky-punch/raft","commit_stats":null,"previous_names":["turbamentum1/raft","cocky-punch/raft"],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/cocky-punch/raft","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cocky-punch%2Fraft","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cocky-punch%2Fraft/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cocky-punch%2Fraft/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cocky-punch%2Fraft/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/cocky-punch","download_url":"https://codeload.github.com/cocky-punch/raft/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cocky-punch%2Fraft/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":269787312,"owners_count":24475714,"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","status":"online","status_checked_at":"2025-08-10T02:00:08.965Z","response_time":71,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":["distributed-systems","raft","raft-consensus-algorithm","zig","ziglang"],"created_at":"2025-06-17T05:01:05.073Z","updated_at":"2025-08-10T21:04:33.796Z","avatar_url":"https://github.com/cocky-punch.png","language":"Zig","funding_links":[],"categories":["Network \u0026 Web","\u003ca name=\"Zig\"\u003e\u003c/a\u003eZig"],"sub_categories":["Network"],"readme":"# Raft [WIP]\n\nAn implementation of Raft Consensus Algorithm in Zig\n\n## Features\n- [x] Leader tracking\n- [x] In-memory transport\n- [x] Cluster-wide coordination\n- [x] Basic TCP transport\n- [ ] gRPC transport\n- [x] Client redirection\n- [x] Election timeout logic\n- [x] Client command submission\n- [x] Log replication\n- [x] Apply committed entries\n- [x] Heartbeats / ticks\n- [x] State machine plumbing\n- [ ] Client acknowledgment / client request retries - confirmations\n- [ ] Persistent log\n- [ ] Rotation of the log files\n- [ ] Persistent snapshots\n- [ ] Proper handler of `TimeoutNow` -  Leadership Transfer Mechanism - message (Raft extensions)\n- [ ] Read-only GET message (Raft extensions)\n\n## Installation\n\nFetch the master or a release\n\n```bash\nzig fetch --save https://github.com/cocky-punch/raft/archive/refs/heads/master.tar.gz\n# or by a release version\n# zig fetch --save https://github.com/cocky-punch/raft/archive/refs/tags/[RELEASE_VERSION].tar.gz\n```\nwhich will save a reference to the library into build.zig.zon\n\nThen add this into build.zig\n\n```zig\n// after \"b.installArtifact(exe)\" line\nconst raft = b.dependency(\"raft\", .{\n  .target = target,\n  .optimize = optimize,\n});\nexe.root_module.addImport(\"raft\", raft.module(\"raft\"));\n```\n\n\n## Usage\n\n* Implement `MyStateMachine#apply(...)`\n* create a config for each node\n* in each config specify a node itself and all the nodes, including itself again, of a cluster\n* run each of the nodes\n* interract with them via the cli-client\n\n```zig\nconst std = @import(\"std\");\nconst raft = @import(\"raft\");\n\nconst Allocator = std.mem.Allocator;\n\n// Your own state machine implementation.\n// This will apply committed commands (Set/Delete) to a file\nconst MyStateMachine = struct {\n    db_file: std.fs.File,\n\n    // Interface function\n    // Custom implementation, for a custom storage\n    pub fn apply(self: *MyStateMachine, entry: raft.LogEntry) void {\n        switch (entry.command) {\n            .Set =\u003e |cmd| {\n                // Simulate persistent insert by appending to file\n                _ = self.db_file.writer().print(\"SET {s} {any}\\n\", .{cmd.key, cmd.value}) catch {};\n            },\n            .Delete =\u003e |cmd| {\n                _ = self.db_file.writer().print(\"DELETE {s}\\n\", .{cmd.key}) catch {};\n            },\n\n\n            //TODO\n            .Update =\u003e |u| {\n                // Optional: check if key exists first\n                if (!self.db.contains(u.key)) return error.KeyNotFound;\n                try self.db_file_update_key(u.key, u.value); // Overwrite\n            },\n            //TODO\n            .Get =\u003e |cmd| {\n                // find a value in the file\n            },\n        }\n    }\n\n    pub fn init() !MyStateMachine {\n        const f = try std.fs.cwd().createFile(\"raft_db.txt\", .{ .read = true, .truncate = false });\n        return MyStateMachine{ .db_file = f };\n    }\n\n    pub fn deinit(self: *MyStateMachine) void {\n        self.db_file.close();\n    }\n\n    //mock method\n    inline fn db_file_contain_key(k: string) bool {\n        return true;\n    }\n\n    //mock method\n    inline fn db_file_update_key(k: string, v: string) void {\n    }\n};\n\npub fn main() !void {\n    const allocator = std.heap.page_allocator;\n\n    // Load config\n    const config = try raft.loadConfig(allocator, \"node1_raft.yaml\");\n\n    // Wrap the state machine logic\n    var sm_impl = try MyStateMachine.init();\n    const sm = raft.StateMachine(MyStateMachine){\n        .ctx = \u0026sm_impl,\n    };\n\n    const Node = raft.RaftNode(MyStateMachine);\n    const ClusterT = raft.Cluster(MyStateMachine);\n    var cluster = ClusterT.init(allocator);\n    var node = try Node.init(allocator, config.self_id, sm);\n\n    for (config.nodes) |peer| {\n        try cluster.addNodeAddress(peer.id, peer.address);\n    }\n\n    // Start TCP server in background\n    var server = raft.RaftTcpServer(MyStateMachine).init(\n        allocator,\n        \u0026node,\n        \u0026cluster,\n        50, // max clients\n    );\n    const self_port = blk: {\n        for (config.nodes) |p| {\n            if (p.id == config.self_id) break :blk p.address.port;\n        }\n        return error.SelfNotFound;\n    };\n    const t = try std.Thread.spawn(.{}, raft.RaftTcpServer(MyStateMachine).start, .{ \u0026server, self_port });\n    t.detach();\n\n    // Main loop: Raft ticking (election, heartbeat, etc.)\n    while (true) {\n        try cluster.tick();\n        try server.checkCommittedAcks(); // sends acks to clients if commit_index advanced\n        std.time.sleep(50 * std.time.ns_per_ms);\n    }\n}\n\n```\n\n\n## Examples\nin the corresponding directory\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcocky-punch%2Fraft","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcocky-punch%2Fraft","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcocky-punch%2Fraft/lists"}