gen_server is the workhorse OTP behavior -- it's the primary OTP interface to Erlang processes.
:doc:`e2_service <services>` is the equivalent in e2.
e2_service
is identical to gen_server
under the covers -- it is a
gen_server
behavior. The additional overhead in using an e2 service is the
cost of an additional functional call for each gen_server
operation.
e2_service
differs from gen_server
as follows:
init/1
andterminate/2
are optional in e2handle_call/3
,handle_cast/2
, andhandle_info/2
are consolidated into a singlehandle_msg/3
callback in e2e2_service
does not supportcode_change/3
[1]
The minimum foot print of gen_server
looks like this:
.. literalinclude:: gen_server_skel.erl :language: erlang
The minimum foot print of e2_service
looks like this:
.. literalinclude:: e2_service_skel.erl :language: erlang
The application OTP behavior is represented by the :doc:`e2_application <applications>` behavior.
e2_application
implicitly uses a top-level supervisor rather than require a
separate module. e2 application modules provide the top level list of
supervised child specs.
In OTP, applications typically start the top level supervisor.
An :doc:`e2 task <tasks>` is a type of sevice that runs actively after it's
started. It's a cleaner alternative to this pattern used in gen_server
behaviors:
start_link() ->
gen_server:start_link({local, ?MODULE}, []).
init(Args) ->
{ok, init_state(Args), 0}.
handle_info(timeout, State) ->
%% TODO: start my task here
{stop, normal, State}.
Returning 0 for the timeout value in init/1
will cause gen_server
to
call handle_info/2
with a timeout
message before processing any
messages sent to the process from external sources. This can be used to start
process work immediately after init/1
returns without the risk of receiving
unwanted messages.
In e2, this is handled with the task behavior:
start_link() ->
e2_task:start_link(?MODULE, []).
init(Args) ->
{ok, init_state(Args)}.
handle_task(State) ->
%% TODO: start my task here
{stop, normal, State}.
Task supervisors in e2 are simple_one_for_one
supervisors. This supervisor
restart strategy automatically removes children when they're completed, which
is typically the desired behavior when managing concurrently running tasks of a
particular type.
Footnotes
[1] | This will likely be exposed in the future. |