%% Copyright (c) 2026 Benoit Chesneau. Licensed under the MIT License.
%% See the LICENSE file at the project root.
%%
-module(erllama_model_sup).
-moduledoc """
Dynamic supervisor for `erllama_model` gen_statems. Each loaded
model is one child started via `start_model/2`. simple_one_for_one
strategy: children are spawned on demand from a single child spec.
""".
-behaviour(supervisor).
-export([start_link/0, start_model/2, stop_model/1, models/0]).
-export([init/1]).
-define(SERVER, ?MODULE).
-spec start_link() -> {ok, pid()} | {error, term()}.
start_link() ->
supervisor:start_link({local, ?SERVER}, ?MODULE, []).
-doc """
Start a model under this supervisor. ModelId is a binary; the model
registers itself in `erllama_registry` under that key. Returns the
started pid.
""".
-spec start_model(binary(), map()) -> {ok, pid()} | {error, term()}.
start_model(ModelId, Config) when is_binary(ModelId), is_map(Config) ->
supervisor:start_child(?SERVER, [ModelId, Config]).
-doc "Terminate a previously started model.".
-spec stop_model(binary() | pid()) -> ok | {error, term()}.
stop_model(ModelOrPid) ->
case pid_of(ModelOrPid) of
undefined -> {error, not_found};
Pid -> supervisor:terminate_child(?SERVER, Pid)
end.
-doc "List currently-supervised model pids (raw supervisor view).".
-spec models() -> [{undefined, pid(), worker, [module()]}].
models() ->
supervisor:which_children(?SERVER).
init([]) ->
SupFlags = #{
strategy => simple_one_for_one,
intensity => 5,
period => 30
},
Child = #{
id => erllama_model,
%% temporary: a model that crashes in init / first call (bad
%% path, OOM, unsupported quant) will keep crashing the same
%% way. Auto-restarting drains the supervisor intensity budget
%% and cascades up the tree. Failed loads stay dead; the
%% caller surfaces the error and re-loads explicitly.
start => {erllama_model, start_link, []},
restart => temporary,
shutdown => 5000,
type => worker,
modules => [erllama_model]
},
{ok, {SupFlags, [Child]}}.
pid_of(Pid) when is_pid(Pid) -> Pid;
pid_of(ModelId) when is_binary(ModelId) -> erllama_registry:whereis_name(ModelId).