From c9ebb47d7ffecdae3acf22f71c257de8bcdcffdc Mon Sep 17 00:00:00 2001 From: Andrew Ruder Date: Thu, 18 Jan 2024 15:32:39 -0600 Subject: [PATCH] feat: ExMachina.start/2: return a supervisor from Application callback (#434) We're actually returning the PID for an Agent rather than a supervisor. In addition to being against the erlang callback spec: The function is to return {ok,Pid} or {ok,Pid,State}, where Pid is the pid of the top supervisor and State is any term. If omitted, State defaults to []. If the application is stopped later, State is passed to Module:prep_stop/1. Some tools like phoenix live dashboard will send the application supervisor supervisor-y messages and end up crashing the root application tree. ** (FunctionClauseError) no function clause matching in Agent.Server.handle_call/3 (elixir 1.14.5) lib/agent/server.ex:11: Agent.Server.handle_call(:which_children, {#PID<0.22073.22>, #Reference<0.3953567925.3593732098.137638>}, %{}) (stdlib 3.17) gen_server.erl:721: :gen_server.try_handle_call/4 (stdlib 3.17) gen_server.erl:750: :gen_server.handle_msg/6 (stdlib 3.17) proc_lib.erl:226: :proc_lib.init_p_do_apply/3 Last message (from #PID<0.22073.22>): :which_children This change makes ExMachina return a supervisor with a single child - the ExMachina.Sequence. Have also moved to `use Agent` to get the child_spec/1 for free in ExMachina.Sequence. This has been tested per the tool versions file (1.7.4 + otp 21). --- lib/ex_machina.ex | 7 ++++++- lib/ex_machina/sequence.ex | 4 +++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/lib/ex_machina.ex b/lib/ex_machina.ex index 04be659..a0b4fd0 100644 --- a/lib/ex_machina.ex +++ b/lib/ex_machina.ex @@ -16,7 +16,12 @@ defmodule ExMachina do @callback build_pair(factory_name :: atom, attrs :: keyword | map) :: list @doc false - def start(_type, _args), do: ExMachina.Sequence.start_link() + def start(_type, _args) do + Supervisor.start_link([ExMachina.Sequence], + strategy: :one_for_one, + name: __MODULE__.Supervisor + ) + end defmacro __using__(_opts) do quote do diff --git a/lib/ex_machina/sequence.ex b/lib/ex_machina/sequence.ex index 2268159..bbbbeb8 100644 --- a/lib/ex_machina/sequence.ex +++ b/lib/ex_machina/sequence.ex @@ -6,8 +6,10 @@ defmodule ExMachina.Sequence do sequential values instead of calling this module directly. """ + use Agent + @doc false - def start_link do + def start_link(_) do Agent.start_link(fn -> Map.new() end, name: __MODULE__) end