defmodule SpawnSdk.System.Supervisor do @moduledoc """ Documentation for `System.Supervisor`. Start Supervisor tree like this: defmodule MyApp.Application do use Application @impl true def start(_type, _args) do children = [ { SpawnSdk.System.Supervisor, system: "my-system", actors: [MyActor] } ] opts = [strategy: :one_for_one, name: MyApp.Supervisor] Supervisor.start_link(children, opts) end """ use Supervisor alias Actors.Config.PersistentTermConfig, as: Config @impl true def init(opts) do Config.load() unless _system = opts[:system] do raise ArgumentError, "expected :system option to be given" end unless _actors = opts[:actors] do raise ArgumentError, "expected :actors option to be given" end system = Keyword.get(opts, :system) actors = Keyword.get(opts, :actors) extenal_subscribers = Keyword.get(opts, :extenal_subscribers, []) if Config.get(:actor_system_name) != system do raise ArgumentError, "configured system (#{inspect(system)}) is different from env PROXY_ACTOR_SYSTEM_NAME (#{Config.get(:actor_system_name)})" end start_persisted_system(system) children = [ {Sidecar.Supervisor, []}, %{ id: :spawn_system_register_task, start: {Task, :start_link, [ fn -> Process.flag(:trap_exit, true) SpawnSdk.System.SpawnSystem.register(system, actors) receive do {:EXIT, _pid, _reason} -> :persistent_term.erase(system) :ok end end ]} } ] ++ extenal_subscribers Supervisor.init(children, strategy: :one_for_one) end def start_link(state) do Supervisor.start_link( __MODULE__, state, shutdown: 120_000, strategy: :one_for_one ) end defp start_persisted_system(system) do if :persistent_term.get(system, false) do raise "System already registered" else :persistent_term.put(system, true) :ets.new(:"#{system}:actors", [:public, :named_table, read_concurrency: true]) end end end