README.md

simple_global
=====

* A simple gen_server callback module for global name register.
* Eventual consistency for simplicity and performance.
* One process is allowed to have multiple names.
* Processes are only allowed to register/unregister from their own nodes, for consistency.

Build
-----

    $ ./rebar3 compile

Show Case
-----

### start three nodes and simple_global, connect a and b

```
$ erl -sname a -setcookie abc -pa _build/default/lib/simple_global/ebin/
a> net_kernel:connect_node('b@MacBook-Pro').
true
a> simple_global:start().
{ok,<0.120.0>}

$ erl -sname b -setcookie abc -pa _build/default/lib/simple_global/ebin/
b> simple_global:start().
{ok,<0.98.0>}

$ erl -sname c -setcookie abc -pa _build/default/lib/simple_global/ebin/
c> simple_global:start().
{ok,<0.105.0>}
```

### register a name and see it's synced within a and b nodes

```
a> simple_global:register_name(test, self()).
yes
a> ets:tab2list(simple_global).
[{test,<0.116.0>,local,#Ref<0.176713640.3089891331.128970>,
       #{}},
 {{ref,#Ref<0.176713640.3089891331.128970>},test}]

b> ets:tab2list(simple_global).
[{test,<9356.116.0>,'a@MacBook-Pro',undefined,#{}}]

a> simple_global:set_meta(test, #{a => 123}).
ok
a> ets:tab2list(simple_global).
[{test,<0.116.0>,local,#Ref<0.176713640.3089891331.128970>,
       #{a => 123}},
 {{ref,#Ref<0.176713640.3089891331.128970>},test}]

b> ets:tab2list(simple_global).
[{test,<9356.116.0>,'a@MacBook-Pro',undefined,
       #{a => 123}}]
```

### let node c join the cluster and see it gets data

```
c> ets:tab2list(simple_global).
[]
c> net_kernel:connect_node('a@MacBook-Pro').
true
c> ets:tab2list(simple_global).
[{test,<9324.116.0>,'a@MacBook-Pro',undefined,
       #{a => 123}}]
```

### update meta data, only allowed in the node where the process was registered

```
c> simple_global:set_meta(test, #{a => 456}).
error

a> simple_global:set_meta(test, #{a => 456}).
ok
a> ets:tab2list(simple_global).
[{test,<0.116.0>,local,#Ref<0.176713640.3089891331.128970>,
       #{a => 456}},
 {{ref,#Ref<0.176713640.3089891331.128970>},test}]

b> ets:tab2list(simple_global).
[{test,<9356.116.0>,'a@MacBook-Pro',undefined,
       #{a => 456}}]

c> ets:tab2list(simple_global).
[{test,<9324.116.0>,'a@MacBook-Pro',undefined,
       #{a => 456}}]
```

### when disconnects, registry will be removed since the process is no longer accessible

```
c> net_kernel:disconnect('a@MacBook-Pro').
true
c> net_kernel:disconnect('b@MacBook-Pro').
true
> ets:tab2list(simple_global).
[]
```

### when name clash happens, for example, when joining a cluster, processes registered in a smaller(compared with <) nodename win, the other process will be killed

```
c> simple_global:register_name(test, self()).
yes
c> ets:tab2list(simple_global).
[{test,<0.128.0>,local,#Ref<0.1190508258.1479016450.19536>,
       #{}},
 {{ref,#Ref<0.1190508258.1479016450.19536>},test}]
c> net_kernel:connect_node('a@MacBook-Pro').
true
=ERROR REPORT==== 28-Apr-2021::18:41:24.756659 ===
simple_global: Name conflict, terminating {test,<0.128.0>}

** exception exit: killed

c> ets:tab2list(simple_global).
[{test,<9324.116.0>,'a@MacBook-Pro',undefined,
       #{a => 456}}]

a> ets:tab2list(simple_global).
[{test,<0.116.0>,local,#Ref<0.176713640.3089891331.128970>,
       #{a => 456}},
 {{ref,#Ref<0.176713640.3089891331.128970>},test}]

```