Powered by AppSignal & Oban Pro

Lesson 04 Livebook: Spawn Backoffice And Recruiter

04_spawn_backoffice_and_recruiter.livemd

Lesson 04 Livebook: Spawn Backoffice And Recruiter

Lesson 4 is where the studio stops just adding capability and starts adding a small reporting hierarchy.

Mix.install([
  {:spawn_backoffice_and_recruiter, path: "../04_spawn_backoffice_and_recruiter"}
])

Application.ensure_all_started(:spawn_backoffice_and_recruiter)

Helpers

defmodule Lesson04Helpers do
  alias SpawnBackofficeAndRecruiter.StudioJido

  def unique_agent_id(prefix) do
    "#{prefix}-#{System.unique_integer([:positive])}"
  end

  def wait_until(fun, attempts \\ 20)

  def wait_until(fun, attempts) when attempts > 0 do
    case fun.() do
      nil ->
        Process.sleep(50)
        wait_until(fun, attempts - 1)

      value ->
        value
    end
  end

  def wait_until(_fun, 0) do
    raise "condition was not met before the timeout"
  end

  def safe_stop_family(parent_id) do
    child_ids = ["#{parent_id}/backoffice", "#{parent_id}/recruiter"]

    Enum.each(child_ids, fn child_id ->
      case StudioJido.whereis(child_id) do
        nil -> :ok
        _pid -> StudioJido.stop_agent(child_id)
      end
    end)

    case StudioJido.whereis(parent_id) do
      nil -> :ok
      _pid -> StudioJido.stop_agent(parent_id)
    end
  end
end

Spawn The Support Team And Watch Reports Flow Back

alias Jido.AgentServer
alias Jido.Signal

alias SpawnBackofficeAndRecruiter.{
  CEOAgent,
  StudioJido
}

ceo_id = Lesson04Helpers.unique_agent_id("ceo")
{:ok, ceo_pid} = StudioJido.start_agent(CEOAgent, id: ceo_id)

{:ok, _ceo} =
  AgentServer.call(
    ceo_pid,
    Signal.new!("studio.support_team_requested", %{}, source: "/ceo")
  )

ceo_state =
  Lesson04Helpers.wait_until(fn ->
    {:ok, state} = AgentServer.state(ceo_pid)

    if Map.has_key?(state.children, :backoffice) and Map.has_key?(state.children, :recruiter) do
      state
    end
  end)

{:ok, _recruiter} =
  AgentServer.call(
    ceo_state.children.recruiter.pid,
    Signal.new!("recruiter.role_opened", %{role: "gameplay engineer"}, source: "/ceo")
  )

{:ok, _backoffice} =
  AgentServer.call(
    ceo_state.children.backoffice.pid,
    Signal.new!(
      "backoffice.hiring_review_requested",
      %{role: "gameplay engineer"},
      source: "/ceo"
    )
  )

updated_ceo_state =
  Lesson04Helpers.wait_until(fn ->
    {:ok, state} = AgentServer.state(ceo_pid)

    if state.agent.state.recruiting_updates != [] and state.agent.state.backoffice_updates != [] do
      state
    end
  end)

Lesson04Helpers.safe_stop_family(ceo_id)

%{
  child_ids: Map.new(updated_ceo_state.children, fn {tag, child} -> {tag, child.id} end),
  recruiting_updates: updated_ceo_state.agent.state.recruiting_updates,
  backoffice_updates: updated_ceo_state.agent.state.backoffice_updates
}