Elixir v1.6.5 Application behaviour View Source
A module for working with applications and defining application callbacks.
In Elixir (actually, in Erlang/OTP), an application is a component implementing some specific functionality, that can be started and stopped as a unit, and which can be re-used in other systems.
Applications are defined with an application file named APP.app
where
APP
is the application name, usually in underscore_case
. The application
file must reside in the same ebin
directory as the compiled modules of the
application. In Elixir, the Mix build tool is responsible for compiling your
source code and generating your application .app
file. You can learn more
about the generation of .app
files by typing mix help compile.app
.
Once your application is compiled, running your system is a matter of starting
your current application and its dependencies. Differently from other languages,
Elixir does not have a main
procedure that is responsible for starting your
system. Instead, you start one or more applications, each with their own
initialization and termination logic.
Applications also provide an “application environment”, which provides one mechanism for configuring long running applications. We will learn more about the tooling, start and shutdown and the application environment in the next sections.
Start and shutdown
Starting an application is done via the “application module callback”, which
is a module that defines the start/2
function. The start/2
function should
then start a supervisor, which is often called as the top-level supervisor, since
it sits at the root of a potentially long supervision tree. When the system is
shutting down, all applications shut down their top-level supervisor, which
terminates children in the opposite order they are started.
Shutting down a live system cleanly can be done by calling System.stop/1
.
It will shut down all applications in the opposite order they are started.
Each application will then shutdown its top-level supervisor, if one is
available, which then shuts down its children.
From Erlang/OTP 19.1, a SIGTERM from the operating system will automatically
translate to System.stop/0
. Erlang/OTP 20 gives user more explicit control
over OS signals via the :os.set_signal/2
function.
Application module callback
An application may start and stop a supervision tree when it boots via the application module callback.
The first step is to pass the module callback in the application definition
in the mix.exs
file:
def application do
[mod: {MyApp, []}]
end
Our application now requires the MyApp
module to provide an application
callback. This can be done by invoking use Application
in that module and
defining a start/2
callback, for example:
defmodule MyApp do
use Application
def start(_type, _args) do
children = []
Supervisor.start_link(children, strategy: :one_for_one)
end
end
start/2
typically returns {:ok, pid}
or {:ok, pid, state}
where
pid
identifies the supervision tree and state
is the application state.
args
is the second element of the tuple given to the :mod
option.
The type
argument passed to start/2
is usually :normal
unless in a
distributed setup where application takeovers and failovers are configured.
Distributed applications is beyond the scope of this documentation. For those
interested on the topic, please access the OTP documentation:
When an application is shutting down, its stop/1
callback is called after
the supervision tree has been stopped by the runtime. This callback allows the
application to do any final cleanup. The argument is the state returned by
start/2
, if it did, or []
otherwise. The return value of stop/1
is
ignored.
By using Application
, modules get a default implementation of stop/1
that ignores its argument and returns :ok
, but it can be overridden.
Application callback modules may also implement the optional callback
prep_stop/1
. If present, prep_stop/1
is invoked before the supervision
tree is terminated. Its argument is the state returned by start/2
, if it did,
or []
otherwise, and its return value is passed to stop/1
.
An application without a supervision tree doesn’t define an application
module callback in the application definition in mix.exs
file. Even though
there is no module with application callbacks such as start/2
and
stop/1
, the application can be started and stopped the same way as an
application with a supervision tree.
Tooling
The Mix build tool can also be used to start your applications. For example,
mix test
automatically starts your application dependencies and your application
itself before your test runs. mix run --no-halt
boots your current project and
can be used to start a long running system. See mix help run
.
Developers can also use tools like Distillery that build releases. Releases are able to package all of your source code as well as the Erlang VM into a single directory. Releases also give you explicit control over how each application is started and in which order. They also provide a more streamlined mechanism for starting and stopping systems, debugging, logging, as well as system monitoring.
Finally, Elixir provides tools such as escripts and archives, which are
different mechanisms for packaging your application. Those are typically used
when tools must be shared between developers and not as deployment options.
See mix help archive.build
and mix help escript.build
for more detail.
Application environment
Once an application is started, OTP provides an application environment that can be used to configure the application.
Assuming you are inside a Mix project, you can edit the application/0
function in the mix.exs
file to the following:
def application do
[env: [hello: :world]]
end
In the application function, we can define the default environment values
for our application. By starting your application with iex -S mix
, you
can access the default value:
Application.get_env(:APP_NAME, :hello)
#=> :world
Applications and dependencies in Mix projects are typically configured
via the config/config.exs
file. For example, someone using your
application can configure the :hello
key as follows:
config :APP_NAME, hello: :brand_new_world
Keep in mind configuration files are only useful to configure static
values. For example, if you need to configure your applications based
on the system environment, the file system or on database entries,
then those configurations are better placed at runtime. For example,
one may configure applications dynamically via put_env/3
.
Keep in mind that each application is responsible for its environment. Do not use the functions in this module for directly accessing or modifying the environment of other applications (as it may lead to inconsistent data in the application environment).
Link to this section Summary
Functions
Gets the directory for app
Returns the given path inside app_dir/1
Deletes the key
from the given app
environment
Ensures the given app
and its applications are started
Ensures the given app
is started
Returns the value for key
in app
’s environment in a tuple
Returns the value for key
in app
’s environment
Formats the error reason returned by start/2
,
ensure_started/2
, stop/1
, load/1
and unload/1
,
returns a string
Returns all key-value pairs for app
Gets the application for the given module
Returns the value for key
in app
’s environment
Loads the given app
Returns a list with information about the applications which have been loaded
Puts the value
in key
for the given app
Returns the spec for app
Returns the value for key
in app
’s specification
Starts the given app
Returns a list with information about the applications which are currently running
Stops the given app
Unloads the given app
Callbacks
Called before stopping the application
Called when an application is started
Start an application in synchronous phases
Called after an application has been stopped
Link to this section Types
Link to this section Functions
Gets the directory for app.
This information is returned based on the code path. Here is an example:
File.mkdir_p!("foo/ebin")
Code.prepend_path("foo/ebin")
Application.app_dir(:foo)
#=> "foo"
Even though the directory is empty and there is no .app
file
it is considered the application directory based on the name
“foo/ebin”. The name may contain a dash -
which is considered
to be the app version and it is removed for the lookup purposes:
File.mkdir_p!("bar-123/ebin")
Code.prepend_path("bar-123/ebin")
Application.app_dir(:bar)
#=> "bar-123"
For more information on code paths, check the Code
module in
Elixir and also Erlang’s :code
module.
Returns the given path inside app_dir/1
.
Deletes the key
from the given app
environment.
See put_env/4
for a description of the options.
ensure_all_started(app(), start_type()) :: {:ok, [app()]} | {:error, {app(), term()}}
Ensures the given app
and its applications are started.
Same as start/2
but also starts the applications listed under
:applications
in the .app
file in case they were not previously
started.
ensure_started(app(), start_type()) :: :ok | {:error, term()}
Ensures the given app
is started.
Same as start/2
but returns :ok
if the application was already
started. This is useful in scripts and in test setup, where test
applications need to be explicitly started:
:ok = Application.ensure_started(:my_test_dep)
Returns the value for key
in app
’s environment in a tuple.
If the configuration parameter does not exist, the function returns :error
.
Returns the value for key
in app
’s environment.
If the configuration parameter does not exist, raises ArgumentError
.
Formats the error reason returned by start/2
,
ensure_started/2
, stop/1
, load/1
and unload/1
,
returns a string.
Returns all key-value pairs for app
.
Gets the application for the given module.
The application is located by analyzing the spec
of all loaded applications. Returns nil
if
the module is not listed in any application spec.
Returns the value for key
in app
’s environment.
If the configuration parameter does not exist, the function returns the
default
value.
Loads the given app
.
In order to be loaded, an .app
file must be in the load paths.
All :included_applications
will also be loaded.
Loading the application does not start it nor load its modules, but it does load its environment.
Returns a list with information about the applications which have been loaded.
Puts the value
in key
for the given app
.
Options
:timeout
- the timeout for the change (defaults to5_000
milliseconds):persistent
- persists the given value on application load and reloads
If put_env/4
is called before the application is loaded, the application
environment values specified in the .app
file will override the ones
previously set.
The persistent option can be set to true
when there is a need to guarantee
parameters set with this function will not be overridden by the ones defined
in the application resource file on load. This means persistent values will
stick after the application is loaded and also on application reload.
Returns the spec for app
.
The following keys are returned:
:description
:id
:vsn
:modules
:maxP
:maxT
:registered
:included_applications
:applications
:mod
:start_phases
Note the environment is not returned as it can be accessed via
fetch_env/2
. Returns nil
if the application is not loaded.
Returns the value for key
in app
’s specification.
See spec/1
for the supported keys. If the given
specification parameter does not exist, this function
will raise. Returns nil
if the application is not loaded.
start(app(), start_type()) :: :ok | {:error, term()}
Starts the given app
.
If the app
is not loaded, the application will first be loaded using load/1
.
Any included application, defined in the :included_applications
key of the
.app
file will also be loaded, but they won’t be started.
Furthermore, all applications listed in the :applications
key must be explicitly
started before this application is. If not, {:error, {:not_started, app}}
is
returned, where app
is the name of the missing application.
In case you want to automatically load and start all of app
’s dependencies,
see ensure_all_started/2
.
The type
argument specifies the type of the application:
:permanent
- ifapp
terminates, all other applications and the entire node are also terminated.:transient
- ifapp
terminates with:normal
reason, it is reported but no other applications are terminated. If a transient application terminates abnormally, all other applications and the entire node are also terminated.:temporary
- ifapp
terminates, it is reported but no other applications are terminated (the default).
Note that it is always possible to stop an application explicitly by calling
stop/1
. Regardless of the type of the application, no other applications will
be affected.
Note also that the :transient
type is of little practical use, since when a
supervision tree terminates, the reason is set to :shutdown
, not :normal
.
Returns a list with information about the applications which are currently running.
Stops the given app
.
When stopped, the application is still loaded.
Unloads the given app
.
It will also unload all :included_applications
.
Note that the function does not purge the application modules.
Link to this section Callbacks
Called before stopping the application.
This function is called before the top-level supervisor is terminated. It
receives the state returned by start/2
, if it did, or []
otherwise.
The return value is later passed to stop/1
.
Called when an application is started.
This function is called when an application is started using
Application.start/2
(and functions on top of that, such as
Application.ensure_started/2
). This function should start the top-level
process of the application (which should be the top supervisor of the
application’s supervision tree if the application follows the OTP design
principles around supervision).
start_type
defines how the application is started:
:normal
- used if the startup is a normal startup or if the application is distributed and is started on the current node because of a failover from another node and the application specification key:start_phases
is:undefined
.{:takeover, node}
- used if the application is distributed and is started on the current node because of a failover on the nodenode
.{:failover, node}
- used if the application is distributed and is started on the current node because of a failover on nodenode
, and the application specification key:start_phases
is not:undefined
.
start_args
are the arguments passed to the application in the :mod
specification key (e.g., mod: {MyApp, [:my_args]}
).
This function should either return {:ok, pid}
or {:ok, pid, state}
if
startup is successful. pid
should be the PID of the top supervisor. state
can be an arbitrary term, and if omitted will default to []
; if the
application is later stopped, state
is passed to the stop/1
callback (see
the documentation for the stop/1
callback for more information).
use Application
provides no default implementation for the start/2
callback.
start_phase(phase :: term(), start_type(), phase_args :: term()) :: :ok | {:error, reason :: term()}
Start an application in synchronous phases.
This function is called after start/2
finishes but before
Application.start/2
returns. It will be called once for every start phase
defined in the application’s (and any included applications’) specification,
in the order they are listed in.
Called after an application has been stopped.
This function is called after an application has been stopped, i.e., after its
supervision tree has been stopped. It should do the opposite of what the
start/2
callback did, and should perform any necessary cleanup. The return
value of this callback is ignored.
state
is the state returned by start/2
, if it did, or []
otherwise.
If the optional callback prep_stop/1
is present, state
is its return
value instead.
use Application
defines a default implementation of this function which does
nothing and just returns :ok
.