I have an umbrella application which contains a router and a number of different services. Currently everything is deployed as a single OTP release and on a single machine. Now I'm splitting everything apart to live on separate nodes.
A few of these services depend on each other for 1) testing purposes, 2) "public helper" functions are exposed for how to send messages to an erlang process. This works well when you want all of the services started on the same node, but what if you don't want to start the dependant application? Just listing the module in the .app
file will ensure that it is started.
Do people typically not depend on an application just to have access to those "public helper" functions? Here is an example to try and explain what I mean:
%
% Public API
%
helper_function(Pid) ->
gen_server:call(Pid, secret_message).
%
% GenServer callbacks
%
handle_call(secret_message, _, State) ->
{ok, [], State}.
So a few thoughts. In general, Erlang applications can be active or "library". Active applications have a supervision tree and can be started. Library applications either only contain support code or contain services that are intended to be started in the context of some other app's supervision tree.
But you can also have applications that can do both and there are a few ways of using an application that otherwise would be active without activating it if all you want is access to the code.
You can embed the behavior into the "dual purpose" app's supervisor and only actually start stuff (except for the top-level supervisor which is cheap) based on app config.
Probably the better approach is to use "included applications". This is a way of declaring a dependency in such a way that it will not be automatically started for you. You can either not start it at all or start it in the context of your own supervision tree -- because sometimes you don't want app1 and app2 to have separate supervision trees under the application master and rather want app2 to be part of app1's tree.