SlideShare une entreprise Scribd logo
1  sur  86
Télécharger pour lire hors ligne
LEARN U ERLANG
WEEK6 - PRESENTED BY NOLLEH
DESIGNING A
CONCURRENT PROGRAM
CHAPTER.13
13. DESIGNING A CONCURRENT PROGRAM
UNDERSTANDING THE PROBLEM
▸ roles
▸ add event ( event contains deadline / name / desc )
▸ show an warning when time has comes up
▸ cancel event
▸ no persistent disk storage
▸ update while it is running
▸ interaction via command line
13. DESIGNING A CONCURRENT PROGRAM
UNDERSTANDING THE PROBLEM
▸ event server
▸ Accepts subscriptions from clients
▸ Forwards notifications from event processes to each of the subscribers
▸ Accepts messages to add events (and start the x, y, z processes
needed)
▸ Can accept messages to cancel an event and subsequently kill the
event processes
▸ Can be terminated by a client
▸ Can have its code reloaded via the shell.
13. DESIGNING A CONCURRENT PROGRAM
UNDERSTANDING THE PROBLEM
▸ client
▸ Subscribes to the event server and receive notifications as
messages. Each of these could potentially be a gateway to the
different interaction points mentioned above (GUI, web page,
instant messaging software, email, etc.)
▸ Asks the server to add an event with all its details
▸ Asks the server to cancel an event
▸ Monitors the server (to know if it goes down)
▸ Shuts down the event server if needed
13. DESIGNING A CONCURRENT PROGRAM
UNDERSTANDING THE PROBLEM
▸ x, y and z:
▸ Represent a notification waiting to fire (they're basically
just timers linked to the event server)
▸ Send a message to the event server when the time is up
▸ Receive a cancellation message and die
13. DESIGNING A CONCURRENT PROGRAM
UNDERSTANDING THE PROBLEM
▸ for real program,
▸ timer:send_after/2-3 to avoid spawning too many processes.
13. DESIGNING A CONCURRENT APPLICATION
DEFINING THE PROTOCOL
▸ subscribe
13. DESIGNING A CONCURRENT APPLICATION
DEFINING THE PROTOCOL
▸ add
13. DESIGNING A CONCURRENT APPLICATION
DEFINING THE PROTOCOL
▸ cancel
13. DESIGNING A CONCURRENT APPLICATION
DEFINING THE PROTOCOL
▸ notification
13. DESIGNING A CONCURRENT APPLICATION
DEFINING THE PROTOCOL
▸ shutdown
13. DESIGNING A CONCURRENT APPLICATION
DEFINING THE PROTOCOL
▸ notification
13. DESIGNING A CONCURRENT APPLICATION
DEFINING THE PROTOCOL
▸ cancel
13. DESIGNING A CONCURRENT APPLICATION
DEFINING THE PROTOCOL
▸ code change
13. DESIGNING A CONCURRENT APPLICATION
LAY THEM FOUNDATION
▸ project
▸ ebin/ (compiled)
▸ include/ (header)
▸ priv/ (executables that might have to interact with
Erlang, such as specific drivers and whatnot)
▸ src/ (private hrl, erl)
13. DESIGNING A CONCURRENT APPLICATION
AN EVENT MODULE
▸ project
▸ {Pid, Ref, Message}, where Pid is the sender and Ref is a
unique message identifier to help know what reply
came from who.
loop(State) ->
receive
{Server, Ref, cancel} ->
...
after Delay ->
...
end.
13. DESIGNING A CONCURRENT APPLICATION
AN EVENT MODULE
▸ state
▸ contains
▸ timeout / name of event / event server pid (for noti)
-module(event).
-compile(export_all).
-record(state, {server,
name="",
to_go=0}).
13. DESIGNING A CONCURRENT APPLICATION
AN EVENT MODULE
▸ state
▸ contains
▸ timeout / name of event / event server pid (for noti)
loop(S = #state{server=Server}) ->
receive
{Server, Ref, cancel} ->
Server ! {Ref, ok}
after S#state.to_go*1000 ->
Server ! {done, S#state.name}
end.
13. DESIGNING A CONCURRENT APPLICATION
AN EVENT MODULE
▸ test event
6> c(event).
{ok,event}
7> rr(event, state).
[state]
8> spawn(event, loop, [#state{server=self(), name="test", to_go=5}]).
<0.60.0>
9> flush().
ok
10> flush().
Shell got {done,"test"}
ok
13. DESIGNING A CONCURRENT APPLICATION
AN EVENT MODULE
▸ test event
▸ we don't expect it to come from anywhere specific (any place will do, we
won't match on the receive) nor should we want to reply to it
11> Pid = spawn(event, loop, [#state{server=self(), name=“test",
to_go=500}]).
<0.64.0>
12> ReplyRef = make_ref().
#Ref<0.0.0.210>
13> Pid ! {self(), ReplyRef, cancel}.
{<0.50.0>,#Ref<0.0.0.210>,cancel}
14> flush().
Shell got {#Ref<0.0.0.210>,ok}
ok
13. DESIGNING A CONCURRENT APPLICATION
AN EVENT MODULE
▸ limit of timer
15> spawn(event, loop, [#state{server=self(), name="test",
to_go=365*24*60*60}]).
<0.69.0>
16>
=ERROR REPORT==== DD-MM-YYYY::HH:mm:SS ===
Error in process <0.69.0> with exit value: {timeout_value,[{event,loop,
1}]}
13. DESIGNING A CONCURRENT APPLICATION
AN EVENT MODULE
▸ split it
▸ ex. 98*24*60*60+4 -> [4,4233600,4233600]
%% Because Erlang is limited to about 49 days (49*24*60*60*1000) in
%% milliseconds, the following function is used
normalize(N) ->
Limit = 49*24*60*60,
[N rem Limit | lists:duplicate(N div Limit, Limit)].
13. DESIGNING A CONCURRENT APPLICATION
AN EVENT MODULE
▸ split it
loop(S = #state{server=Server, to_go=[T|Next]}) ->
receive
{Server, Ref, cancel} ->
Server ! {Ref, ok}
after T*1000 ->
if Next =:= [] ->
Server ! {done, S#state.name};
Next =/= [] ->
loop(S#state{to_go=Next})
end
end.
13. DESIGNING A CONCURRENT APPLICATION
AN EVENT MODULE
▸ normalize helper
start(EventName, Delay) ->
spawn(?MODULE, init, [self(), EventName, Delay]).
start_link(EventName, Delay) ->
spawn_link(?MODULE, init, [self(), EventName, Delay]).
%%% Event's innards
init(Server, EventName, Delay) ->
loop(#state{server=Server,
name=EventName,
to_go=normalize(Delay)}).
13. DESIGNING A CONCURRENT APPLICATION
AN EVENT MODULE
▸ cancel helper
cancel(Pid) ->
%% Monitor in case the process is already dead
Ref = erlang:monitor(process, Pid),
Pid ! {self(), Ref, cancel},
receive
{Ref, ok} ->
erlang:demonitor(Ref, [flush]),
ok;
{'DOWN', Ref, process, Pid, _Reason} ->
ok
end.
13. DESIGNING A CONCURRENT APPLICATION
AN EVENT MODULE
▸ test
19> event:start("Event", 0).
<0.103.0>
20> flush().
Shell got {done,"Event"}
ok
21> Pid = event:start("Event", 500).
<0.106.0>
22> event:cancel(Pid).
ok
13. DESIGNING A CONCURRENT APPLICATION
AN EVENT MODULE
▸ I don’t want noti-time as second
time_to_go(TimeOut={{_,_,_}, {_,_,_}}) ->
Now = calendar:local_time(),
ToGo = calendar:datetime_to_gregorian_seconds(TimeOut) -
calendar:datetime_to_gregorian_seconds(Now),
Secs = if ToGo > 0 -> ToGo;
ToGo =< 0 -> 0
end,
normalize(Secs).
13. DESIGNING A CONCURRENT APPLICATION
AN EVENT MODULE
▸ init function using time_to_go
init(Server, EventName, DateTime) ->
loop(#state{server=Server,
name=EventName,
to_go=time_to_go(DateTime)}).
13. DESIGNING A CONCURRENT APPLICATION
THE EVENT SERVER
▸ skeleton
-module(evserv).
-compile(export_all).
loop(State) ->
receive
{Pid, MsgRef, {subscribe, Client}} ->
...
{Pid, MsgRef, {add, Name, Description, TimeOut}} ->
...
{Pid, MsgRef, {cancel, Name}} ->
...
13. DESIGNING A CONCURRENT APPLICATION
THE EVENT SERVER
▸ skeleton
{done, Name} ->
...
shutdown ->
...
{'DOWN', Ref, process, _Pid, _Reason} ->
...
code_change ->
...
Unknown ->
io:format("Unknown message: ~p~n",[Unknown]),
loop(State)
end.
13. DESIGNING A CONCURRENT APPLICATION
THE EVENT SERVER
▸ declare state
-record(state, {events, %% list of #event{} records
clients}). %% list of Pids
-record(event, {name="",
description="",
pid,
timeout={{1970,1,1},{0,0,0}}}).
13. DESIGNING A CONCURRENT APPLICATION
THE EVENT SERVER
▸ declare state
loop(S = #state{}) ->
receive
...
end.
init() ->
%% Loading events from a static file could be done here.
%% You would need to pass an argument to init telling where the
%% resource to find the events is. Then load it from here.
%% Another option is to just pass the events straight to the server
%% through this function.
loop(#state{events=orddict:new(),
clients=orddict:new()}).
13. DESIGNING A CONCURRENT APPLICATION
THE EVENT SERVER
▸ implement subscribe
{Pid, MsgRef, {subscribe, Client}} ->
Ref = erlang:monitor(process, Client),
NewClients = orddict:store(Ref, Client, S#state.clients),
Pid ! {MsgRef, ok},
loop(S#state{clients=NewClients});
13. DESIGNING A CONCURRENT APPLICATION
THE EVENT SERVER
▸ implement add event
valid_datetime({Date,Time}) ->
try
calendar:valid_date(Date) andalso valid_time(Time)
catch
error:function_clause -> %% not in {{Y,M,D},{H,Min,S}} format
false
end;
valid_datetime(_) ->
false.
13. DESIGNING A CONCURRENT APPLICATION
THE EVENT SERVER
▸ implement add event
valid_time({H,M,S}) -> valid_time(H,M,S).
valid_time(H,M,S) when H >= 0, H < 24,
M >= 0, M < 60,
S >= 0, S < 60 -> true;
valid_time(_,_,_) -> false.
13. DESIGNING A CONCURRENT APPLICATION
THE EVENT SERVER
▸ implement add event
{Pid, MsgRef, {add, Name, Description, TimeOut}} ->
case valid_datetime(TimeOut) of
true ->
EventPid = event:start_link(Name, TimeOut),
NewEvents = orddict:store(Name,
#event{name=Name,
description=Description,
pid=EventPid,
timeout=TimeOut},
S#state.events),
Pid ! {MsgRef, ok},
loop(S#state{events=NewEvents});
13. DESIGNING A CONCURRENT APPLICATION
THE EVENT SERVER
▸ implement add event
false ->
Pid ! {MsgRef, {error, bad_timeout}},
loop(S)
end;
13. DESIGNING A CONCURRENT APPLICATION
THE EVENT SERVER
▸ implement cancel event
{Pid, MsgRef, {cancel, Name}} ->
Events = case orddict:find(Name, S#state.events) of
{ok, E} ->
event:cancel(E#event.pid),
orddict:erase(Name, S#state.events);
error ->
S#state.events
end,
Pid ! {MsgRef, ok},
loop(S#state{events=Events});
13. DESIGNING A CONCURRENT APPLICATION
THE EVENT SERVER
▸ implement handle done
{done, Name} ->
case orddict:find(Name, S#state.events) of
{ok, E} ->
send_to_clients({done, E#event.name, E#event.description},
S#state.clients),
NewEvents = orddict:erase(Name, S#state.events),
loop(S#state{events=NewEvents});
error ->
%% This may happen if we cancel an event and
%% it fires at the same time
loop(S)
end;
13. DESIGNING A CONCURRENT APPLICATION
THE EVENT SERVER
▸ implement send_to_client
▸ others
send_to_clients(Msg, ClientDict) ->
orddict:map(fun(_Ref, Pid) -> Pid ! Msg end, ClientDict).
shutdown ->
exit(shutdown);
{'DOWN', Ref, process, _Pid, _Reason} ->
loop(S#state{clients=orddict:erase(Ref, S#state.clients)});
code_change ->
?MODULE:loop(S);
Unknown ->
io:format("Unknown message: ~p~n",[Unknown]),
loop(S)
13. DESIGNING A CONCURRENT APPLICATION
HOT CODE LOVING
▸ code server
▸ basically a VM process in charge of an ETS table
▸ ETS table : in-memory database table
▸ A new version of a module is automatically loaded when compiling
it with c(Module), loading with l(Module) or loading it with one of
the many functions of the code module.
▸ local and external call
▸ external calls are always done on the newest version of the code
available in the code server
13. DESIGNING A CONCURRENT APPLICATION
HOT CODE LOVING
▸ code server
13. DESIGNING A CONCURRENT APPLICATION
HOT CODE LOVING
▸ more generic code update
-module(hotload).
-export([server/1, upgrade/1]).
server(State) ->
receive
update ->
NewState = ?MODULE:upgrade(State),
?MODULE:server(NewState);
SomeMessage ->
%% do something here
server(State) %% stay in the same version no matter what.
end.
13. DESIGNING A CONCURRENT APPLICATION
I SAID, HIDE YOUR MESSAGE
▸ hiding
▸ we should only have one running at a time
start() ->
register(?MODULE, Pid=spawn(?MODULE, init, [])),
Pid.
start_link() ->
register(?MODULE, Pid=spawn_link(?MODULE, init, [])),
Pid.
terminate() ->
?MODULE ! shutdown.
13. DESIGNING A CONCURRENT APPLICATION
I SAID, HIDE YOUR MESSAGE
▸ subscribe
subscribe(Pid) ->
Ref = erlang:monitor(process, whereis(?MODULE)),
?MODULE ! {self(), Ref, {subscribe, Pid}},
receive
{Ref, ok} ->
{ok, Ref};
{'DOWN', Ref, process, _Pid, Reason} ->
{error, Reason}
after 5000 ->
{error, timeout}
end.
13. DESIGNING A CONCURRENT APPLICATION
I SAID, HIDE YOUR MESSAGE
▸ add_event
add_event(Name, Description, TimeOut) ->
Ref = make_ref(),
?MODULE ! {self(), Ref, {add, Name, Description, TimeOut}},
receive
{Ref, Msg} -> Msg
after 5000 ->
{error, timeout}
end.
13. DESIGNING A CONCURRENT APPLICATION
I SAID, HIDE YOUR MESSAGE
▸ add_event
add_event2(Name, Description, TimeOut) ->
Ref = make_ref(),
?MODULE ! {self(), Ref, {add, Name, Description, TimeOut}},
receive
{Ref, {error, Reason}} -> erlang:error(Reason);
{Ref, Msg} -> Msg
after 5000 ->
{error, timeout}
end.
13. DESIGNING A CONCURRENT APPLICATION
I SAID, HIDE YOUR MESSAGE
▸ cancel
cancel(Name) ->
Ref = make_ref(),
?MODULE ! {self(), Ref, {cancel, Name}},
receive
{Ref, ok} -> ok
after 5000 ->
{error, timeout}
end.
13. DESIGNING A CONCURRENT APPLICATION
I SAID, HIDE YOUR MESSAGE
▸ accumulate all messages during a given period of time
listen(Delay) ->
receive
M = {done, _Name, _Description} ->
[M | listen(0)]
after Delay*1000 ->
[]
end.
13. DESIGNING A CONCURRENT APPLICATION
A TEST DRIVE
▸ vim Emakefile
▸ erl -make
▸ erl -pa ebin/
▸ add path for look in erlang module
▸ make:all([load])
▸ find Emakefile -> recompile -> load
{'src/*', [debug_info,
{i, "src"},
{i, "include"},
{outdir, "ebin"}]}.
13. DESIGNING A CONCURRENT APPLICATION
A TEST DRIVE
1> evserv:start().
<0.34.0>
2> evserv:subscribe(self()).
{ok,#Ref<0.0.0.31>}
3> evserv:add_event("Hey there", "test", FutureDateTime).
ok
4> evserv:listen(5).
[]
5> evserv:cancel("Hey there").
ok
6> evserv:add_event("Hey there2", "test", NextMinuteDateTime).
ok
7> evserv:listen(2000).
[{done,"Hey there2","test"}]
13. DESIGNING A CONCURRENT APPLICATION
ADDING SUPERVISION
▸ supervisor
-module(sup).
-export([start/2, start_link/2, init/1, loop/1]).
start(Mod,Args) ->
spawn(?MODULE, init, [{Mod, Args}]).
start_link(Mod,Args) ->
spawn_link(?MODULE, init, [{Mod, Args}]).
init({Mod,Args}) ->
process_flag(trap_exit, true),
loop({Mod,start_link,Args}).
13. DESIGNING A CONCURRENT APPLICATION
ADDING SUPERVISION
▸ supervisor
loop({M,F,A}) ->
Pid = apply(M,F,A),
receive
{'EXIT', _From, shutdown} ->
exit(shutdown); % will kill the child too
{'EXIT', Pid, Reason} ->
io:format("Process ~p exited for reason ~p~n",[Pid,Reason]),
loop({M,F,A})
end.
13. DESIGNING A CONCURRENT APPLICATION
ADDING SUPERVISION
▸ using supervisor
1> c(evserv), c(sup).
{ok,sup}
2> SupPid = sup:start(evserv, []).
<0.43.0>
3> whereis(evserv).
<0.44.0>
4> exit(whereis(evserv), die).
true
Process <0.44.0> exited for reason die
5> exit(whereis(evserv), die).
Process <0.48.0> exited for reason die
true
13. DESIGNING A CONCURRENT APPLICATION
ADDING SUPERVISION
▸ using supervisor
▸ The supervisor demonstrated here is only the most basic
form that exists and is not exactly fit for production
environments compared to the real thing.
6> exit(SupPid, shutdown).
true
7> whereis(evserv).
undefined
13. DESIGNING A CONCURRENT APPLICATION
NAMESPACES (OR LACK THERE OF)
▸ using prefix
▸ renamed to reminder_evserv, reminder_sup and
reminder_event.
▸ Some programmers then decide to add a module, named
after the application itself, which wraps common calls
▸ No need to synchronize them, no locks, no real main loop
WHAT IS OTP?
CHAPTER.14
14. WHAT IS OTP?
IT’S THE OPEN TELECOM PLATFORM!
▸ meaning?
▸ OTP stands for Open Telecom Platform, although it's not
that much about telecom anymore (it's more about
software that has the property of telecom applications)
▸ erlang’s greatness comes from
▸ concurrency + distribution + error handling capabilities,
and otp
14. WHAT IS OTP?
IT’S THE OPEN TELECOM PLATFORM!
▸ There were a few 'gotchas' here and there
▸ on how to avoid race conditions or to always remember
that a process could die at any time. There was also hot
code loading, naming processes and adding
supervisors, to name a few.
▸ The OTP framework takes care of this by grouping these
essential practices
▸ Every Erlang programmer should use them
14. WHAT IS OTP?
THE COMMON PROCESS, ABSTRACTED
▸ In most processes, we had a function in charge of
spawning the new process, a function in charge of giving it
its initial values, a main loop, etc.
▸ these parts are usually present
14. WHAT IS OTP?
THE COMMON PROCESS, ABSTRACTED
▸ crafted code
▸ with the advantage of being used for years in the field
▸ also being built with far more caution than we were with
our implementations.
▸ fault-tolerant manner
14. WHAT IS OTP?
THE BASIC SERVER
▸ kitty_server
%%%%% Naive version
-module(kitty_server).
-export([start_link/0, order_cat/4, return_cat/2, close_shop/1]).
-record(cat, {name, color=green, description}).
%%% Client API
start_link() -> spawn_link(fun init/0).
14. WHAT IS OTP?
THE BASIC SERVER
▸ kitty_server - api, order_cat
%% Synchronous call
order_cat(Pid, Name, Color, Description) ->
Ref = erlang:monitor(process, Pid),
Pid ! {self(), Ref, {order, Name, Color, Description}},
receive
{Ref, Cat} ->
erlang:demonitor(Ref, [flush]),
Cat;
{'DOWN', Ref, process, Pid, Reason} ->
erlang:error(Reason)
after 5000 ->
erlang:error(timeout)
end
14. WHAT IS OTP?
THE BASIC SERVER
▸ kitty_server - api, return_cat
%% This call is asynchronous
return_cat(Pid, Cat = #cat{}) ->
Pid ! {return, Cat},
ok.
close_shop(Pid) ->
Ref = erlang:monitor(process, Pid),
Pid ! {self(), Ref, terminate},
receive
{Ref, ok} -> erlang:demonitor(Ref, [flush]), ok;
{'DOWN', Ref, process, Pid, Reason} -> erlang:error(Reason)
after 5000 -> erlang:error(timeout)
end.
14. WHAT IS OTP?
THE BASIC SERVER
▸ kitty_server - server_fun, init, loop
%%% Server functions
init() -> loop([]).
loop(Cats) ->
receive
{Pid, Ref, {order, Name, Color, Description}} ->
if Cats =:= [] ->
Pid ! {Ref, make_cat(Name, Color, Description)},
loop(Cats);
Cats =/= [] -> % got to empty the stock
Pid ! {Ref, hd(Cats)},
loop(tl(Cats))
end;
14. WHAT IS OTP?
THE BASIC SERVER
▸ kitty_server - server_fun, loop2
{return, Cat = #cat{}} ->
loop([Cat|Cats]);
{Pid, Ref, terminate} ->
Pid ! {Ref, ok},
terminate(Cats);
Unknown ->
%% do some logging here too
io:format("Unknown message: ~p~n", [Unknown]),
loop(Cats)
end.
14. WHAT IS OTP?
THE BASIC SERVER
▸ kitty_server - private server_fun
%%% Private functions
make_cat(Name, Col, Desc) ->
#cat{name=Name, color=Col, description=Desc}.
terminate(Cats) ->
[io:format("~p was set free.~n",[C#cat.name]) || C <- Cats],
ok.
14. WHAT IS OTP?
THE BASIC SERVER
▸ kitty_server - private server_fun
1> c(kitty_server).
{ok,kitty_server}
2> rr(kitty_server).
[cat]
3> Pid = kitty_server:start_link().
<0.57.0>
4> Cat1 = kitty_server:order_cat(Pid, carl, brown, "loves to burn
bridges").
#cat{name = carl,color = brown,
description = "loves to burn bridges"}
5> kitty_server:return_cat(Pid, Cat1).
ok
14. WHAT IS OTP?
THE BASIC SERVER
▸ kitty_server - private server_fun
6> kitty_server:order_cat(Pid, jimmy, orange, "cuddly").
#cat{name = carl,color = brown,
description = "loves to burn bridges"}
7> kitty_server:order_cat(Pid, jimmy, orange, "cuddly").
#cat{name = jimmy,color = orange,description = "cuddly"}
8> kitty_server:return_cat(Pid, Cat1).
ok
9> kitty_server:close_shop(Pid).
carl was set free.
ok
10> kitty_server:close_shop(Pid).
** exception error: no such process or port
in function kitty_server:close_shop/1
14. WHAT IS OTP?
THE BASIC SERVER
▸ we can see patterns we've previously applied
▸ The sections where we set monitors up and down, apply
timers, receive data, use a main loop, handle the init
function, etc.
14. WHAT IS OTP?
THE BASIC SERVER
▸ let’s generic~
-module(my_server).
-compile(export_all).
call(Pid, Msg) ->
Ref = erlang:monitor(process, Pid),
Pid ! {self(), Ref, Msg},
receive
{Ref, Reply} -> erlang:demonitor(Ref, [flush]), Reply;
{'DOWN', Ref, process, Pid, Reason} ->
erlang:error(Reason)
after 5000 ->
erlang:error(timeout)
end.
14. WHAT IS OTP?
THE BASIC SERVER
▸ let’s generic~
%% Synchronous call
order_cat(Pid, Name, Color, Description) ->
my_server:call(Pid, {order, Name, Color, Description}).
%% This call is asynchronous
return_cat(Pid, Cat = #cat{}) ->
Pid ! {return, Cat},
ok.
%% Synchronous call
close_shop(Pid) ->
my_server:call(Pid, terminate).
14. WHAT IS OTP?
THE BASIC SERVER
▸ next generic chunk is not obvious..
▸ Note that every process we've written so far has a loop
where all the messages are pattern matched
loop(Module, State) ->
receive
Message -> Module:handle(Message, State)
end.
handle(Message1, State) -> NewState1;
handle(Message2, State) -> NewState2;
...
handle(MessageN, State) -> NewStateN.
14. WHAT IS OTP?
THE BASIC SERVER
▸ async call / sync call
▸ It would be pretty helpful if our generic server
implementation could provide a clear way to know
which kind of call is which.
▸ we will need to match different kinds of messages in
my_server:loop/2
▸ add atom sync
14. WHAT IS OTP?
THE BASIC SERVER
▸ async call / sync call
call(Pid, Msg) ->
Ref = erlang:monitor(process, Pid),
Pid ! {sync, self(), Ref, Msg},
receive
{Ref, Reply} ->
erlang:demonitor(Ref, [flush]),
Reply;
{'DOWN', Ref, process, Pid, Reason} ->
erlang:error(Reason)
after 5000 ->
erlang:error(timeout)
end.
14. WHAT IS OTP?
THE BASIC SERVER
▸ async call / sync call
cast(Pid, Msg) ->
Pid ! {async, Msg},
ok.
loop(Module, State) ->
receive
{async, Msg} ->
loop(Module, Module:handle_cast(Msg, State));
{sync, Pid, Ref, Msg} ->
loop(Module, Module:handle_call(Msg, Pid, Ref, State))
end.
14. WHAT IS OTP?
THE BASIC SERVER
▸ disappointing thing
▸ The programmers who will use my_server will still need
to know about references when sending synchronous
messages and replying to them.
loop(Module, State) ->
receive
{async, Msg} ->
loop(Module, Module:handle_cast(Msg, State));
{sync, Pid, Ref, Msg} ->
loop(Module, Module:handle_call(Msg, {Pid, Ref}, State))
end.
14. WHAT IS OTP?
THE BASIC SERVER
▸ and now,
▸ they can be passed as a single argument to the other
function as a variable with a name like From.
▸ we'll provide a function to send replies that should
understand what From contains.
reply({Pid, Ref}, Reply) ->
Pid ! {Ref, Reply}.
14. WHAT IS OTP?
THE BASIC SERVER
▸ and now our code is,
-module(my_server).
-export([start/2, start_link/2, call/2, cast/2, reply/2]).
start(Module, InitialState) ->
spawn(fun() -> init(Module, InitialState) end).
start_link(Module, InitialState) ->
spawn_link(fun() -> init(Module, InitialState) end).
…call.. cast… reply…
init(Module, InitialState) ->
loop(Module, Module:init(InitialState)).
…loop…
14. WHAT IS OTP?
THE BASIC SERVER
▸ kitty server 2 as, callback module
-record(cat, {name, color=green, description}).
start_link() -> my_server:start_link(?MODULE, []).
order_cat(Pid, Name, Color, Description) ->
my_server:call(Pid, {order, Name, Color, Description}).
return_cat(Pid, Cat = #cat{}) ->
my_server:cast(Pid, {return, Cat}).
close_shop(Pid) ->
my_server:call(Pid, terminate).
14. WHAT IS OTP?
THE BASIC SERVER
▸ kitty server 2 as, callback module
%%% Server functions
init([]) -> []. %% no treatment of info here!
handle_call({order, Name, Color, Description}, From, Cats) ->
if Cats =:= [] ->
my_server:reply(From, make_cat(Name, Color, Description)),
Cats;
Cats =/= [] ->
my_server:reply(From, hd(Cats)),
tl(Cats)
end;
14. WHAT IS OTP?
THE BASIC SERVER
▸ kitty server 2 as, callback module
handle_call(terminate, From, Cats) ->
my_server:reply(From, ok),
terminate(Cats).
handle_cast({return, Cat = #cat{}}, Cats) ->
[Cat|Cats].
%%% Private functions
make_cat(Name, Col, Desc) ->
#cat{name=Name, color=Col, description=Desc}.
terminate(Cats) ->
[io:format("~p was set free.~n",[C#cat.name]) || C <- Cats],
exit(normal).
14. WHAT IS OTP?
SPECIFIC VS GENERIC
▸ now you understand OTP!
▸ taking all generic component
▸ extracting library…
▸ If you're going to have larger applications then it might be worth it
to separate generic parts of your code from the specific sections.
▸ U have many server - client..
▸ if all these servers share the same common my_server
abstraction, you substantially reduce that complexity
14. WHAT IS OTP?
SPECIFIC VS GENERIC
▸ This means you reduce a lot of time tracking and solving
bugs
▸ when separating the generic from the specific is that we
instantly made it much easier to test our individual
modules.
▸ first kitty server need to spawn,..give right state…
▸ on the otherhand, requires us to run the function calls
over the 'handle_call/3' and 'handle_cast/2'
14. WHAT IS OTP?
SPECIFIC VS GENERIC
▸ when someone optimizes that single backend
▸ every process using it become faster!
▸ that's what happens with the OTP framework.
▸ we need to also consider to our module, (kitty)
▸ named processes, configuring the timeouts, adding debug information, what to do with
unexpected messages, how to tie in hot code loading, handling specific errors, abstracting away
the need to write most replies, handling most ways to shut a server down, making sure the server
plays nice with supervisors, etc.
▸ the Erlang/OTP team managed to handle all of that for you with the
gen_server behaviour

Contenu connexe

Tendances

Google Fit, Android Wear & Xamarin
Google Fit, Android Wear & XamarinGoogle Fit, Android Wear & Xamarin
Google Fit, Android Wear & XamarinPeter Friese
 
Calculator code with scientific functions in java
Calculator code with scientific functions in java Calculator code with scientific functions in java
Calculator code with scientific functions in java Amna Nawazish
 
The Ring programming language version 1.10 book - Part 80 of 212
The Ring programming language version 1.10 book - Part 80 of 212The Ring programming language version 1.10 book - Part 80 of 212
The Ring programming language version 1.10 book - Part 80 of 212Mahmoud Samir Fayed
 
The Ring programming language version 1.5.2 book - Part 62 of 181
The Ring programming language version 1.5.2 book - Part 62 of 181The Ring programming language version 1.5.2 book - Part 62 of 181
The Ring programming language version 1.5.2 book - Part 62 of 181Mahmoud Samir Fayed
 
Google Play Services Rock
Google Play Services RockGoogle Play Services Rock
Google Play Services RockPeter Friese
 
The Ring programming language version 1.8 book - Part 74 of 202
The Ring programming language version 1.8 book - Part 74 of 202The Ring programming language version 1.8 book - Part 74 of 202
The Ring programming language version 1.8 book - Part 74 of 202Mahmoud Samir Fayed
 
The Ring programming language version 1.5 book - Part 12 of 31
The Ring programming language version 1.5 book - Part 12 of 31The Ring programming language version 1.5 book - Part 12 of 31
The Ring programming language version 1.5 book - Part 12 of 31Mahmoud Samir Fayed
 
As time goes by (episode 2)
As time goes by (episode 2)As time goes by (episode 2)
As time goes by (episode 2)Thomas Pierrain
 
The Ring programming language version 1.5.4 book - Part 68 of 185
The Ring programming language version 1.5.4 book - Part 68 of 185The Ring programming language version 1.5.4 book - Part 68 of 185
The Ring programming language version 1.5.4 book - Part 68 of 185Mahmoud Samir Fayed
 

Tendances (9)

Google Fit, Android Wear & Xamarin
Google Fit, Android Wear & XamarinGoogle Fit, Android Wear & Xamarin
Google Fit, Android Wear & Xamarin
 
Calculator code with scientific functions in java
Calculator code with scientific functions in java Calculator code with scientific functions in java
Calculator code with scientific functions in java
 
The Ring programming language version 1.10 book - Part 80 of 212
The Ring programming language version 1.10 book - Part 80 of 212The Ring programming language version 1.10 book - Part 80 of 212
The Ring programming language version 1.10 book - Part 80 of 212
 
The Ring programming language version 1.5.2 book - Part 62 of 181
The Ring programming language version 1.5.2 book - Part 62 of 181The Ring programming language version 1.5.2 book - Part 62 of 181
The Ring programming language version 1.5.2 book - Part 62 of 181
 
Google Play Services Rock
Google Play Services RockGoogle Play Services Rock
Google Play Services Rock
 
The Ring programming language version 1.8 book - Part 74 of 202
The Ring programming language version 1.8 book - Part 74 of 202The Ring programming language version 1.8 book - Part 74 of 202
The Ring programming language version 1.8 book - Part 74 of 202
 
The Ring programming language version 1.5 book - Part 12 of 31
The Ring programming language version 1.5 book - Part 12 of 31The Ring programming language version 1.5 book - Part 12 of 31
The Ring programming language version 1.5 book - Part 12 of 31
 
As time goes by (episode 2)
As time goes by (episode 2)As time goes by (episode 2)
As time goes by (episode 2)
 
The Ring programming language version 1.5.4 book - Part 68 of 185
The Ring programming language version 1.5.4 book - Part 68 of 185The Ring programming language version 1.5.4 book - Part 68 of 185
The Ring programming language version 1.5.4 book - Part 68 of 185
 

En vedette

learn you some erlang - chap0 to chap2
learn you some erlang - chap0 to chap2learn you some erlang - chap0 to chap2
learn you some erlang - chap0 to chap2경미 김
 
learn you some erlang - chap11 to chap12
learn you some erlang - chap11 to chap12learn you some erlang - chap11 to chap12
learn you some erlang - chap11 to chap12경미 김
 
learn you some erlang - chap 6 to chap7
learn you some erlang - chap 6 to chap7learn you some erlang - chap 6 to chap7
learn you some erlang - chap 6 to chap7경미 김
 
learn you some erlang - chap3 to chap5
learn you some erlang - chap3 to chap5learn you some erlang - chap3 to chap5
learn you some erlang - chap3 to chap5경미 김
 
learn you some erlang - chap 9 to chap10
learn you some erlang - chap 9 to chap10learn you some erlang - chap 9 to chap10
learn you some erlang - chap 9 to chap10경미 김
 
Learn You Some Erlang for great good! 日本語化プロジェクト
Learn You Some Erlang for great good! 日本語化プロジェクトLearn You Some Erlang for great good! 日本語化プロジェクト
Learn You Some Erlang for great good! 日本語化プロジェクトYoshifumi Yamaguchi
 
Developing web apps using Erlang-Web
Developing web apps using Erlang-WebDeveloping web apps using Erlang-Web
Developing web apps using Erlang-Webfanqstefan
 
Lição_122016_Filho de Davi_GGR
Lição_122016_Filho de Davi_GGRLição_122016_Filho de Davi_GGR
Lição_122016_Filho de Davi_GGRGerson G. Ramos
 
Erlang web framework: Chicago boss
Erlang web framework: Chicago bossErlang web framework: Chicago boss
Erlang web framework: Chicago bossBarcamp Saigon
 
Por que tantas igrejas se Deus é um so? palestra 22
Por que tantas igrejas se Deus é um so? palestra 22Por que tantas igrejas se Deus é um so? palestra 22
Por que tantas igrejas se Deus é um so? palestra 22Rogerio Sena
 
Caching Strategies for an Erlang Based Web Stack
Caching Strategies for an Erlang Based Web StackCaching Strategies for an Erlang Based Web Stack
Caching Strategies for an Erlang Based Web Stackenriquepazperez
 
Mcollective orchestration tool 소개
Mcollective orchestration tool 소개Mcollective orchestration tool 소개
Mcollective orchestration tool 소개태준 문
 
Concurrent Planning
Concurrent PlanningConcurrent Planning
Concurrent Planningbartoncenter
 
6 Estágios das lagartas voadoras - palestra 31
6 Estágios das lagartas voadoras - palestra 316 Estágios das lagartas voadoras - palestra 31
6 Estágios das lagartas voadoras - palestra 31Rogerio Sena
 
Lunar.pptx
Lunar.pptxLunar.pptx
Lunar.pptxstowlson
 
25 Ways To Take Initiative At Work
25 Ways To Take Initiative At Work25 Ways To Take Initiative At Work
25 Ways To Take Initiative At WorkThriveYard
 

En vedette (20)

learn you some erlang - chap0 to chap2
learn you some erlang - chap0 to chap2learn you some erlang - chap0 to chap2
learn you some erlang - chap0 to chap2
 
learn you some erlang - chap11 to chap12
learn you some erlang - chap11 to chap12learn you some erlang - chap11 to chap12
learn you some erlang - chap11 to chap12
 
learn you some erlang - chap 6 to chap7
learn you some erlang - chap 6 to chap7learn you some erlang - chap 6 to chap7
learn you some erlang - chap 6 to chap7
 
learn you some erlang - chap3 to chap5
learn you some erlang - chap3 to chap5learn you some erlang - chap3 to chap5
learn you some erlang - chap3 to chap5
 
learn you some erlang - chap 9 to chap10
learn you some erlang - chap 9 to chap10learn you some erlang - chap 9 to chap10
learn you some erlang - chap 9 to chap10
 
Learn You Some Erlang for great good! 日本語化プロジェクト
Learn You Some Erlang for great good! 日本語化プロジェクトLearn You Some Erlang for great good! 日本語化プロジェクト
Learn You Some Erlang for great good! 日本語化プロジェクト
 
Developing web apps using Erlang-Web
Developing web apps using Erlang-WebDeveloping web apps using Erlang-Web
Developing web apps using Erlang-Web
 
Lição_122016_Filho de Davi_GGR
Lição_122016_Filho de Davi_GGRLição_122016_Filho de Davi_GGR
Lição_122016_Filho de Davi_GGR
 
Erlang web framework: Chicago boss
Erlang web framework: Chicago bossErlang web framework: Chicago boss
Erlang web framework: Chicago boss
 
Reporte
ReporteReporte
Reporte
 
BEAMing With Joy
BEAMing With JoyBEAMing With Joy
BEAMing With Joy
 
Por que tantas igrejas se Deus é um so? palestra 22
Por que tantas igrejas se Deus é um so? palestra 22Por que tantas igrejas se Deus é um so? palestra 22
Por que tantas igrejas se Deus é um so? palestra 22
 
Caching Strategies for an Erlang Based Web Stack
Caching Strategies for an Erlang Based Web StackCaching Strategies for an Erlang Based Web Stack
Caching Strategies for an Erlang Based Web Stack
 
Mcollective orchestration tool 소개
Mcollective orchestration tool 소개Mcollective orchestration tool 소개
Mcollective orchestration tool 소개
 
Concurrent Planning
Concurrent PlanningConcurrent Planning
Concurrent Planning
 
6 Estágios das lagartas voadoras - palestra 31
6 Estágios das lagartas voadoras - palestra 316 Estágios das lagartas voadoras - palestra 31
6 Estágios das lagartas voadoras - palestra 31
 
A18
A18A18
A18
 
Lunar.pptx
Lunar.pptxLunar.pptx
Lunar.pptx
 
Laboratorio n 16
Laboratorio n 16Laboratorio n 16
Laboratorio n 16
 
25 Ways To Take Initiative At Work
25 Ways To Take Initiative At Work25 Ways To Take Initiative At Work
25 Ways To Take Initiative At Work
 

Similaire à learn you some erlang - chap13 to chap14

AngularJS, More Than Directives !
AngularJS, More Than Directives !AngularJS, More Than Directives !
AngularJS, More Than Directives !Gaurav Behere
 
The Promised Land (in Angular)
The Promised Land (in Angular)The Promised Land (in Angular)
The Promised Land (in Angular)Domenic Denicola
 
Event-Driven Architecture Traps - Jakub Pilimon
Event-Driven Architecture Traps - Jakub PilimonEvent-Driven Architecture Traps - Jakub Pilimon
Event-Driven Architecture Traps - Jakub PilimonVMware Tanzu
 
MongoDB.local DC 2018: Scaling Realtime Apps with Change Streams
MongoDB.local DC 2018: Scaling Realtime Apps with Change StreamsMongoDB.local DC 2018: Scaling Realtime Apps with Change Streams
MongoDB.local DC 2018: Scaling Realtime Apps with Change StreamsMongoDB
 
Web Push Notifications
Web Push NotificationsWeb Push Notifications
Web Push NotificationsUgur Eker
 
Google DevFest MN - Windows Azure Notification Hubs
Google DevFest MN - Windows Azure Notification HubsGoogle DevFest MN - Windows Azure Notification Hubs
Google DevFest MN - Windows Azure Notification HubsAdam Grocholski
 
Cloud Native Microservices with Spring Cloud
Cloud Native Microservices with Spring CloudCloud Native Microservices with Spring Cloud
Cloud Native Microservices with Spring CloudConor Svensson
 
Simple callcenter platform with PHP
Simple callcenter platform with PHPSimple callcenter platform with PHP
Simple callcenter platform with PHPMorten Amundsen
 
MVI - Managing State The Kotlin Way
MVI - Managing State The Kotlin WayMVI - Managing State The Kotlin Way
MVI - Managing State The Kotlin WayZeyad Gasser
 
The road to continuous deployment: a case study (DPC16)
The road to continuous deployment: a case study (DPC16)The road to continuous deployment: a case study (DPC16)
The road to continuous deployment: a case study (DPC16)Michiel Rook
 
Design Patterns in Micro-services architectures & Gilmour
Design Patterns in Micro-services architectures & GilmourDesign Patterns in Micro-services architectures & Gilmour
Design Patterns in Micro-services architectures & GilmourPiyush Verma
 
Building Apps with Flutter - Hillel Coren, Invoice Ninja
Building Apps with Flutter - Hillel Coren, Invoice NinjaBuilding Apps with Flutter - Hillel Coren, Invoice Ninja
Building Apps with Flutter - Hillel Coren, Invoice NinjaDroidConTLV
 
Push Notification in IBM MobileFirst Xamarin SDK
Push Notification in IBM MobileFirst Xamarin SDKPush Notification in IBM MobileFirst Xamarin SDK
Push Notification in IBM MobileFirst Xamarin SDKAjay Chebbi
 
リローダブルClojureアプリケーション
リローダブルClojureアプリケーションリローダブルClojureアプリケーション
リローダブルClojureアプリケーションKenji Nakamura
 

Similaire à learn you some erlang - chap13 to chap14 (20)

AngularJS, More Than Directives !
AngularJS, More Than Directives !AngularJS, More Than Directives !
AngularJS, More Than Directives !
 
The Promised Land (in Angular)
The Promised Land (in Angular)The Promised Land (in Angular)
The Promised Land (in Angular)
 
Event-Driven Architecture Traps - Jakub Pilimon
Event-Driven Architecture Traps - Jakub PilimonEvent-Driven Architecture Traps - Jakub Pilimon
Event-Driven Architecture Traps - Jakub Pilimon
 
MongoDB.local DC 2018: Scaling Realtime Apps with Change Streams
MongoDB.local DC 2018: Scaling Realtime Apps with Change StreamsMongoDB.local DC 2018: Scaling Realtime Apps with Change Streams
MongoDB.local DC 2018: Scaling Realtime Apps with Change Streams
 
Web Push Notifications
Web Push NotificationsWeb Push Notifications
Web Push Notifications
 
Google DevFest MN - Windows Azure Notification Hubs
Google DevFest MN - Windows Azure Notification HubsGoogle DevFest MN - Windows Azure Notification Hubs
Google DevFest MN - Windows Azure Notification Hubs
 
Cloud Native Microservices with Spring Cloud
Cloud Native Microservices with Spring CloudCloud Native Microservices with Spring Cloud
Cloud Native Microservices with Spring Cloud
 
Simple callcenter platform with PHP
Simple callcenter platform with PHPSimple callcenter platform with PHP
Simple callcenter platform with PHP
 
MVI - Managing State The Kotlin Way
MVI - Managing State The Kotlin WayMVI - Managing State The Kotlin Way
MVI - Managing State The Kotlin Way
 
Event source everything!
Event source everything!Event source everything!
Event source everything!
 
The road to continuous deployment: a case study (DPC16)
The road to continuous deployment: a case study (DPC16)The road to continuous deployment: a case study (DPC16)
The road to continuous deployment: a case study (DPC16)
 
Design Patterns in Micro-services architectures & Gilmour
Design Patterns in Micro-services architectures & GilmourDesign Patterns in Micro-services architectures & Gilmour
Design Patterns in Micro-services architectures & Gilmour
 
My SQL Events
My SQL EventsMy SQL Events
My SQL Events
 
My sql events
My sql eventsMy sql events
My sql events
 
Android wearpp
Android wearppAndroid wearpp
Android wearpp
 
Coroutines
CoroutinesCoroutines
Coroutines
 
Building Apps with Flutter - Hillel Coren, Invoice Ninja
Building Apps with Flutter - Hillel Coren, Invoice NinjaBuilding Apps with Flutter - Hillel Coren, Invoice Ninja
Building Apps with Flutter - Hillel Coren, Invoice Ninja
 
Push Notification in IBM MobileFirst Xamarin SDK
Push Notification in IBM MobileFirst Xamarin SDKPush Notification in IBM MobileFirst Xamarin SDK
Push Notification in IBM MobileFirst Xamarin SDK
 
リローダブルClojureアプリケーション
リローダブルClojureアプリケーションリローダブルClojureアプリケーション
リローダブルClojureアプリケーション
 
Granada_Perl_Workshop_2014_Google_API_Client
Granada_Perl_Workshop_2014_Google_API_ClientGranada_Perl_Workshop_2014_Google_API_Client
Granada_Perl_Workshop_2014_Google_API_Client
 

Dernier

Unlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language ModelsUnlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language Modelsaagamshah0812
 
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...Steffen Staab
 
How To Use Server-Side Rendering with Nuxt.js
How To Use Server-Side Rendering with Nuxt.jsHow To Use Server-Side Rendering with Nuxt.js
How To Use Server-Side Rendering with Nuxt.jsAndolasoft Inc
 
10 Trends Likely to Shape Enterprise Technology in 2024
10 Trends Likely to Shape Enterprise Technology in 202410 Trends Likely to Shape Enterprise Technology in 2024
10 Trends Likely to Shape Enterprise Technology in 2024Mind IT Systems
 
How to Choose the Right Laravel Development Partner in New York City_compress...
How to Choose the Right Laravel Development Partner in New York City_compress...How to Choose the Right Laravel Development Partner in New York City_compress...
How to Choose the Right Laravel Development Partner in New York City_compress...software pro Development
 
Define the academic and professional writing..pdf
Define the academic and professional writing..pdfDefine the academic and professional writing..pdf
Define the academic and professional writing..pdfPearlKirahMaeRagusta1
 
Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...
Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...
Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...OnePlan Solutions
 
Right Money Management App For Your Financial Goals
Right Money Management App For Your Financial GoalsRight Money Management App For Your Financial Goals
Right Money Management App For Your Financial GoalsJhone kinadey
 
Optimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTVOptimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTVshikhaohhpro
 
The Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdfThe Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdfkalichargn70th171
 
5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdf5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdfWave PLM
 
Diamond Application Development Crafting Solutions with Precision
Diamond Application Development Crafting Solutions with PrecisionDiamond Application Development Crafting Solutions with Precision
Diamond Application Development Crafting Solutions with PrecisionSolGuruz
 
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...Health
 
VTU technical seminar 8Th Sem on Scikit-learn
VTU technical seminar 8Th Sem on Scikit-learnVTU technical seminar 8Th Sem on Scikit-learn
VTU technical seminar 8Th Sem on Scikit-learnAmarnathKambale
 
The Guide to Integrating Generative AI into Unified Continuous Testing Platfo...
The Guide to Integrating Generative AI into Unified Continuous Testing Platfo...The Guide to Integrating Generative AI into Unified Continuous Testing Platfo...
The Guide to Integrating Generative AI into Unified Continuous Testing Platfo...kalichargn70th171
 
A Secure and Reliable Document Management System is Essential.docx
A Secure and Reliable Document Management System is Essential.docxA Secure and Reliable Document Management System is Essential.docx
A Secure and Reliable Document Management System is Essential.docxComplianceQuest1
 
Software Quality Assurance Interview Questions
Software Quality Assurance Interview QuestionsSoftware Quality Assurance Interview Questions
Software Quality Assurance Interview QuestionsArshad QA
 
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️Delhi Call girls
 
Unveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time ApplicationsUnveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time ApplicationsAlberto González Trastoy
 

Dernier (20)

Unlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language ModelsUnlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language Models
 
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
 
How To Use Server-Side Rendering with Nuxt.js
How To Use Server-Side Rendering with Nuxt.jsHow To Use Server-Side Rendering with Nuxt.js
How To Use Server-Side Rendering with Nuxt.js
 
10 Trends Likely to Shape Enterprise Technology in 2024
10 Trends Likely to Shape Enterprise Technology in 202410 Trends Likely to Shape Enterprise Technology in 2024
10 Trends Likely to Shape Enterprise Technology in 2024
 
How to Choose the Right Laravel Development Partner in New York City_compress...
How to Choose the Right Laravel Development Partner in New York City_compress...How to Choose the Right Laravel Development Partner in New York City_compress...
How to Choose the Right Laravel Development Partner in New York City_compress...
 
Define the academic and professional writing..pdf
Define the academic and professional writing..pdfDefine the academic and professional writing..pdf
Define the academic and professional writing..pdf
 
Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...
Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...
Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...
 
Right Money Management App For Your Financial Goals
Right Money Management App For Your Financial GoalsRight Money Management App For Your Financial Goals
Right Money Management App For Your Financial Goals
 
Optimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTVOptimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTV
 
The Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdfThe Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdf
 
5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdf5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdf
 
Diamond Application Development Crafting Solutions with Precision
Diamond Application Development Crafting Solutions with PrecisionDiamond Application Development Crafting Solutions with Precision
Diamond Application Development Crafting Solutions with Precision
 
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
 
VTU technical seminar 8Th Sem on Scikit-learn
VTU technical seminar 8Th Sem on Scikit-learnVTU technical seminar 8Th Sem on Scikit-learn
VTU technical seminar 8Th Sem on Scikit-learn
 
Vip Call Girls Noida ➡️ Delhi ➡️ 9999965857 No Advance 24HRS Live
Vip Call Girls Noida ➡️ Delhi ➡️ 9999965857 No Advance 24HRS LiveVip Call Girls Noida ➡️ Delhi ➡️ 9999965857 No Advance 24HRS Live
Vip Call Girls Noida ➡️ Delhi ➡️ 9999965857 No Advance 24HRS Live
 
The Guide to Integrating Generative AI into Unified Continuous Testing Platfo...
The Guide to Integrating Generative AI into Unified Continuous Testing Platfo...The Guide to Integrating Generative AI into Unified Continuous Testing Platfo...
The Guide to Integrating Generative AI into Unified Continuous Testing Platfo...
 
A Secure and Reliable Document Management System is Essential.docx
A Secure and Reliable Document Management System is Essential.docxA Secure and Reliable Document Management System is Essential.docx
A Secure and Reliable Document Management System is Essential.docx
 
Software Quality Assurance Interview Questions
Software Quality Assurance Interview QuestionsSoftware Quality Assurance Interview Questions
Software Quality Assurance Interview Questions
 
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
 
Unveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time ApplicationsUnveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
 

learn you some erlang - chap13 to chap14

  • 1. LEARN U ERLANG WEEK6 - PRESENTED BY NOLLEH
  • 3. 13. DESIGNING A CONCURRENT PROGRAM UNDERSTANDING THE PROBLEM ▸ roles ▸ add event ( event contains deadline / name / desc ) ▸ show an warning when time has comes up ▸ cancel event ▸ no persistent disk storage ▸ update while it is running ▸ interaction via command line
  • 4. 13. DESIGNING A CONCURRENT PROGRAM UNDERSTANDING THE PROBLEM ▸ event server ▸ Accepts subscriptions from clients ▸ Forwards notifications from event processes to each of the subscribers ▸ Accepts messages to add events (and start the x, y, z processes needed) ▸ Can accept messages to cancel an event and subsequently kill the event processes ▸ Can be terminated by a client ▸ Can have its code reloaded via the shell.
  • 5. 13. DESIGNING A CONCURRENT PROGRAM UNDERSTANDING THE PROBLEM ▸ client ▸ Subscribes to the event server and receive notifications as messages. Each of these could potentially be a gateway to the different interaction points mentioned above (GUI, web page, instant messaging software, email, etc.) ▸ Asks the server to add an event with all its details ▸ Asks the server to cancel an event ▸ Monitors the server (to know if it goes down) ▸ Shuts down the event server if needed
  • 6. 13. DESIGNING A CONCURRENT PROGRAM UNDERSTANDING THE PROBLEM ▸ x, y and z: ▸ Represent a notification waiting to fire (they're basically just timers linked to the event server) ▸ Send a message to the event server when the time is up ▸ Receive a cancellation message and die
  • 7. 13. DESIGNING A CONCURRENT PROGRAM UNDERSTANDING THE PROBLEM ▸ for real program, ▸ timer:send_after/2-3 to avoid spawning too many processes.
  • 8. 13. DESIGNING A CONCURRENT APPLICATION DEFINING THE PROTOCOL ▸ subscribe
  • 9. 13. DESIGNING A CONCURRENT APPLICATION DEFINING THE PROTOCOL ▸ add
  • 10. 13. DESIGNING A CONCURRENT APPLICATION DEFINING THE PROTOCOL ▸ cancel
  • 11. 13. DESIGNING A CONCURRENT APPLICATION DEFINING THE PROTOCOL ▸ notification
  • 12. 13. DESIGNING A CONCURRENT APPLICATION DEFINING THE PROTOCOL ▸ shutdown
  • 13. 13. DESIGNING A CONCURRENT APPLICATION DEFINING THE PROTOCOL ▸ notification
  • 14. 13. DESIGNING A CONCURRENT APPLICATION DEFINING THE PROTOCOL ▸ cancel
  • 15. 13. DESIGNING A CONCURRENT APPLICATION DEFINING THE PROTOCOL ▸ code change
  • 16. 13. DESIGNING A CONCURRENT APPLICATION LAY THEM FOUNDATION ▸ project ▸ ebin/ (compiled) ▸ include/ (header) ▸ priv/ (executables that might have to interact with Erlang, such as specific drivers and whatnot) ▸ src/ (private hrl, erl)
  • 17. 13. DESIGNING A CONCURRENT APPLICATION AN EVENT MODULE ▸ project ▸ {Pid, Ref, Message}, where Pid is the sender and Ref is a unique message identifier to help know what reply came from who. loop(State) -> receive {Server, Ref, cancel} -> ... after Delay -> ... end.
  • 18. 13. DESIGNING A CONCURRENT APPLICATION AN EVENT MODULE ▸ state ▸ contains ▸ timeout / name of event / event server pid (for noti) -module(event). -compile(export_all). -record(state, {server, name="", to_go=0}).
  • 19. 13. DESIGNING A CONCURRENT APPLICATION AN EVENT MODULE ▸ state ▸ contains ▸ timeout / name of event / event server pid (for noti) loop(S = #state{server=Server}) -> receive {Server, Ref, cancel} -> Server ! {Ref, ok} after S#state.to_go*1000 -> Server ! {done, S#state.name} end.
  • 20. 13. DESIGNING A CONCURRENT APPLICATION AN EVENT MODULE ▸ test event 6> c(event). {ok,event} 7> rr(event, state). [state] 8> spawn(event, loop, [#state{server=self(), name="test", to_go=5}]). <0.60.0> 9> flush(). ok 10> flush(). Shell got {done,"test"} ok
  • 21. 13. DESIGNING A CONCURRENT APPLICATION AN EVENT MODULE ▸ test event ▸ we don't expect it to come from anywhere specific (any place will do, we won't match on the receive) nor should we want to reply to it 11> Pid = spawn(event, loop, [#state{server=self(), name=“test", to_go=500}]). <0.64.0> 12> ReplyRef = make_ref(). #Ref<0.0.0.210> 13> Pid ! {self(), ReplyRef, cancel}. {<0.50.0>,#Ref<0.0.0.210>,cancel} 14> flush(). Shell got {#Ref<0.0.0.210>,ok} ok
  • 22. 13. DESIGNING A CONCURRENT APPLICATION AN EVENT MODULE ▸ limit of timer 15> spawn(event, loop, [#state{server=self(), name="test", to_go=365*24*60*60}]). <0.69.0> 16> =ERROR REPORT==== DD-MM-YYYY::HH:mm:SS === Error in process <0.69.0> with exit value: {timeout_value,[{event,loop, 1}]}
  • 23. 13. DESIGNING A CONCURRENT APPLICATION AN EVENT MODULE ▸ split it ▸ ex. 98*24*60*60+4 -> [4,4233600,4233600] %% Because Erlang is limited to about 49 days (49*24*60*60*1000) in %% milliseconds, the following function is used normalize(N) -> Limit = 49*24*60*60, [N rem Limit | lists:duplicate(N div Limit, Limit)].
  • 24. 13. DESIGNING A CONCURRENT APPLICATION AN EVENT MODULE ▸ split it loop(S = #state{server=Server, to_go=[T|Next]}) -> receive {Server, Ref, cancel} -> Server ! {Ref, ok} after T*1000 -> if Next =:= [] -> Server ! {done, S#state.name}; Next =/= [] -> loop(S#state{to_go=Next}) end end.
  • 25. 13. DESIGNING A CONCURRENT APPLICATION AN EVENT MODULE ▸ normalize helper start(EventName, Delay) -> spawn(?MODULE, init, [self(), EventName, Delay]). start_link(EventName, Delay) -> spawn_link(?MODULE, init, [self(), EventName, Delay]). %%% Event's innards init(Server, EventName, Delay) -> loop(#state{server=Server, name=EventName, to_go=normalize(Delay)}).
  • 26. 13. DESIGNING A CONCURRENT APPLICATION AN EVENT MODULE ▸ cancel helper cancel(Pid) -> %% Monitor in case the process is already dead Ref = erlang:monitor(process, Pid), Pid ! {self(), Ref, cancel}, receive {Ref, ok} -> erlang:demonitor(Ref, [flush]), ok; {'DOWN', Ref, process, Pid, _Reason} -> ok end.
  • 27. 13. DESIGNING A CONCURRENT APPLICATION AN EVENT MODULE ▸ test 19> event:start("Event", 0). <0.103.0> 20> flush(). Shell got {done,"Event"} ok 21> Pid = event:start("Event", 500). <0.106.0> 22> event:cancel(Pid). ok
  • 28. 13. DESIGNING A CONCURRENT APPLICATION AN EVENT MODULE ▸ I don’t want noti-time as second time_to_go(TimeOut={{_,_,_}, {_,_,_}}) -> Now = calendar:local_time(), ToGo = calendar:datetime_to_gregorian_seconds(TimeOut) - calendar:datetime_to_gregorian_seconds(Now), Secs = if ToGo > 0 -> ToGo; ToGo =< 0 -> 0 end, normalize(Secs).
  • 29. 13. DESIGNING A CONCURRENT APPLICATION AN EVENT MODULE ▸ init function using time_to_go init(Server, EventName, DateTime) -> loop(#state{server=Server, name=EventName, to_go=time_to_go(DateTime)}).
  • 30. 13. DESIGNING A CONCURRENT APPLICATION THE EVENT SERVER ▸ skeleton -module(evserv). -compile(export_all). loop(State) -> receive {Pid, MsgRef, {subscribe, Client}} -> ... {Pid, MsgRef, {add, Name, Description, TimeOut}} -> ... {Pid, MsgRef, {cancel, Name}} -> ...
  • 31. 13. DESIGNING A CONCURRENT APPLICATION THE EVENT SERVER ▸ skeleton {done, Name} -> ... shutdown -> ... {'DOWN', Ref, process, _Pid, _Reason} -> ... code_change -> ... Unknown -> io:format("Unknown message: ~p~n",[Unknown]), loop(State) end.
  • 32. 13. DESIGNING A CONCURRENT APPLICATION THE EVENT SERVER ▸ declare state -record(state, {events, %% list of #event{} records clients}). %% list of Pids -record(event, {name="", description="", pid, timeout={{1970,1,1},{0,0,0}}}).
  • 33. 13. DESIGNING A CONCURRENT APPLICATION THE EVENT SERVER ▸ declare state loop(S = #state{}) -> receive ... end. init() -> %% Loading events from a static file could be done here. %% You would need to pass an argument to init telling where the %% resource to find the events is. Then load it from here. %% Another option is to just pass the events straight to the server %% through this function. loop(#state{events=orddict:new(), clients=orddict:new()}).
  • 34. 13. DESIGNING A CONCURRENT APPLICATION THE EVENT SERVER ▸ implement subscribe {Pid, MsgRef, {subscribe, Client}} -> Ref = erlang:monitor(process, Client), NewClients = orddict:store(Ref, Client, S#state.clients), Pid ! {MsgRef, ok}, loop(S#state{clients=NewClients});
  • 35. 13. DESIGNING A CONCURRENT APPLICATION THE EVENT SERVER ▸ implement add event valid_datetime({Date,Time}) -> try calendar:valid_date(Date) andalso valid_time(Time) catch error:function_clause -> %% not in {{Y,M,D},{H,Min,S}} format false end; valid_datetime(_) -> false.
  • 36. 13. DESIGNING A CONCURRENT APPLICATION THE EVENT SERVER ▸ implement add event valid_time({H,M,S}) -> valid_time(H,M,S). valid_time(H,M,S) when H >= 0, H < 24, M >= 0, M < 60, S >= 0, S < 60 -> true; valid_time(_,_,_) -> false.
  • 37. 13. DESIGNING A CONCURRENT APPLICATION THE EVENT SERVER ▸ implement add event {Pid, MsgRef, {add, Name, Description, TimeOut}} -> case valid_datetime(TimeOut) of true -> EventPid = event:start_link(Name, TimeOut), NewEvents = orddict:store(Name, #event{name=Name, description=Description, pid=EventPid, timeout=TimeOut}, S#state.events), Pid ! {MsgRef, ok}, loop(S#state{events=NewEvents});
  • 38. 13. DESIGNING A CONCURRENT APPLICATION THE EVENT SERVER ▸ implement add event false -> Pid ! {MsgRef, {error, bad_timeout}}, loop(S) end;
  • 39. 13. DESIGNING A CONCURRENT APPLICATION THE EVENT SERVER ▸ implement cancel event {Pid, MsgRef, {cancel, Name}} -> Events = case orddict:find(Name, S#state.events) of {ok, E} -> event:cancel(E#event.pid), orddict:erase(Name, S#state.events); error -> S#state.events end, Pid ! {MsgRef, ok}, loop(S#state{events=Events});
  • 40. 13. DESIGNING A CONCURRENT APPLICATION THE EVENT SERVER ▸ implement handle done {done, Name} -> case orddict:find(Name, S#state.events) of {ok, E} -> send_to_clients({done, E#event.name, E#event.description}, S#state.clients), NewEvents = orddict:erase(Name, S#state.events), loop(S#state{events=NewEvents}); error -> %% This may happen if we cancel an event and %% it fires at the same time loop(S) end;
  • 41. 13. DESIGNING A CONCURRENT APPLICATION THE EVENT SERVER ▸ implement send_to_client ▸ others send_to_clients(Msg, ClientDict) -> orddict:map(fun(_Ref, Pid) -> Pid ! Msg end, ClientDict). shutdown -> exit(shutdown); {'DOWN', Ref, process, _Pid, _Reason} -> loop(S#state{clients=orddict:erase(Ref, S#state.clients)}); code_change -> ?MODULE:loop(S); Unknown -> io:format("Unknown message: ~p~n",[Unknown]), loop(S)
  • 42. 13. DESIGNING A CONCURRENT APPLICATION HOT CODE LOVING ▸ code server ▸ basically a VM process in charge of an ETS table ▸ ETS table : in-memory database table ▸ A new version of a module is automatically loaded when compiling it with c(Module), loading with l(Module) or loading it with one of the many functions of the code module. ▸ local and external call ▸ external calls are always done on the newest version of the code available in the code server
  • 43. 13. DESIGNING A CONCURRENT APPLICATION HOT CODE LOVING ▸ code server
  • 44. 13. DESIGNING A CONCURRENT APPLICATION HOT CODE LOVING ▸ more generic code update -module(hotload). -export([server/1, upgrade/1]). server(State) -> receive update -> NewState = ?MODULE:upgrade(State), ?MODULE:server(NewState); SomeMessage -> %% do something here server(State) %% stay in the same version no matter what. end.
  • 45. 13. DESIGNING A CONCURRENT APPLICATION I SAID, HIDE YOUR MESSAGE ▸ hiding ▸ we should only have one running at a time start() -> register(?MODULE, Pid=spawn(?MODULE, init, [])), Pid. start_link() -> register(?MODULE, Pid=spawn_link(?MODULE, init, [])), Pid. terminate() -> ?MODULE ! shutdown.
  • 46. 13. DESIGNING A CONCURRENT APPLICATION I SAID, HIDE YOUR MESSAGE ▸ subscribe subscribe(Pid) -> Ref = erlang:monitor(process, whereis(?MODULE)), ?MODULE ! {self(), Ref, {subscribe, Pid}}, receive {Ref, ok} -> {ok, Ref}; {'DOWN', Ref, process, _Pid, Reason} -> {error, Reason} after 5000 -> {error, timeout} end.
  • 47. 13. DESIGNING A CONCURRENT APPLICATION I SAID, HIDE YOUR MESSAGE ▸ add_event add_event(Name, Description, TimeOut) -> Ref = make_ref(), ?MODULE ! {self(), Ref, {add, Name, Description, TimeOut}}, receive {Ref, Msg} -> Msg after 5000 -> {error, timeout} end.
  • 48. 13. DESIGNING A CONCURRENT APPLICATION I SAID, HIDE YOUR MESSAGE ▸ add_event add_event2(Name, Description, TimeOut) -> Ref = make_ref(), ?MODULE ! {self(), Ref, {add, Name, Description, TimeOut}}, receive {Ref, {error, Reason}} -> erlang:error(Reason); {Ref, Msg} -> Msg after 5000 -> {error, timeout} end.
  • 49. 13. DESIGNING A CONCURRENT APPLICATION I SAID, HIDE YOUR MESSAGE ▸ cancel cancel(Name) -> Ref = make_ref(), ?MODULE ! {self(), Ref, {cancel, Name}}, receive {Ref, ok} -> ok after 5000 -> {error, timeout} end.
  • 50. 13. DESIGNING A CONCURRENT APPLICATION I SAID, HIDE YOUR MESSAGE ▸ accumulate all messages during a given period of time listen(Delay) -> receive M = {done, _Name, _Description} -> [M | listen(0)] after Delay*1000 -> [] end.
  • 51. 13. DESIGNING A CONCURRENT APPLICATION A TEST DRIVE ▸ vim Emakefile ▸ erl -make ▸ erl -pa ebin/ ▸ add path for look in erlang module ▸ make:all([load]) ▸ find Emakefile -> recompile -> load {'src/*', [debug_info, {i, "src"}, {i, "include"}, {outdir, "ebin"}]}.
  • 52. 13. DESIGNING A CONCURRENT APPLICATION A TEST DRIVE 1> evserv:start(). <0.34.0> 2> evserv:subscribe(self()). {ok,#Ref<0.0.0.31>} 3> evserv:add_event("Hey there", "test", FutureDateTime). ok 4> evserv:listen(5). [] 5> evserv:cancel("Hey there"). ok 6> evserv:add_event("Hey there2", "test", NextMinuteDateTime). ok 7> evserv:listen(2000). [{done,"Hey there2","test"}]
  • 53. 13. DESIGNING A CONCURRENT APPLICATION ADDING SUPERVISION ▸ supervisor -module(sup). -export([start/2, start_link/2, init/1, loop/1]). start(Mod,Args) -> spawn(?MODULE, init, [{Mod, Args}]). start_link(Mod,Args) -> spawn_link(?MODULE, init, [{Mod, Args}]). init({Mod,Args}) -> process_flag(trap_exit, true), loop({Mod,start_link,Args}).
  • 54. 13. DESIGNING A CONCURRENT APPLICATION ADDING SUPERVISION ▸ supervisor loop({M,F,A}) -> Pid = apply(M,F,A), receive {'EXIT', _From, shutdown} -> exit(shutdown); % will kill the child too {'EXIT', Pid, Reason} -> io:format("Process ~p exited for reason ~p~n",[Pid,Reason]), loop({M,F,A}) end.
  • 55. 13. DESIGNING A CONCURRENT APPLICATION ADDING SUPERVISION ▸ using supervisor 1> c(evserv), c(sup). {ok,sup} 2> SupPid = sup:start(evserv, []). <0.43.0> 3> whereis(evserv). <0.44.0> 4> exit(whereis(evserv), die). true Process <0.44.0> exited for reason die 5> exit(whereis(evserv), die). Process <0.48.0> exited for reason die true
  • 56. 13. DESIGNING A CONCURRENT APPLICATION ADDING SUPERVISION ▸ using supervisor ▸ The supervisor demonstrated here is only the most basic form that exists and is not exactly fit for production environments compared to the real thing. 6> exit(SupPid, shutdown). true 7> whereis(evserv). undefined
  • 57. 13. DESIGNING A CONCURRENT APPLICATION NAMESPACES (OR LACK THERE OF) ▸ using prefix ▸ renamed to reminder_evserv, reminder_sup and reminder_event. ▸ Some programmers then decide to add a module, named after the application itself, which wraps common calls ▸ No need to synchronize them, no locks, no real main loop
  • 59. 14. WHAT IS OTP? IT’S THE OPEN TELECOM PLATFORM! ▸ meaning? ▸ OTP stands for Open Telecom Platform, although it's not that much about telecom anymore (it's more about software that has the property of telecom applications) ▸ erlang’s greatness comes from ▸ concurrency + distribution + error handling capabilities, and otp
  • 60. 14. WHAT IS OTP? IT’S THE OPEN TELECOM PLATFORM! ▸ There were a few 'gotchas' here and there ▸ on how to avoid race conditions or to always remember that a process could die at any time. There was also hot code loading, naming processes and adding supervisors, to name a few. ▸ The OTP framework takes care of this by grouping these essential practices ▸ Every Erlang programmer should use them
  • 61. 14. WHAT IS OTP? THE COMMON PROCESS, ABSTRACTED ▸ In most processes, we had a function in charge of spawning the new process, a function in charge of giving it its initial values, a main loop, etc. ▸ these parts are usually present
  • 62. 14. WHAT IS OTP? THE COMMON PROCESS, ABSTRACTED ▸ crafted code ▸ with the advantage of being used for years in the field ▸ also being built with far more caution than we were with our implementations. ▸ fault-tolerant manner
  • 63. 14. WHAT IS OTP? THE BASIC SERVER ▸ kitty_server %%%%% Naive version -module(kitty_server). -export([start_link/0, order_cat/4, return_cat/2, close_shop/1]). -record(cat, {name, color=green, description}). %%% Client API start_link() -> spawn_link(fun init/0).
  • 64. 14. WHAT IS OTP? THE BASIC SERVER ▸ kitty_server - api, order_cat %% Synchronous call order_cat(Pid, Name, Color, Description) -> Ref = erlang:monitor(process, Pid), Pid ! {self(), Ref, {order, Name, Color, Description}}, receive {Ref, Cat} -> erlang:demonitor(Ref, [flush]), Cat; {'DOWN', Ref, process, Pid, Reason} -> erlang:error(Reason) after 5000 -> erlang:error(timeout) end
  • 65. 14. WHAT IS OTP? THE BASIC SERVER ▸ kitty_server - api, return_cat %% This call is asynchronous return_cat(Pid, Cat = #cat{}) -> Pid ! {return, Cat}, ok. close_shop(Pid) -> Ref = erlang:monitor(process, Pid), Pid ! {self(), Ref, terminate}, receive {Ref, ok} -> erlang:demonitor(Ref, [flush]), ok; {'DOWN', Ref, process, Pid, Reason} -> erlang:error(Reason) after 5000 -> erlang:error(timeout) end.
  • 66. 14. WHAT IS OTP? THE BASIC SERVER ▸ kitty_server - server_fun, init, loop %%% Server functions init() -> loop([]). loop(Cats) -> receive {Pid, Ref, {order, Name, Color, Description}} -> if Cats =:= [] -> Pid ! {Ref, make_cat(Name, Color, Description)}, loop(Cats); Cats =/= [] -> % got to empty the stock Pid ! {Ref, hd(Cats)}, loop(tl(Cats)) end;
  • 67. 14. WHAT IS OTP? THE BASIC SERVER ▸ kitty_server - server_fun, loop2 {return, Cat = #cat{}} -> loop([Cat|Cats]); {Pid, Ref, terminate} -> Pid ! {Ref, ok}, terminate(Cats); Unknown -> %% do some logging here too io:format("Unknown message: ~p~n", [Unknown]), loop(Cats) end.
  • 68. 14. WHAT IS OTP? THE BASIC SERVER ▸ kitty_server - private server_fun %%% Private functions make_cat(Name, Col, Desc) -> #cat{name=Name, color=Col, description=Desc}. terminate(Cats) -> [io:format("~p was set free.~n",[C#cat.name]) || C <- Cats], ok.
  • 69. 14. WHAT IS OTP? THE BASIC SERVER ▸ kitty_server - private server_fun 1> c(kitty_server). {ok,kitty_server} 2> rr(kitty_server). [cat] 3> Pid = kitty_server:start_link(). <0.57.0> 4> Cat1 = kitty_server:order_cat(Pid, carl, brown, "loves to burn bridges"). #cat{name = carl,color = brown, description = "loves to burn bridges"} 5> kitty_server:return_cat(Pid, Cat1). ok
  • 70. 14. WHAT IS OTP? THE BASIC SERVER ▸ kitty_server - private server_fun 6> kitty_server:order_cat(Pid, jimmy, orange, "cuddly"). #cat{name = carl,color = brown, description = "loves to burn bridges"} 7> kitty_server:order_cat(Pid, jimmy, orange, "cuddly"). #cat{name = jimmy,color = orange,description = "cuddly"} 8> kitty_server:return_cat(Pid, Cat1). ok 9> kitty_server:close_shop(Pid). carl was set free. ok 10> kitty_server:close_shop(Pid). ** exception error: no such process or port in function kitty_server:close_shop/1
  • 71. 14. WHAT IS OTP? THE BASIC SERVER ▸ we can see patterns we've previously applied ▸ The sections where we set monitors up and down, apply timers, receive data, use a main loop, handle the init function, etc.
  • 72. 14. WHAT IS OTP? THE BASIC SERVER ▸ let’s generic~ -module(my_server). -compile(export_all). call(Pid, Msg) -> Ref = erlang:monitor(process, Pid), Pid ! {self(), Ref, Msg}, receive {Ref, Reply} -> erlang:demonitor(Ref, [flush]), Reply; {'DOWN', Ref, process, Pid, Reason} -> erlang:error(Reason) after 5000 -> erlang:error(timeout) end.
  • 73. 14. WHAT IS OTP? THE BASIC SERVER ▸ let’s generic~ %% Synchronous call order_cat(Pid, Name, Color, Description) -> my_server:call(Pid, {order, Name, Color, Description}). %% This call is asynchronous return_cat(Pid, Cat = #cat{}) -> Pid ! {return, Cat}, ok. %% Synchronous call close_shop(Pid) -> my_server:call(Pid, terminate).
  • 74. 14. WHAT IS OTP? THE BASIC SERVER ▸ next generic chunk is not obvious.. ▸ Note that every process we've written so far has a loop where all the messages are pattern matched loop(Module, State) -> receive Message -> Module:handle(Message, State) end. handle(Message1, State) -> NewState1; handle(Message2, State) -> NewState2; ... handle(MessageN, State) -> NewStateN.
  • 75. 14. WHAT IS OTP? THE BASIC SERVER ▸ async call / sync call ▸ It would be pretty helpful if our generic server implementation could provide a clear way to know which kind of call is which. ▸ we will need to match different kinds of messages in my_server:loop/2 ▸ add atom sync
  • 76. 14. WHAT IS OTP? THE BASIC SERVER ▸ async call / sync call call(Pid, Msg) -> Ref = erlang:monitor(process, Pid), Pid ! {sync, self(), Ref, Msg}, receive {Ref, Reply} -> erlang:demonitor(Ref, [flush]), Reply; {'DOWN', Ref, process, Pid, Reason} -> erlang:error(Reason) after 5000 -> erlang:error(timeout) end.
  • 77. 14. WHAT IS OTP? THE BASIC SERVER ▸ async call / sync call cast(Pid, Msg) -> Pid ! {async, Msg}, ok. loop(Module, State) -> receive {async, Msg} -> loop(Module, Module:handle_cast(Msg, State)); {sync, Pid, Ref, Msg} -> loop(Module, Module:handle_call(Msg, Pid, Ref, State)) end.
  • 78. 14. WHAT IS OTP? THE BASIC SERVER ▸ disappointing thing ▸ The programmers who will use my_server will still need to know about references when sending synchronous messages and replying to them. loop(Module, State) -> receive {async, Msg} -> loop(Module, Module:handle_cast(Msg, State)); {sync, Pid, Ref, Msg} -> loop(Module, Module:handle_call(Msg, {Pid, Ref}, State)) end.
  • 79. 14. WHAT IS OTP? THE BASIC SERVER ▸ and now, ▸ they can be passed as a single argument to the other function as a variable with a name like From. ▸ we'll provide a function to send replies that should understand what From contains. reply({Pid, Ref}, Reply) -> Pid ! {Ref, Reply}.
  • 80. 14. WHAT IS OTP? THE BASIC SERVER ▸ and now our code is, -module(my_server). -export([start/2, start_link/2, call/2, cast/2, reply/2]). start(Module, InitialState) -> spawn(fun() -> init(Module, InitialState) end). start_link(Module, InitialState) -> spawn_link(fun() -> init(Module, InitialState) end). …call.. cast… reply… init(Module, InitialState) -> loop(Module, Module:init(InitialState)). …loop…
  • 81. 14. WHAT IS OTP? THE BASIC SERVER ▸ kitty server 2 as, callback module -record(cat, {name, color=green, description}). start_link() -> my_server:start_link(?MODULE, []). order_cat(Pid, Name, Color, Description) -> my_server:call(Pid, {order, Name, Color, Description}). return_cat(Pid, Cat = #cat{}) -> my_server:cast(Pid, {return, Cat}). close_shop(Pid) -> my_server:call(Pid, terminate).
  • 82. 14. WHAT IS OTP? THE BASIC SERVER ▸ kitty server 2 as, callback module %%% Server functions init([]) -> []. %% no treatment of info here! handle_call({order, Name, Color, Description}, From, Cats) -> if Cats =:= [] -> my_server:reply(From, make_cat(Name, Color, Description)), Cats; Cats =/= [] -> my_server:reply(From, hd(Cats)), tl(Cats) end;
  • 83. 14. WHAT IS OTP? THE BASIC SERVER ▸ kitty server 2 as, callback module handle_call(terminate, From, Cats) -> my_server:reply(From, ok), terminate(Cats). handle_cast({return, Cat = #cat{}}, Cats) -> [Cat|Cats]. %%% Private functions make_cat(Name, Col, Desc) -> #cat{name=Name, color=Col, description=Desc}. terminate(Cats) -> [io:format("~p was set free.~n",[C#cat.name]) || C <- Cats], exit(normal).
  • 84. 14. WHAT IS OTP? SPECIFIC VS GENERIC ▸ now you understand OTP! ▸ taking all generic component ▸ extracting library… ▸ If you're going to have larger applications then it might be worth it to separate generic parts of your code from the specific sections. ▸ U have many server - client.. ▸ if all these servers share the same common my_server abstraction, you substantially reduce that complexity
  • 85. 14. WHAT IS OTP? SPECIFIC VS GENERIC ▸ This means you reduce a lot of time tracking and solving bugs ▸ when separating the generic from the specific is that we instantly made it much easier to test our individual modules. ▸ first kitty server need to spawn,..give right state… ▸ on the otherhand, requires us to run the function calls over the 'handle_call/3' and 'handle_cast/2'
  • 86. 14. WHAT IS OTP? SPECIFIC VS GENERIC ▸ when someone optimizes that single backend ▸ every process using it become faster! ▸ that's what happens with the OTP framework. ▸ we need to also consider to our module, (kitty) ▸ named processes, configuring the timeouts, adding debug information, what to do with unexpected messages, how to tie in hot code loading, handling specific errors, abstracting away the need to write most replies, handling most ways to shut a server down, making sure the server plays nice with supervisors, etc. ▸ the Erlang/OTP team managed to handle all of that for you with the gen_server behaviour