Skip to content

Instantly share code, notes, and snippets.

@rlb3
Last active December 22, 2022 03:07
Show Gist options
  • Save rlb3/4630eb7b1e2d816e107777a25ac6e155 to your computer and use it in GitHub Desktop.
Save rlb3/4630eb7b1e2d816e107777a25ac6e155 to your computer and use it in GitHub Desktop.

Manager Architecture

Mix.install([
  {:kino, "~> 0.7.0"}
])

Worker

defmodule Worker do
  use GenServer

  def child_spec(pid) do
    %{
      id: Worker,
      start: {Worker, :start_link, [pid]},
      restart: :transient
    }
  end

  defp via(pid) do
    {:via, Registry, {WorkerRegistry, pid}}
  end

  def start_link(pid) do
    GenServer.start_link(__MODULE__, pid, name: via(pid))
  end

  def init(pid) do
    IO.inspect("WORKER")
    :timer.send_interval(1000, self(), :reply) |> IO.inspect()
    {:ok, %{manager_pid: pid}}
  end

  def handle_info(:reply, %{manager_pid: pid} = state) do
    result = :rand.uniform(10)
    send(pid, {:result, result})
    {:noreply, state}
  end
end
defmodule MySupervisor do
  use Supervisor

  def start_link do
    start_link([])
  end

  def start_link(_) do
    Supervisor.start_link(__MODULE__, [], name: MySupervisor)
  end

  def init(_) do
    children = [
      {Registry, keys: :unique, name: WorkerRegistry},
      {DynamicSupervisor, name: WorkerSupervisor},
      {Manager, []}
    ]

    Supervisor.init(children, strategy: :one_for_one)
  end
end

Manager

defmodule Manager do
  use GenServer

  def start_link(_) do
    GenServer.start_link(__MODULE__, [], name: __MODULE__)
  end

  def init(_) do
    state =
      case DynamicSupervisor.start_child(WorkerSupervisor, Worker.child_spec(self())) do
        {:ok, pid} ->
          IO.inspect(pid, label: "WORKER")
          Process.monitor(pid)
          %{worker: pid}

        err ->
          IO.inspect(err, label: "ERROR")
          %{}
      end

    {:ok, state}
  end

  def handle_info({:result, result}, state) do
    IO.inspect(result, label: "RESULTS")
    {:noreply, state}
  end

  def handle_info({:DOWN, ref, :process, pid, _}, %{worker: pid} = state) do
    Process.demonitor(ref)
    IO.inspect("Worker Down: #{inspect(pid)}")
    {:noreply, state}
  end
end
{:ok, sup} = MySupervisor.start_link()
sup
MySupervisor
case Manager.start_link([]) do
  {:ok, pid} -> pid
  {:error, {:already_started, pid}} -> pid
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment