# Visor
Visor adds VSR (View Stamped Replication) on top of GenServer.
If you want easy process supervision, add a Supervisor.
If you want easy replication, add Visor!
## Usage
Create a module, use `Visor`, and implement the callbacks.
Let's create a replicated cache.
Define a module called `Cache`, set the `initial_state` to an empty map (`%{}`) and implement the
`handle_commit` callback which returns `nil` and merges the passed in data with the existing state.
```elixir
defmodule Cache do
use Visor
@impl Visor
def initial_state(_opts), do: %{}
@impl Visor
def handle_commit({:add, item}, state) do
{:ok, nil, Map.merge(state, item)}
end
end
```
Now, add Cache to your application's supervision tree, and configure your `cluster_size`
(how many nodes you want this to replicate across)
```elixir
def start(_type, _args) do
children = [
{Cache, cluster_size: 3}
]
opts = [strategy: :one_for_one, name: Cache.Supervisor]
Supervisor.start_link(children, opts)
end
```
And that's it. You now have a cache that's replicated across 3 nodes.
It handles replication, leader election, and recovery.
To add an item to your cache, commit the data:
```elixir
Cache.commit({:add, %{user1: %{email: "advisor1@example.com"}}})
#=> nil
Cache.commit({:add, %{user2: %{email: "advisor2@example.com"}}})
#=> nil
```
Get the full state of your cache with:
```elixir
Cache.get()
#=> %{email: "advisor@example.com"}
%{
user1: %{email: "advisor1@example.com"},
user2: %{email: "advisor1@example.com"}
}
```
Pass in an accessor list to `get_in` your cache for quicker access:
```elixir
Cache.get_in([:user1, :email])
#=> "advisor1@example.com"
```