Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/peterkrauz/pistis
Transparent, easily-configurable, strongly-consistent distributed state-machine replicas.
https://github.com/peterkrauz/pistis
distributed-systems elixir erlang fault-tolerance raft state-machine-replication
Last synced: 10 days ago
JSON representation
Transparent, easily-configurable, strongly-consistent distributed state-machine replicas.
- Host: GitHub
- URL: https://github.com/peterkrauz/pistis
- Owner: peterkrauz
- License: apache-2.0
- Created: 2022-05-30T22:13:28.000Z (over 2 years ago)
- Default Branch: master
- Last Pushed: 2022-07-18T19:56:05.000Z (over 2 years ago)
- Last Synced: 2024-09-18T00:02:53.132Z (about 2 months ago)
- Topics: distributed-systems, elixir, erlang, fault-tolerance, raft, state-machine-replication
- Language: Elixir
- Homepage:
- Size: 72.3 KB
- Stars: 2
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE.md
Awesome Lists containing this project
README
# Pistis
An Elixir library to reduce the boilerplate work one would have in order to implement a distributed cluster of strongly-consistent BEAM instances.
Pistis ensures deterministic commands through [`:ra`](https://github.com/rabbitmq/ra), an Erlang-based implementation of the [Raft](https://www.usenix.org/conference/atc14/technical-sessions/presentation/ongaro) consensus protocol.
## Installation
1. Add the `pistis` artifact to you project's dependencies
```elixir
def deps do
[
{:pistis, "~> 0.1.10"}
]
end
```2. Define your state machine module on `config/config.exs`
```elixir
config :pistis, machine: YourApp.YourStateMachine
```3. Add the library's entrypoint supervisor to your Elixir app's children
```elixir
defmodule YourApp.Application do
# ...
def start(_type, _args) do
children = [Pistis.Core.Entrypoint]
opts = [strategy: :one_for_one, name: YourApp.Supervisor]
Supervisor.start_link(children, opts)
end
end
```4. Profit
## Usage
The library demands two things from its user:
1. Make sure client commands are sent to Pistis' server
```elixir
defmodule YourApp.SomeModule do
def your_fn_that_increments_state_by_2(_args) do
Pistis.Server.send_request({:increment_by, 2})
enddef another_fn_but_a_shy_one(_args) do
Pistis.Server.send_request(:increment)
end
end
```2. A concrete state-machine
```elixir
defmodule YourApp.YourStateMachine do
@behaviour Pistis.Machinedef initial_state, do: 0
def process_command(%Pistis.Request{body: :increment}, current_state) do
%Pistis.Response(response: :ok, state: current_state + 1)
enddef process_command(%Pistis.Request{body: {:increment_by, num}}, current_state) do
%Pistis.Response(response: :ok, state: current_state + num)
end
end
```Pistis does not inspect your message's content. It simply wraps your state-machine implementation with a Raft-aware component that takes care of delivering the request and getting a response out of it.
All requests are wrapped inside the `Pistis.Request` struct. Responses should follow the same pattern by being wrapped in a `Pistis.Response` struct.
## Examples
Example state-machines can be found at `lib/example`