forked from bitwalker/libcluster
-
Notifications
You must be signed in to change notification settings - Fork 0
/
supervisor.ex
89 lines (77 loc) · 2.78 KB
/
supervisor.ex
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
defmodule Cluster.Supervisor do
@moduledoc """
This module handles supervising the configured topologies, and is designed
to support being started within your own supervision tree, as shown below:
defmodule MyApp.App do
use Application
def start(_type, _args) do
topologies = [
example: [
strategy: Cluster.Strategy.Epmd,
config: [hosts: [:"[email protected]", :"[email protected]"]],
]
]
children = [
{Cluster.Supervisor, [topologies, [name: MyApp.ClusterSupervisor]]},
..other children..
]
Supervisor.start_link(children, strategy: :one_for_one, name: MyApp.Supervisor)
end
end
The `topologies` configuration structure shown above can be built manually,
like shown, so that you can load config at runtime in a way that best
suits your application; or if you don't need to do any special config
handling, you can use the Mix config file, and just use
`Application.get_env(:libcluster, :topologies)`. That config would look like so:
config :libcluster,
topologies: [
example: [...]
]
Use the method most convenient for you.
"""
use Supervisor
@doc """
Start a new instance of this supervisor. This is the callback indicated in
the child specification returned by `child_spec/1`. It expects a list of
the form `[config, supervisor_opts]`, or `[config]`. The former allows you
to provide options for the supervisor like with `Supervisor.start_link/3`.
"""
def start_link([_config, opts] = args) do
Supervisor.start_link(__MODULE__, args, opts)
end
def start_link([config]) do
start_link([config, []])
end
@doc false
@impl Supervisor
def init([config, opts]) do
opts = Keyword.put(opts, :strategy, :one_for_one)
children = get_configured_topologies(config)
Supervisor.init(children, opts)
end
defp get_configured_topologies(config) do
for {topology, spec} <- config do
strategy = Keyword.fetch!(spec, :strategy)
state = build_initial_state([{:topology, topology} | spec])
%{
id: state.topology,
start: {strategy, :start_link, [[state]]}
}
end
end
defp build_initial_state(spec) do
topology = Keyword.fetch!(spec, :topology)
config = Keyword.get(spec, :config, [])
connect_mfa = Keyword.get(spec, :connect, {:net_kernel, :connect_node, []})
disconnect_mfa = Keyword.get(spec, :disconnect, {:erlang, :disconnect_node, []})
list_nodes_mfa = Keyword.get(spec, :list_nodes, {:erlang, :nodes, [:connected]})
%Cluster.Strategy.State{
topology: topology,
connect: connect_mfa,
disconnect: disconnect_mfa,
list_nodes: list_nodes_mfa,
config: config,
meta: nil
}
end
end