1 hour dive into erlang/otp
DESCRIPTION
Introduction to Erlang and OTPTRANSCRIPT
1 hour dive into Erlang/OTP
@jvalduvieco @jordillonch
Problem domain
Lots of users
Lots of users
24x7x365
24x7x365
Lots of critical concurrent transactions
Lots of critical concurrent transactions
Hardware or softwarebreaks
Hardware or softwarebreaks
Lots of code changes
Lots of code changes
UnscalableUnmaintainable } code
UnscalableUnmaintainable } code
Maintenance/Debugin
production system
Maintenance/Debugin
production system
Does it sound to you?
The Erlang solution
Simplicity...
Minimize defensive programming
Typeless variables
Develop by contract
t-shirt function size
If����������� ������������������ a����������� ������������������ function����������� ������������������ does����������� ������������������ not����������� ������������������ fit����������� ������������������ on����������� ������������������ your����������� ������������������ t-shirt����������� ������������������ it����������� ������������������ is����������� ������������������ too����������� ������������������ long!
Single responsibility principle
No shared state between entities
High Concurrency
High ConcurrencyHigh concurrency
Light threads
Light threadshundreds of thousands of threads in one
machine with a good cpu scheduler
Light threadshundreds of thousands of threads in one
machine with a good cpu scheduler
Lt
Lt
Lt
Lt
Message passing
Lt
Lt
Lt
Message passingA shared nothing architecture that
communicates through message passing
Lt
Lt
Lt
Message passingA shared nothing architecture that
communicates through message passing
Lt
Lt
Lt
Process Mailbox
Lt
Lt
Lt
Process MailboxEvery process has a mailbox with incoming
messages, process take on convenience
Lt
Lt
Lt
No shared state
Lt
LtS
S
S
Lt
No shared stateEvery process its own internal state stored in
a variable avoiding lock contention
Lt
LtS
S
S
Soft realtime
Soft realtime
You have no strict guarantees on latency but language is designed
to have low latency
High availability
High availabilityHigh availability
Pa
Supervised processes
Pb
Pa
Supervised processesprocesses can be monitored by other
processes, handling its termination
Pb
Pb
Fail early
Pa
S
Pb
Fail earlyFail as soon as possible and let someone handle bad data, someone will restart you
Pa
S
Fail earlyFail as soon as possible and let someone handle bad data, someone will restart you
Pa
Pb2
S
Hot code update
Pa v1
S
Pb
Pc
Hot code updateprocesses code and data can be replaced
without loosing service
Pa v1
S
Pb
Pc
Hot code updateprocesses code and data can be replaced
without loosing service
Pa v1Pa v2
S
Pb
Pc
P
Distribution
Node
P
PP
P
Node
P
P
P
PP PP
P
DistributionProcesses run on nodes and can be located
wherever they are
Node
P
PP
P
Node
P
P
P
PP PP
How does it look like?
Show me the code!
Demo 1
Hands on
The shell
Type on your console:
erl
You should see:Erlang R16B (erts-5.10.1) [source] [64-bit] [smp:2:2] [async-threads:10] [hipe] [kernel-poll:false] [dtrace]
Eshell V5.10.1 (abort with ^G)1>
Variables
Variables start Uppercase
Variables are immutable
Can contain any type
You can do things like...
1> Foo = 1.12> Foo = 2.** exception error: no match of right hand side value 2
1> Foo = 1.12> Foo = 2.** exception error: no match of right hand side value 2
Foo����������� ������������������ is����������� ������������������ bounded����������� ������������������ to����������� ������������������ 1
1> Foo = 1.12> Foo = 2.** exception error: no match of right hand side value 2
Foo����������� ������������������ is����������� ������������������ bounded����������� ������������������ to����������� ������������������ 1
Foo����������� ������������������ ==����������� ������������������ 2����������� ������������������ ?
1> Foo = 1.12> Bar = 2.23> Foo = Bar.** exception error: no match of right hand side value 2
This is GREAT!
Now you have your basic error checking system implemented
Advanced types
[List]
[1,2,3,4,5,6]
You can do things like...
Iterate sequentially
1> MyList = [1,2,3,4].[1,2,3,4]2> [Head|Tail] = MyList.[1,2,3,4]3> Head.14> Tail.[2,3,4]
1> MyList = [1,2,3,4].[1,2,3,4]2> [Head|Tail] = MyList.[1,2,3,4]3> Head.14> Tail.[2,3,4]
1> MyList = [1,2,3,4].[1,2,3,4]2> [Head|Tail] = MyList.[1,2,3,4]3> Head.14> Tail.[2,3,4]
Do something to all or some items on a list
(list comprehensions)
1> MyList = [1, 2, 3, 4].[1,2,3,4]2> [X + 2 || X <- MyList, X > 2].[5,6]
[Strings]
A list
You can do things like...
1> MyString = "Erlang is not Ruby"."Erlang is not Ruby"
1> MyString = "Erlang is not Ruby"."Erlang is not Ruby"2> [Head2|Tail2] = MyString."Erlang is not Ruby"3> Head2.694> Tail2."rlang is not Ruby"
ASC����������� ������������������ =����������� ������������������ “E”
{Tuples}
{1,2,3}
Basic data container
random access
matcheable
You can do things like...
1> Mytuple = {1,2,3,4}.{1,2,3,4}2> A = 1.13> B = 2.24> {A,B,C,D} = {1,2,3,4}.{1,2,3,4}5> C.36> D.4
1> Mytuple = {1,2,3,4}.{1,2,3,4}2> A = 1.13> B = 2.24> {A,B,C,D} = {1,2,3,4}.{1,2,3,4}5> C.36> D.4
A����������� ������������������ and����������� ������������������ B����������� ������������������ arebounded����������� ������������������ variables
1> Mytuple = {1,2,3,4}.{1,2,3,4}2> A = 1.13> B = 2.24> {A,B,C,D} = {1,2,3,4}.{1,2,3,4}5> C.36> D.4
A����������� ������������������ and����������� ������������������ B����������� ������������������ arebounded����������� ������������������ variables
pattern����������� ������������������ matchingA==1?B==2?
1> Mytuple = {1,2,3,4}.{1,2,3,4}2> A = 1.13> B = 2.24> {A,B,C,D} = {1,2,3,4}.{1,2,3,4}5> C.36> D.4
A����������� ������������������ and����������� ������������������ B����������� ������������������ arebounded����������� ������������������ variables
pattern����������� ������������������ matchingA==1?B==2?
C����������� ������������������ and����������� ������������������ D����������� ������������������ are����������� ������������������ unbounded����������� ������������������ variables
functions
functions are types
single exit point
You can do things like...
foo_bar_func(Foo, Bar) -> Result = Foo + Bar, Result.
foo_bar_func(Foo, Bar) -> Result = Foo + Bar, Result.
This����������� ������������������ is����������� ������������������ a����������� ������������������ arity����������� ������������������ 2����������� ������������������ function����������� ������������������ (2����������� ������������������ parameters)
foo_bar_func(Foo, Bar) -> Result = Foo + Bar, Result.
This����������� ������������������ is����������� ������������������ a����������� ������������������ arity����������� ������������������ 2����������� ������������������ function����������� ������������������ (2����������� ������������������ parameters)
means����������� ������������������ that����������� ������������������ more����������� ������������������ code����������� ������������������ is����������� ������������������ to����������� ������������������ come
foo_bar_func(Foo, Bar) -> Result = Foo + Bar, Result.
This����������� ������������������ is����������� ������������������ a����������� ������������������ arity����������� ������������������ 2����������� ������������������ function����������� ������������������ (2����������� ������������������ parameters)
means����������� ������������������ that����������� ������������������ more����������� ������������������ code����������� ������������������ is����������� ������������������ to����������� ������������������ come
means����������� ������������������ the����������� ������������������ function����������� ������������������ code����������� ������������������ has����������� ������������������ ended
foo_bar_func(Foo, Bar) -> Result = Foo + Bar, Result.
Single����������� ������������������ exit����������� ������������������ pointReturns����������� ������������������ Result
This����������� ������������������ is����������� ������������������ a����������� ������������������ arity����������� ������������������ 2����������� ������������������ function����������� ������������������ (2����������� ������������������ parameters)
means����������� ������������������ that����������� ������������������ more����������� ������������������ code����������� ������������������ is����������� ������������������ to����������� ������������������ come
means����������� ������������������ the����������� ������������������ function����������� ������������������ code����������� ������������������ has����������� ������������������ ended
1> FooBar = fun(Foo, Bar) ->1> Foo + Bar1> end.#Fun<erl_eval.12.82930912>2> Result = FooBar(1, 2).3
atoms
A constant with name
lowercase
You can do things like...
1> ok.ok2> ko.ko3> ok =:= ko.false4> ok =:= ok.true
1> MyFuncOK = fun() -> {ok, 33} end.#Fun<erl_eval.20.82930912>2> MyFuncFail = fun() -> {error, bad_arg} end.#Fun<erl_eval.20.82930912>
3> {ok, Result} = MyFuncOK().{ok,33}4> {ok, Result2} = MyFuncFail().** exception error: no match of right hand side value {error,bad_arg}
1> MyFuncOK = fun() -> {ok, 33} end.#Fun<erl_eval.20.82930912>2> MyFuncFail = fun() -> {error, bad_arg} end.#Fun<erl_eval.20.82930912>
3> {ok, Result} = MyFuncOK().{ok,33}4> {ok, Result2} = MyFuncFail().** exception error: no match of right hand side value {error,bad_arg}
atoms
1> MyFuncOK = fun() -> {ok, 33} end.#Fun<erl_eval.20.82930912>2> MyFuncFail = fun() -> {error, bad_arg} end.#Fun<erl_eval.20.82930912>
3> {ok, Result} = MyFuncOK().{ok,33}4> {ok, Result2} = MyFuncFail().** exception error: no match of right hand side value {error,bad_arg}
atoms
errorchecking}
1> MyFuncOK = fun() -> {ok, 33} end.#Fun<erl_eval.20.82930912>2> MyFuncFail = fun() -> {error, bad_arg} end.#Fun<erl_eval.20.82930912>
3> {ok, Result} = MyFuncOK().{ok,33}4> {ok, Result2} = MyFuncFail().** exception error: no match of right hand side value {error,bad_arg}
atoms
errorchecking}
do����������� ������������������ they����������� ������������������ match?
modules
basic name spacing
public/private functions
You can do things like...
-module(cool_func).
-export([foo_bar_func/2]).
foo_bar_func (Foo, Bar) -> Result = Foo + Bar, {ok, Result}.
On your ${EDITOR} create cool_func.erl
On erlang shell type:
1> c("cool_module").{ok,cool_module}2> {ok, Result3} = cool_module:sum(33, 44).{ok,77}3> Result3.77
Too easy?
Let’s add some pattern matching on parameters!
area({square, Side}) -> {ok,Side * Side};area({circle, Radius}) -> % almost :-) {ok, 3 * Radius * Radius};area({triangle, A, B, C}) -> S = (A + B + C)/2, {ok, math:sqrt(S*(S-A)*(S-B)*(S-C))};area(Other) -> {error, invalid_object}.
area({square, Side}) -> {ok,Side * Side};area({circle, Radius}) -> % almost :-) {ok, 3 * Radius * Radius};area({triangle, A, B, C}) -> S = (A + B + C)/2, {ok, math:sqrt(S*(S-A)*(S-B)*(S-C))};area(Other) -> {error, invalid_object}.
means����������� ������������������ that����������� ������������������ there����������� ������������������ is����������� ������������������ another����������� ������������������ matching����������� ������������������
posibility
area({square, Side}) -> {ok,Side * Side};area({circle, Radius}) -> % almost :-) {ok, 3 * Radius * Radius};area({triangle, A, B, C}) -> S = (A + B + C)/2, {ok, math:sqrt(S*(S-A)*(S-B)*(S-C))};area(Other) -> {error, invalid_object}.
means����������� ������������������ that����������� ������������������ there����������� ������������������ is����������� ������������������ another����������� ������������������ matching����������� ������������������
posibility
mymodule:area({square, 10}).mymodule:area({circle, 10}).mymodule:area({triangle, 2, 2, 3.5}).
Want more?
Let’s add some recursion!
Want more?
Let’s add some recursion!
Erlang does not use loops
factorial(0) -> 1;factorial(N) -> N * factorial(N-1).
OTP
Oh, This is Perfect!
OTP is a set of rock solid architecture patterns, practices and tools
Improves the design, fault tolerance and
deployment of your app
Erlang is just a language, OTP makes it great for
the real world
Basic architecture patterns
Supervisor
S
P P P S
P P
Supervisor
S
P P P S
P P
Supervisor spawns processes and handles its death
gen_server
gs
P
P
P
gen_server
gs
P
P
P
Generic single threaded server
gen_fsm
gf
P
P
P
{S}
gf
gen_fsm
P
P
P
{S}
Generic Finite State Machine
gen_event
em
P
P
P
PP
P
gen_event
em
P
P
P
PP
P
Event handler, you can subscribe to events
More on OTP...
• File hierarchy
• Applications
• Releases
• Basic abstraction libraries (logging, system...)
Let’s see a gen_server in action!
Introducing Simple Key Value Store
A server that is able to store {Key,
Value} and retrieve them by Key
Demo II
ets
S
gsP
skvs diagram
ets
S
gsP
skvs diagram
Starting skvs
Go to skvs source directory
Compile./rebar compile
Start the Erlang nodeerl -pa ebin
Start the appapplication:start(skvs).
Some commands
Set a value
skvs_server:set(“Key”,”Value”).
skvs_server:set(“Key2”,”Value2”).
Get a value
skvs_server:get(“Key2”).
start_link() -> gen_server:start_link({local, skvs}, skvs_server, [], []).
get(Key) -> gen_server:call(skvs, {get, Key}).
set(Key,Value) -> gen_server:call(skvs, {set, Key, Value}).
set_fire_and_forget(Key,Value) -> gen_server:cast(skvs, {set, Key, Value}).
Code on client: skvs_server.erl
start_link() -> gen_server:start_link({local, skvs}, skvs_server, [], []).
get(Key) -> gen_server:call(skvs, {get, Key}).
set(Key,Value) -> gen_server:call(skvs, {set, Key, Value}).
set_fire_and_forget(Key,Value) -> gen_server:cast(skvs, {set, Key, Value}).
Code on client: skvs_server.erl
start����������� ������������������ gen_server
start_link() -> gen_server:start_link({local, skvs}, skvs_server, [], []).
get(Key) -> gen_server:call(skvs, {get, Key}).
set(Key,Value) -> gen_server:call(skvs, {set, Key, Value}).
set_fire_and_forget(Key,Value) -> gen_server:cast(skvs, {set, Key, Value}).
Code on client: skvs_server.erl
start����������� ������������������ gen_server
sync����������� ������������������ call����������� ������������������ to����������� ������������������ server(waits����������� ������������������ for����������� ������������������ reply)
start_link() -> gen_server:start_link({local, skvs}, skvs_server, [], []).
get(Key) -> gen_server:call(skvs, {get, Key}).
set(Key,Value) -> gen_server:call(skvs, {set, Key, Value}).
set_fire_and_forget(Key,Value) -> gen_server:cast(skvs, {set, Key, Value}).
Code on client: skvs_server.erl
start����������� ������������������ gen_server
async����������� ������������������ call����������� ������������������ to����������� ������������������ server(fire����������� ������������������ &����������� ������������������ forget)
sync����������� ������������������ call����������� ������������������ to����������� ������������������ server(waits����������� ������������������ for����������� ������������������ reply)
%% Client Callbacks on server%% Sync calls, expects responsehandle_call({set, Key, Value}, _From,State) -> {reply, set_value(Key,Value), State};handle_call({get, Key}, _From, State) -> {reply, get_value(Key), State}.
%% Async calls, do not expect responsehandle_cast({set, Key, Value}, State) -> set_value(Key,Value), {noreply, State}.
Callback code: skvs_server.erl
%% Client Callbacks on server%% Sync calls, expects responsehandle_call({set, Key, Value}, _From,State) -> {reply, set_value(Key,Value), State};handle_call({get, Key}, _From, State) -> {reply, get_value(Key), State}.
%% Async calls, do not expect responsehandle_cast({set, Key, Value}, State) -> set_value(Key,Value), {noreply, State}.
Callback code: skvs_server.erl
return����������� ������������������ value
%% Client Callbacks on server%% Sync calls, expects responsehandle_call({set, Key, Value}, _From,State) -> {reply, set_value(Key,Value), State};handle_call({get, Key}, _From, State) -> {reply, get_value(Key), State}.
%% Async calls, do not expect responsehandle_cast({set, Key, Value}, State) -> set_value(Key,Value), {noreply, State}.
Callback code: skvs_server.erl
return����������� ������������������ valueSurvives����������� ������������������ between����������� ������������������
requests
%% Private functionsset_value(Key, Value) -> % Insert Key, Value into ETS. % Fail early {ok,Result}=case ets:insert(data_store,{Key,Value}) of true -> {ok, {Key,Value}}; {error, Reason} -> {error, Reason} end, Result.
Actual work...: skvs_server.erl
%% Private functionsset_value(Key, Value) -> % Insert Key, Value into ETS. % Fail early {ok,Result}=case ets:insert(data_store,{Key,Value}) of true -> {ok, {Key,Value}}; {error, Reason} -> {error, Reason} end, Result.
Actual work...: skvs_server.erl
ETS����������� ������������������ is����������� ������������������ a����������� ������������������ Key����������� ������������������ value����������� ������������������ store����������� ������������������ in����������� ������������������ RAM
Use cases
Gaming Industry
Gaming Industry
Messaging / IM
Messaging / IM
Payments
Payments
Databases
Databases
Others
Others
Some day...
Every highly interactive website? ;)
Every highly interactive website? ;)
Hi
Hey
HelloPayOuch!
!BufNO!
Would you...
Internet of things
And now what?
Install Erlang/OTP!
https://www.erlang-solutions.com/downloads/download-erlang-otp
Use a great IDE• IntelliJ + Erlang (plugin)
• Sublime Text + SublimErl
• Emacs
Read some books
RTFM
• http://www.erlang.org/doc.html
• http://erldocs.com/
Join mailing lists
• Official Erlang mailing list
• http://erlang.org/mailman/listinfo/erlang-questions
• Join Barcelona Erlang user group on google groups
Find know-how
• Check http://www.erlang-factory.com/ videos
• Search for Erlang conferences on slideshare
• Pray for an http://erlangcamp.com/ near your city
Read some code
This is the result of 6 months of fun learning Erlang/OTP
We are looking for awesome projects
http://es.linkedin.com/in/jllonch
http://es.linkedin.com/in/jvalduvieco
Thank you!
https://github.com/jvalduvieco/betabeers_201303
Thank you!
we����������� ������������������ hope����������� ������������������ you����������� ������������������ feel����������� ������������������ like����������� ������������������ him����������� ������������������ :)
(we����������� ������������������ did)
https://github.com/jvalduvieco/betabeers_201303
Erlang, The Movie
http://www.youtube.com/watch?v=uKfKtXYLG78
Images sourceshttp://diromero.wordpress.com/2011/10/07/home-automation/http://iffergan.com/http://technode.com/2012/05/14/internet-of-things-not-just-a-concept-for-fund-raising/http://modernherstory.wordpress.com/2011/05/18/open-minds-open-hearts/http://www.i-m.co/eviemouse/problemsolved/http://strategicsalesmarketingosmg.wordpress.com/2012/06/25/who-are-twitter-users/http://www.secureworks.com/it_security_services/advantage/soc/http://labourlist.org/2011/11/my-biggest-worry-about-labour%E2%80%99s-future/broken-chain/http://prothemedesign.com/how-to/why-you-should-keep-wordpress-and-your-plugins-up-to-date/attachment/matrix-code-update/http://thegapbetweentwoworlds.com/category/career-transitionhttp://www.wingweb.co.uk/Images/697/KC-10_Extender_SR-71_Blackbirdhttp://www.tonywoodtraining.com/2010/11/29/motivation-to-exercise-and-eat-right/http://portalmie.com/blog/6/2011/09/kushimoto-diving-park-tokushima-revista-no-7/http://www.bcsagroup.com/http://www.losemyaccent.com/tag/hand/http://articulo.mercadolibre.com.ar/MLA-450970296-cortaplumas-victorinox-huntsman-15-usos-navaja-origen-suizo-_JMhttp://openclipart.org/detail/4112/http://blog-en.coaching-go.com/2012/02/learn-to-say-no-and-know-how-to-say-yes/ok-2/http://en.wikipedia.org/wiki/File:We_Can_Do_It!.jpghttp://triniblog.wordpress.com/tag/laberintos/http://www.catskillsnyrealestate.com/Want-More-Info-Catskill-Real-Estate.phphttp://www.thelovelyplanet.net/lush-green-images-planet-earth/http://www.growthmax.com/how-exactly-does-growthmax-plus-make-you-grow-taller/http://www.ayurvedalive.in/keep-your-eyes-healthy-beautifulhttp://my.mmosite.com/510619/blog/item/lord_of_the_rings_online.htmlhttp://scifistorm.org/2010/03/24/lord-of-the-rings-blu-ray-review/http://www.123rf.com/photo_15612022_3d-cartoon-bug.htmlhttp://www.airliners.net/photo/1134244/L/http://www.muypymes.com/2009/12/04/moleskine-mucho-mas-que-una-agenda-personalhttp://learnyousomeerlang.com/the-hitchhikers-guide-to-concurrencyhttp://planetpooks.com/one-more-reason-to-love-hermiones-handbag/