Overseer v0.1.0 Overseer behaviour View Source

Inspired by Supervisor, Overseer is used to start/monitor/interact/restart/terminate erlang nodes. We know that Supervisor can start workers with predefined MFA (Module, Function, Args). Similarly, Overseer can start nodes with predefined ARO (Adapter, Release and Options):

  • Adapter tells overseer how to spawn the node. It is provided in the term {adapter, opts}.
  • Release is a full path of a release tarball. Local file, S3 or https are supported. Overseer will load the release to the remote node once it is started.
  • Options could be: max_nodes, default 8, strategy, default :simple_one_for_one.

Once a new node is spawned and connected with overseer, overseer will monitor it and handles events posted by the node.

Supported Adapter

When Overseer is going to spawn a new node, it will call Adapter.start(opts). Client module need to choose the adapter they’re going to use and the opts for that adapter. Initially we will support two adapters: Overseer.Adapter.Local and Overseer.Adapter.EC2.

Overseer.Adapter.Local

Start new nodes in localhost. Options:

  • prefix: name prefix of the node.

Overseer.Adapter.EC2

bring up new EC2 instance to start the new nodes. Options:

  • prefix: name prefix of the node.
  • type: type of the instance.
  • spot?: start it as spot instance or not.
  • image: AMI for the instance.

Supported events

  • connected: a node successfully connected to overseer.
  • disconnected: if a node is DOWN, overseer will generate disconnected event. After a timeout that node didn’t connect to overseer, overseer will bring up a new node with same ARA.
  • loaded: if a node finished loading the release, overseer will generate loaded event.
  • paired: if a node finished pairing with overseer, overseer will generate paired event.
  • telemetry: telemetry data sent from node to overseer.
  • terminated: once overseer brings down a node, it will emit terminated event.

Supported strategy

Overseer supports :one_for_one and simple_one_for_one.

Examples

defmodule MyOverseer do
  use Overseer

  def start_link(children, opts) do
    Overseer.start_link(children, opts)
  end

  # One shall provide initial labor_state and global_state
  # later on only global_state are provided for handle_call / cast / info.
  # labor_state will be provided for labor event: handle_connected / disconnected / telemetry / etc.
  def init(state) do
    {:ok, labor_state, global_state}
  end

  def handle_connected(node, state) do

  end

  def handle_disconnected(node, state) do

  end

  def handle_telemetry(telemetry, state) do

  end

  def handle_telemetry(telemetry, state) do

  end

  def handle_terminated(node, state) do

  end
end

defmodule Application1 do
  use Application
  alias Overseer.Adapters.EC2

  def start(_type, _args) do
    children = [
      {Worker1, []),
      {MyOverseer, [node_spec, [name: MyOverseer1]]}
    ]

    opts = [strategy: :one_for_one, name: Application1.Supervisor]
    Supervisor.start_link(children, opts)
  end

  defp node_spec do
    adapter = {Overseer.Adapters.EC2, [
      prefix: "merlin",
      image: "ami-31bb8c7f",
      type: "c5.xlarge",
      spot?: true
    ]}

    opts = [
      strategy: :simple_one_for_one,
      max_nodes: 10
    ]

    {adapter, "merlin.tar.gz", opts}
  end
end

Link to this section Summary

Callbacks

Invoked when a remote node connected

Invoked when a remote node disconnected

Invoked when a remote node loaded the release

Invoked when a remote node paired with overseer

Invoked when a remote node sends telemetry report

Invoked when a remote node is terminated

Link to this section Functions

Link to this function handle_call(msg, from, data) View Source
Link to this function start_link(spec, options) View Source

Start overseer.

Example:

iex> adapter = {EC2,
      %{
        region: "us-west-1",
        zone: "us-west-1c",
        key_name: "adRise AWS",
        price: 0.15,
        image: "ami-eb19128b",
        instance_type: "c5.large",
        iam_role: "arn:aws:iam::370025973162:instance-profile/uapi",
        subnet: "subnet-81e344e4",
        security_groups: ["sg-f2432e94", "sg-780be81c"],
      }}

iex> release = {:release, "a.tar.gz", {Module, :pair}}

iex> opts = [
  strategy: :simple_one_for_one,
  max_nodes: 10
]
iex> Overseer.start_link({adapter, release, opts}, name: MyOverseer)
Link to this function start_link(mod, spec, options) View Source
Link to this function terminate_all_children(pid) View Source
Link to this function terminate_child(pid, node_name) View Source

Link to this section Callbacks

Link to this callback handle_connected(from, state) View Source (optional)
handle_connected(from :: node(), state :: term()) ::
  {:ok, term()} | {:error, term()}

Invoked when a remote node connected

Link to this callback handle_disconnected(from, state) View Source (optional)
handle_disconnected(from :: node(), state :: term()) ::
  {:ok, term()} | {:error, term()}

Invoked when a remote node disconnected

Link to this callback handle_loaded(from, state) View Source (optional)
handle_loaded(from :: node(), state :: term()) ::
  {:ok, term()} | {:error, term()}

Invoked when a remote node loaded the release

Link to this callback handle_paired(from, state) View Source (optional)
handle_paired(from :: node(), state :: term()) ::
  {:ok, term()} | {:error, term()}

Invoked when a remote node paired with overseer

Link to this callback handle_telemetry(telemetry, state) View Source
handle_telemetry(telemetry :: GenExecutor.Telemetry, state :: term()) ::
  {:ok, term()} | {:error, term()}

Invoked when a remote node sends telemetry report

Link to this callback handle_terminated(from, state) View Source (optional)
handle_terminated(from :: node(), state :: term()) ::
  {:ok, term()} | {:error, term()}

Invoked when a remote node is terminated