Yet Another Sum-it-up on the Erlang/OTP basics.
Basics of the Open Telecom Platform.
Кроме непосредственно языка Erlang есть платформа Open Telecom Platform (OTP). Об основных принципах разработки с использованием OTP можно прочесть здесь.
Если коротоко, то OTP – это набор приципов структурирования кода с использованием деревьев контроля, в которые входят супервизоры и рабочие. В корне дерева контроля находится один большой и главный супервизор, который контролирует ход выполнения своих потомков, которые, в свою очередь, могут быть либо супервизорами, либо работниками (как правило — листья дерева контроля). Поведение первых и, зачастую, поведение вторых описывают с использованием общих паттернов. Идея таких паттернов заключается в разнесении кода модуля на две части. Одна из этих частей содержит код общий для всех модулей с таким поведением, другая — код, специфичный для данного модуля. Специфичная для данного приложения часть кода содержит реализацию коллбеков. Множество коллбеков является строго определенным для каждого типа поведений.
Рассмотрим данную концепцию на примере поведения Generic Server и Supervisor.
Маны говорят нам, какие функции в модуле паттерна вызывают какие функции из модуля коллбеков.
gen_server:start_link -----> Module:init/1
gen_server:call
gen_server:multi_call -----> Module:handle_call/3
gen_server:cast
gen_server:abcast -----> Module:handle_cast/2
- -----> Module:handle_info/2
- -----> Module:terminate/2
- -----> Module:code_change/3
Функция
start_link(Module, Args, Options) -> Result
Аргумент Module — имя модуля, содержащего коллбеки.
Args — список аргументов, который будет передан в функцию Module:init/1.
порождает процесс с поведением gen_server. Данный процесс становится частью дерева контроля. Далее он вызывает функцию инициализации из модуля коллбеков (Module:init/1).
Серверу возможно посылать синхронные и асинхронные запросы. Синхронные запросы осуществляются с помощью вызова функции gen_server:call(ServerRef, Request). ServerRef идентифицирует сервер, которому посылается этот запрос. Request — любая структура языка Erlang, которая будет обработана коллбеком handle_call данного сервера.
Supervisor.
Процесс супервизора создается при вызове функции start_link() и
становится частью дерева контроля. Рассмотрим вариант этой функции
start_link(Module, Args). Module — имя модуля, содержащего набор
коллбеков супервизора. Args — список аргументов, которые будут переданы
функции Module:init/1. Данная функций должна возвращать набор {ok,
{{RestartStrategy, MaxR, MaxT},[ChildSpec]}}, где RestartStrategy —
стратегия перезапуска упавших потомков, Childspec — описание потомков.
Рассмотрим пример из супервизора, котролирующего сервер.
Сервер:
-behaviour(gen_server).
-export([start_link/0]).
-export([init/1,handle_call/3,handle_cast/2]).
%% let's start a server and register it locally
%% with the name 'testotp_ser'.
start_link() ->
gen_server:start_link({local,testotp_ser},
testotp_ser,[],[]).
init(_Args) ->
{ok,ok}.
handle_call(test,_From,Chs) ->
io:format("This is a handle_call~n",[]),
{reply,Chs,Chs}.
handle_cast({test_cast,Ch},Chs) ->
io:format("This is handle_cast~n",[]),
{noreply,Chs}.
Соберем и запустим этот пример:
2> c(testotp_sup).
3> testotp_sup:start_link().
4> gen_server:call(testotp_ser,test).
This is a handle_call
ok
5> gen_server:cast(testotp_ser,{test_cast,a}).
This is handle_cast
ok
Sum it up.
Итак, основная часть идеи OTP состоит в построении деревьев контроля и в использовании поведений. При использовании поведений необходимо просто реализовать специфичную для данного модуля функциональность в в виде набора коллбеков. Общую для всех приложений часть поведения берет на себя система. При правильном использовании OTP вы получите надежный, хорошо читаемый код. В следющий раз мы поговорим о системе релизов в OTP. Удачи!

