Current section

Files

Jump to
sagents lib sagents process_supervisor.ex
Raw

lib/sagents/process_supervisor.ex

defmodule Sagents.ProcessSupervisor do
@moduledoc """
Abstraction over dynamic supervisor implementations.
Supports two backends:
- `:local` — Elixir's `DynamicSupervisor` (single-node)
- `:horde``Horde.DynamicSupervisor` (distributed cluster)
## Configuration
# Single-node (default — no config needed)
config :sagents, :distribution, :local
# Distributed cluster
config :sagents, :distribution, :horde
# Horde options (optional)
config :sagents, :horde,
members: :auto,
distribution_strategy: Horde.UniformDistribution
"""
@compile {:no_warn_undefined,
[
Horde.DynamicSupervisor,
Sagents.Horde.AgentsSupervisorImpl,
Sagents.Horde.FileSystemSupervisorImpl
]}
@agent_supervisor_name Sagents.AgentsDynamicSupervisor
@filesystem_supervisor_name Sagents.FileSystem.FileSystemSupervisor
# ---------------------------------------------------------------------------
# Child Specs for Supervision Tree
# ---------------------------------------------------------------------------
@doc """
Returns the child spec for the agents dynamic supervisor.
Used in `Sagents.Application` supervision tree.
"""
def agents_supervisor_child_spec(opts \\ []) do
case distribution_type() do
:local ->
{DynamicSupervisor,
Keyword.merge([name: @agent_supervisor_name, strategy: :one_for_one], opts)}
:horde ->
assert_horde_available!()
Sagents.Horde.AgentsSupervisorImpl.child_spec(opts)
end
end
@doc """
Returns the child spec for the filesystem dynamic supervisor.
Used in `Sagents.Application` supervision tree.
"""
def filesystem_supervisor_child_spec(opts \\ []) do
case distribution_type() do
:local ->
{DynamicSupervisor,
Keyword.merge([name: @filesystem_supervisor_name, strategy: :one_for_one], opts)}
:horde ->
assert_horde_available!()
Sagents.Horde.FileSystemSupervisorImpl.child_spec(opts)
end
end
# ---------------------------------------------------------------------------
# Public API - Delegated Operations
# ---------------------------------------------------------------------------
@doc """
Start a child process under the specified supervisor.
"""
def start_child(supervisor_name, child_spec) do
supervisor_module().start_child(supervisor_name, child_spec)
end
@doc """
Terminate a child process.
"""
def terminate_child(supervisor_name, pid) do
supervisor_module().terminate_child(supervisor_name, pid)
end
@doc """
List all children of the specified supervisor.
"""
def which_children(supervisor_name) do
supervisor_module().which_children(supervisor_name)
end
@doc """
Count children of the specified supervisor.
"""
def count_children(supervisor_name) do
supervisor_module().count_children(supervisor_name)
end
@doc """
Returns the supervisor module (`DynamicSupervisor` or `Horde.DynamicSupervisor`).
"""
def supervisor_module do
case distribution_type() do
:local -> DynamicSupervisor
:horde -> Horde.DynamicSupervisor
end
end
@doc """
Returns the configured distribution type (`:local` or `:horde`).
"""
def distribution_type do
Application.get_env(:sagents, :distribution, :local)
end
# ---------------------------------------------------------------------------
# Internal
# ---------------------------------------------------------------------------
defp assert_horde_available! do
unless Code.ensure_loaded?(Horde.DynamicSupervisor) do
raise """
Sagents is configured to use Horde (config :sagents, :distribution, :horde)
but the :horde dependency is not available.
Add it to your mix.exs:
{:horde, "~> 0.10"}
"""
end
end
end