package oraft
Install
Dune Dependency
Authors
Maintainers
Sources
md5=30d9c899940ca6b46297e59b13eaa3bf
sha512=27b6e893dbc72dc54058f49deeb50e2df784d292918485ce360457f8eb9b9c7c2c90f781e5f725a70b47664a1e039106c374c9429e6c773e70780d46b776a386
Description
Raft consensus algorithm implemented in OCaml
README
ORaft
Library of Raft consensus algorithm implemented in OCaml
Current Status
TODO
Cluster membership changes
Log compaction
Requirement
OCaml 4.14 or later
opam
dune
Build
$ opam install --deps-only --with-test .
$ dune build
Install
$ opam install .
Test
Unit test
$ dune runtest
Smoke test
This repository has an example Raft application that is a simple KVS as described below. The following command runs 5 KVS servers and a verification tool that sequentially restarts at most 2 servers.
$ smoke_test/run.sh
Chaos test
This repository has an example Raft application that is a simple KVS as described below. The following command runs 5 KVS servers, a verification tool and chaos testing tool in docker containers. The 5 KVS servers will randomly experience pause and network delay.
$ chaos_test/run.sh
Usage
Create a config file for each Raft application
{
"node_id": 2,
"nodes": [
{"id": 1, "host": "localhost", "port": 7891, "app_port": 8181},
{"id": 2, "host": "localhost", "port": 7892, "app_port": 8182},
{"id": 3, "host": "localhost", "port": 7893, "app_port": 8183}
],
"log_file": "oraft.log",
"log_level": "INFO",
"state_dir": "state",
"election_timeout_millis": 200,
"heartbeat_interval_millis": 50,
"request_timeout_millis": 100
}
node_id
needs to be modified for each node.
Write an application using ORaft
The following code is a very simple application that uses ORaft.
let main ~conf_file =
let oraft =
Oraft.start ~conf_file ~apply_log:(fun ~node_id ~log_index ~log_data ->
Printf.printf
"[node_id:%d, log_index:%d] %s\n"
node_id log_index log_data;
flush stdout
)
in
let rec loop () =
let%lwt s = Lwt_io.read_line Lwt_io.stdin in
let%lwt result = oraft.post_command s in
let%lwt _ = Lwt_io.printl (if result then "OK" else "ERR") in
loop ()
in
Lwt.join [ loop (); oraft.process ] |> Lwt_main.run
let () =
let open Command.Let_syntax in
Command.basic ~summary:"Simple example application for ORaft"
[%map_open
let config =
flag "config" (required string) ~doc:"CONFIG Config file path"
in
fun () -> main ~conf_file:config]
|> Command_unix.run
See example-simple
project for details.
Example
This repo contains example-kv
project that is a simple KVS.
Run a cluster on multi processes
You can execute the project like this:
$ ./example-kv/run_all.sh
5 Raft application processes will start.
And then, you can send a request using curl
command or something
$ curl -X POST --data-binary 'SET a hello' http://localhost:8181/command
$ curl -X POST --data-binary 'GET a' http://localhost:8182/command
hello
$ curl -X POST --data-binary 'SET b 42' http://localhost:8183/command
$ curl -X POST --data-binary 'GET b' http://localhost:8184/command
42
$ curl -X POST --data-binary 'INCR b' http://localhost:8185/command
$ curl -X POST --data-binary 'GET b' http://localhost:8181/command
43
Development
Pre-commit hook
This project uses pre-commit to automate code format and so on as much as possible. Please install pre-commit and the git hook script as follows.
$ ls -a .pre-commit-config.yaml
.pre-commit-config.yaml
$ pre-commit install
The code formatter is automatically executed when commiting files. A commit will fail and be formatted by the formatter when any invalid code format is detected. Try to commit the change again.
Dependencies (10)
-
ppx_deriving_yojson
>= "3.6.0"
- ppx_deriving
- lwt_ppx
- yojson
-
sqlite3
>= "5.0.0"
-
cohttp-lwt-unix
>= "5.0.0"
-
core_unix
>= "v0.16.0"
-
core
>= "v0.16.0"
-
dune
>= "3.6"
-
ocaml
>= "4.14.0"
Used by
None
Conflicts
None