README.md

# ExRaft

![Build Status](https://github.com/bajankristof/ex_raft/actions/workflows/main.yml/badge.svg?branch=main)

An Elixir implementation of the raft consensus protocol.

This library takes an in-memory approach for storing log entries
and the state machine state, therefore it is not really suitable
for storing large amounts of data. Since it's in-memory only though,
it's supposed to be fast.

To get started, check out the
[`ExRaft.StateMachine` documentation](https://hexdocs.pm/ex_raft/ExRaft.StateMachine.html).

To understand the internals of the project, check out the
[main `ExRaft` module documentation](https://hexdocs.pm/ex_raft/ExRaft.html).

For a full overview of the project, check out the full
[online documentation](https://hexdocs.pm/ex_raft).

## Installation

The package can be installed by adding `ex_raft` to your list of dependencies in `mix.exs`:

```elixir
def deps do
  [
    {:ex_raft, "~> 0.2.0"}
  ]
end
```


## Example

```elixir
init_arg = [very_cool: true]
initial_config = [raft1: node(), raft2: node()]

# after starting these servers, they will time out and eventually elect a leader
# amongst themselves
{:ok, _} = ExRaft.start_server(YourStateMachine, init_arg, name: :raft1, initial_config: initial_config)
{:ok, _} = ExRaft.start_server(YourStateMachine, init_arg, name: :raft2, initial_config: initial_config)

# this server can never become leader unless its added to an existing cluster
# since it doesn't know of any other server but is required to achieve
# a minimum majority of 2 in elections and log replication
{:ok, _} = ExRaft.start_server(YourStateMachine, init_arg, name: :raft3, min_majority: 2)

# we could pick any server to await the leader
leader = ExRaft.await_leader(:raft1)
:ok = ExRaft.add_server(leader, :raft3)

# the success result of write/3 depends on the state machine
:ok = ExRaft.write(leader, :hello)

# making a write/3 call to a follower results in an error
follower = List.delete(initial_config, leader) |> List.first()
{:error, {:redirect, ^leader}} = ExRaft.write(follower, :hello)

# if we stop the active leader (or it crashes)
# the rest of the cluster will be able to recover
:ok = ExRaft.stop_server(leader)
:ok = ExRaft.trigger_election(:raft3)
new_leader = ExRaft.await_leader(:raft3)
true = Enum.member?([raft2: node(), raft3: node()], new_leader)
```

## Contributing

All contributions must adhere to the guidelines below:

  * https://github.com/christopheradams/elixir_style_guide
  * https://github.com/christopheradams/elixir_style_guide#modules
  * https://hexdocs.pm/elixir/master/library-guidelines.html
  * https://hexdocs.pm/elixir/master/writing-documentation.html

## License

`ExRaft` source code is released under Apache License 2.0.
Check LICENSE file for more information.