README.md

# Individual

Process adapter to handle singleton processes in Elixir applications.

## The problem

Sometimes, when you start your program on cluster with *MASTER<->MASTER* strategy,
some of your modules should be started only on one node at a time. This is common pattern, which is called **CLUSTER SINGLETON**.
These modules can be thus be registered within `:global` module, but `:global` doesn't handle name conflicts and restarts.

## Solution

**Individual** will cover working with `:global` module by itself.
It will ensure, that **ONLY** one defined module at a time is working on a cluster,
and also will restart the process on another node in node with working process will fail.

## Default name conflicts resolution

If the cluster is starting in the same time, `Individual` will give time gape of 5 seconds. Within it, 
every node has the same probability to become a leader.

After 5 seconds gap, *oldest* node will always be a leader.

This solution should prevent the situation, when node that is added to the cluster can kill already working processes to restart the
by nodeself.

## Split Brain Resolution

Since **Individual** uses `:global` module, there is a common problem with [cluster splits](https://en.wikipedia.org/wiki/Network_partition).
In this case, each part of previous stable cluster will have it's own process, thus
this process stops to be *singleton*.
In current implementation, **Individual** does not resolve this problems for you,
you should resolve them by yourself.

(*If you have great ideas of doing this - welcome to your PRs to this repo!*)

## Usage

Wrap your worker or supervisor specification inside any of your supervisors with
`Individual` call, passing supervisor specification as an argument for `Individual`.

Your worker or supervisor can register itself with some name or not - `Individual` will take care about registering it in a global scope.

## Examples

```elixir
# Simple call:
def start(_type, _args) do
  Supervisor.start_link([
    {Individual, MyModule}
  ], strategy: :one_for_one, name: Individual.Supervisor)
end

# Call with args:
def start(_type, _args) do
  Supervisor.start_link([
    {Individual, {MyModule, %{foo: :bar}}}
  ], strategy: :one_for_one, name: Individual.Supervisor)
end

# To start multiple processes with same name:
def start(_type, _args) do
  Supervisor.start_link([
    {Individual, Supervisor.child_spec({MyModule, []}, id: Test1)},
    {Individual, Supervisor.child_spec({MyModule, []}, id: Test2)}
  ], strategy: :one_for_one, name: Individual.Supervisor)
end
```

## Starting cluster

```
iex --name a@127.0.0.1 -S mix
iex --name b@127.0.0.1 -S mix
...
```

## Changelog

### 0.3.1

#### **ENHANCEMENTS**
*  Adding `Individual.Registry`, that proxies `:global` module calls. It will prevent process recreation if the node was just added to working cluster.

### 0.2.1

#### **ENHANCEMENTS**
*  Adding `Individual.Wrapper` module, that allows to control GenServer, that don't register themselves in `:global` scope.

### 0.1.1

#### **ENHANCEMENTS**
* Beautifying `observer`'s output

## Installation

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

```elixir
def deps do
  [
    {:individual, "~> 0.3"}
  ]
end
```