How to Create And Supervise Processes In Erlang OTP?

13 minutes read

Creating and supervising processes in Erlang/OTP involves using the built-in mechanisms provided by OTP to ensure fault tolerance and scalability in distributed systems. Here is an overview of the process creation and supervision in Erlang/OTP:

  1. Process Creation: In Erlang, processes are lightweight and isolated units of computation. They communicate by sending messages to each other. To create a process, you use the spawn/1 function, which takes a module or a function as an argument and returns the process identifier (PID) of the newly created process.
  2. Linking Processes: By default, Erlang processes are not linked. When a process exits normally or abnormally, it does not affect other processes in the system. However, you can establish a mutual link between two processes using the link/1 function. Upon linking, if one process terminates, it will cause the other linked processes to also terminate.
  3. Supervision Trees: OTP introduces supervision trees to manage the lifecycle of processes. A supervision tree is a hierarchical structure where processes are organized into supervisors and workers. The supervisors are responsible for supervising child processes and restarting them in case of failures.
  4. OTP Behaviors: OTP provides behaviors that abstract away common patterns of process creation and supervision. The most commonly used behavior is gen_server, which follows the client-server pattern. It helps in creating a server process that handles requests and maintains its state.
  5. Supervision Strategies: OTP offers different supervision strategies to define how child processes should be restarted upon failures. The two most common strategies are "one for one" and "one for all". In the "one for one" strategy, only the failed process is restarted, whereas in the "one for all" strategy, all child processes are restarted when one fails.
  6. Restarts and Backoff: OTP provides settings for restart intensity and restart interval to control how processes are restarted after failures. The restart intensity defines the number of restarts allowed within a specified interval before escalating to a higher hierarchy level. The restart interval determines the time interval within which restarts are counted.
  7. Error Kernel and Application Supervisors: At the top of the supervision tree, there are system-level supervisors like the error kernel supervisor and application supervisors. These supervisors are responsible for monitoring and restarting top-level supervisors and applications, respectively.
  8. OTP Releases: OTP also supports release handling, which enables you to bundle and manage the whole system as a release. A release includes the entire Erlang runtime system along with applications, libraries, and dependencies. It simplifies the deployment and upgrade processes.


By leveraging Erlang/OTP's process creation and supervision mechanisms, you can build fault-tolerant, scalable, and resilient distributed systems.

Best Erlang Books to Read in 2024

1
Handbook of Neuroevolution Through Erlang

Rating is 5 out of 5

Handbook of Neuroevolution Through Erlang

2
Designing for Scalability with Erlang/OTP: Implement Robust, Fault-Tolerant Systems

Rating is 4.9 out of 5

Designing for Scalability with Erlang/OTP: Implement Robust, Fault-Tolerant Systems

3
Learn You Some Erlang for Great Good!: A Beginner's Guide

Rating is 4.8 out of 5

Learn You Some Erlang for Great Good!: A Beginner's Guide

4
Erlang Programming: A Concurrent Approach to Software Development

Rating is 4.7 out of 5

Erlang Programming: A Concurrent Approach to Software Development

5
Introducing Erlang: Getting Started in Functional Programming

Rating is 4.6 out of 5

Introducing Erlang: Getting Started in Functional Programming

6
Erlang and OTP in Action

Rating is 4.5 out of 5

Erlang and OTP in Action

7
Programming Erlang: Software for a Concurrent World

Rating is 4.4 out of 5

Programming Erlang: Software for a Concurrent World

8
Programming Erlang: Software for a Concurrent World (Pragmatic Programmers)

Rating is 4.3 out of 5

Programming Erlang: Software for a Concurrent World (Pragmatic Programmers)


How to implement a one-for-one restart strategy in Erlang OTP?

To implement a one-for-one restart strategy in Erlang OTP, you need to follow these steps:

  1. Define a supervisor module: Create a supervisor module using the supervisor behavior from the supervisor Erlang module. Define its behavior by implementing the init/1 and terminate/2 callback functions.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
-module(my_supervisor).
-behaviour(supervisor).

%% init/1 is called to initialize the supervisor
init([]) ->
    RestartStrategy = one_for_one,  % Set the restart strategy
    MaxRestarts = 5,                % Set the maximum restarts allowed within the RestartPeriod
    RestartPeriod = 1800,           % Set the restart period in seconds
    % Create a list of child specifications
    Children = [
        worker_1,
        worker_2,
        % ...
    ],
    % Start the supervisor with the defined settings and children
    {ok, {RestartStrategy, MaxRestarts, RestartPeriod}, Children}.

%% terminate/2 is called when the supervisor is shutting down
terminate(_Reason, _State) ->
    ok.


  1. Define child worker modules: Create child worker modules that implement the gen_server behavior or any other behavior your workers require. Define the init/1 and terminate/2 callback functions in the worker modules as well.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
-module(worker_1).
-behaviour(gen_server).

%% Implementation of gen_server callbacks

init([]) ->
    % Your initialization code here
    {ok, WorkerState}.

%% ...

terminate(_Reason, _State) ->
    % Your termination code here
    ok.


  1. Start the supervisor: In your application's top-level module, start the supervisor by calling the supervisor:start_link/3 function with the supervisor module as the argument.
1
2
3
4
5
-module(my_app).
-export([start/0]).

start() ->
    {ok, _} = supervisor:start_link({local, my_supervisor}, my_supervisor, []).


When the supervisor starts, it will start the child workers according to the defined list of children. If any worker process terminates abnormally (e.g., crashes or exceeds restart limits), the supervisor will automatically restart only that specific worker process, according to the defined one-for-one restart strategy.


How to create a gen_fsm process in Erlang OTP?

To create a gen_fsm process in Erlang OTP, you need to follow these steps:

  1. Start by creating a new module that will implement the behavior of the gen_fsm process. The module should use the gen_fsm behavior and define the callback functions required by that behavior.
1
2
3
4
5
-module(my_fsm).
-behavior(gen_fsm).

%% Callback functions
-export([init/1, state_name/2, handle_event/3, handle_sync_event/4, handle_info/3, handle_timeout/3, terminate/3, code_change/4]).


  1. Define the initial state of your finite state machine (FSM) in the init/1 callback function. The init/1 function is responsible for initializing the FSM's state and setting up any necessary resources.
1
2
init(_) ->
    {ok, idle, undefined}.


  1. Define the individual states of your FSM in the state_name/2 callback function. This function maps the state names to atoms, allowing you to refer to states by name instead of atom.
1
2
3
4
state_name(idle, idle) ->
    idle;
state_name(running, Running) ->
    Running.


  1. Implement the logic for handling events, both asynchronous and synchronous, in the respective callback functions handle_event/3 and handle_sync_event/4. These functions are responsible for processing events and deciding on state transitions.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
handle_event(Event, State, Data) ->
    case {Event, State} of
        {start, idle} ->
            {next_state, running, Data};
        {stop, running} ->
            {next_state, idle, Data}
    end.

handle_sync_event(Event, From, State, Data) ->
    case {Event, State} of
        {get_state, _, running} ->
            {reply, running, State, Data};
        {get_state, _, idle} ->
            {reply, idle, State, Data}
    end.


  1. Implement the logic for handling non-state-specific events in the handle_info/3 callback function. This function is responsible for handling events that are not tied to a specific state.
1
2
handle_info(_Info, State, Data) ->
    {noreply, State, Data}.


  1. Implement the logic for handling timeouts in the handle_timeout/3 callback function. This function is responsible for defining the behavior of the FSM when a timeout occurs.
1
2
3
handle_timeout(_Timeout, State, Data) ->
    %% Handle timeout logic here
    {noreply, State, Data}.


  1. Implement the logic for cleaning up any resources or processes associated with the FSM in the terminate/3 callback function.
1
2
terminate(_Reason, _State, _Data) ->
    ok.


  1. Optionally, implement the code_change/4 callback function if you need to handle code change operations for your FSM.
1
2
code_change(_OldVsn, State, Data, _Extra) ->
    {ok, State, Data}.


  1. Finally, start your gen_fsm process by calling the gen_fsm:start_link/3 or gen_fsm:start/3 function, passing your module name and any additional parameters required by your FSM.
1
gen_fsm:start_link({local, my_fsm}, my_fsm, [], []).


That's it! You've created a gen_fsm process in Erlang OTP.


What is selective message receive in Erlang OTP?

Selective message receive in Erlang OTP refers to the ability for a process to selectively receive certain types of messages while ignoring others. This feature is provided by the selective receive construct, which allows an Erlang process to handle specific message patterns rather than processing messages in the order they arrive.


Selective message receive is achieved using the "receive" keyword along with pattern matching. In a selective receive block, an Erlang process can match and handle messages that conform to a particular pattern, while ignoring other types of messages that do not match any pattern.


Here's an example:

1
2
3
4
5
6
receive
    {add, X, Y} ->
        io:format("Result: ~p~n", [X + Y]);
    {subtract, X, Y} ->
        io:format("Result: ~p~n", [X - Y])
end.


In the above code, the process will only handle messages that are in the form of either {add, X, Y} or {subtract, X, Y}. If a message with a different structure arrives, it will be ignored.


Selective message receive allows for better message handling and increased system efficiency as processes can only focus on specific message types they are interested in, while ignoring others, reducing unnecessary message processing overhead.


What is process linking in Erlang OTP?

Process linking in Erlang OTP is a mechanism for establishing a permanent relationship between two processes. When two processes are linked, if one of them terminates for any reason (such as an error or normal exit), the other process will also be terminated. This ensures that if one process goes down, its linked processes are also notified and can take appropriate action.


Linking can be established using the link/1 function in the erlang module, which takes the process identifier (PID) of the process to be linked as an argument. For example, to link process A to process B, you would call link(B) in process A. Linking can also be established implicitly when a process is spawned using the spawn_link/1 function, which creates a new process and establishes a link with the calling process.


Process linking is an integral part of the fault-tolerant design provided by the OTP framework. With process linking, if a critical process crashes, it can trigger a chain reaction of process terminations, ensuring that the entire system is gracefully shut down. It is commonly used in supervision trees, where linked processes are managed by a supervisor process that monitors and restarts them as needed.


What is a supervisor tree in Erlang OTP?

In Erlang OTP (Open Telecom Platform), a supervisor tree is a hierarchical structure used to manage and monitor a set of Erlang processes. It is a key component of Erlang's fault-tolerance and self-healing capabilities.


A supervisor tree consists of nodes representing supervisors and workers. A supervisor is responsible for managing and supervising a group of child processes (workers). If a worker process fails, the supervisor can restart or terminate it, ensuring that the system remains functional.


Supervisors in a supervisor tree are organized in a hierarchical manner, where higher-level supervisors supervise lower-level supervisors, forming a tree-like structure. If a worker process fails and cannot be restarted by its direct supervisor, the failure is escalated up the supervisor tree until a suitable supervisor can handle it.


This hierarchical structure allows for a cascading failure handling mechanism, where supervisors at higher levels can detect and respond to failures in their child supervisors or workers. In this way, the supervisor tree provides fault tolerance and error recovery capabilities, ensuring the system's reliability and availability.


The supervisor tree is a fundamental concept in Erlang's OTP framework and is widely used to build fault-tolerant and highly reliable distributed systems.

Facebook Twitter LinkedIn Telegram Whatsapp Pocket

Related Posts:

Working with processes and concurrency in Erlang is a fundamental aspect of the language that enables robust and scalable applications. Erlang's lightweight process model allows for the creation of thousands or even millions of concurrent processes. Here&#...
Concurrency in Erlang is a powerful feature that allows multiple processes to execute simultaneously and independently. Here are some guidelines to correctly use concurrency in Erlang:Processes: Erlang uses lightweight processes, also known as green threads, t...
To create Erlang views in CouchDB, you need to perform the following steps:Install Erlang: Erlang is a programming language that is commonly used to create CouchDB views. You need to install the Erlang runtime environment on your system before you can create E...