OLTP is a small Erlang library that allows you to define and start OTP supervisors and workers (including GenServer-style processes) inline within a single module or file. It attempts to provide a simple API to declare child specs as raw MFA tuples, wrapping them under the hood with OTP's native supervisor and gen_server behaviors.
Note: This is still WIP.
- Inline Child Specs: Define workers and supervisors in any module without creating separate callback modules.
- Supervisor API:
sup_start_link/1,sup_start_child/2,sup_terminate_child/2,sup_restart_child/2. - GenServer API:
genserver_start_link/2,genserver_call/2,genserver_cast/2.
-record(oltp_child, {
name, %% process name or identifier
start_fun, %% {M,F,Args}
restart = permanent,%% permanent | transient | temporary
shutdown = 5000, %% milliseconds | brutal_kill
type = worker, %% worker | supervisor
modules = [] %% list of modules for code-change
}).
-record(oltp_gs_spec, {
init_fun, %% fun() -> {ok, State} | ignore | {stop,Reason}
handle_call_fun, %% fun(Request, From, State) -> ...
handle_cast_fun, %% fun(Msg, State) -> ...
handle_info_fun, %% fun(Info, State) -> ...
terminate_fun, %% fun(Reason, State) -> ok
code_change_fun %% fun(OldVsn, State, Extra) -> {ok,NewState}
}).%% Start a supervisor with default one_for_one strategy:
{ok, SupPid} = oltp:sup_start_link([ChildSpec1, ChildSpec2]).
%% Here, ChildSpec1 and ChildSpec2 were #olt_child{name = counter1, …} etc.
%% To terminate or restart them, you reference the same 'name':
oltp:sup_terminate_child(SupPid, counter1).
oltp:sup_restart_child(SupPid, counter1).
%% Start with custom strategy or registration:
{ok, SupPid} =
oltp:sup_start_link(
{local, my_sup},
{{one_for_all, 5, 10}, [ChildSpec]}
).
%% Dynamically add/terminate/restart children:
oltp:sup_start_child(SupPid, NewChildSpec).
oltp:sup_terminate_child(SupPid, NewChildId).
oltp:sup_restart_child(SupPid, NewChildId).%% Define a GenServer spec inline:
Spec = #oltp_gs_spec{
init_fun = fun() -> {ok, #{}} end,
handle_call_fun = fun({get,Key}, _From, S) -> {reply, maps:get(Key,S), S} end,
handle_cast_fun = fun({put,K,V}, S) -> {noreply, maps:put(K,V,S)} end,
handle_info_fun = fun(_,_)-> {noreply,State} end,
terminate_fun = fun(_,_)-> ok end,
code_change_fun = fun(_Old,State,_Extra)-> {ok,State} end
}.
%% Start and interact:
{ok, Pid} = oltp:genserver_start_link({local, my_server}, Spec).
oltp:genserver_call(my_server, {get, some_key}).
oltp:genserver_cast(my_server, {put, some_key, 42}).-module(my_app).
-export([start/0, stop/0]).
-include("oltp.hrl").
start() ->
%% Define two counter workers inline:
Spec = #oltp_gs_spec{ ... }.
C1 = #oltp_child{
name = ctr1,
start_fun = {oltp, genserver_start_link, [{local, ctr1}, Spec]}
},
C2 = #oltp_child{
name = ctr2,
start_fun = {oltp, genserver_start_link, [{local, ctr2}, Spec]}
},
%% Start supervisor:
{ok, Sup} = oltp:sup_start_link({simple_one_for_one,0,1}, [C1,C2]),
register(my_sup, Sup),
ok.
stop() ->
supervisor:stop(my_sup).