you will regret this
DESCRIPTION
A lightning talk given at the London Erlang Factory in 2011, discussing Erlang anti-patterns seen in real world applications.TRANSCRIPT
YOU WILL REGRET THIS!My Other Mood is 'Even More Angry'
Friday, June 10, 2011
I'M GONNA TELL YOU A STORYIn which I tell you how to behave
- how dare I?
Friday, June 10, 2011
SOCKET.IO-ERLANG
•Developed by Yurii Rashkovskii, Omar Yasin, Fred Hebert (me)
• Used as a base demo app for this presentation
• Allows to write neat front-ends for conversational websites
Friday, June 10, 2011
BIZARRO SOCKET.IO-ERLANG
• 'Bad' socket.io-erlang used for the presentation
• Freely substitutes dependencies and actual code for whatever purpose I have
Friday, June 10, 2011
APP STRUCTURE
Friday, June 10, 2011
APP STRUCTUREBunch of supervisors
Friday, June 10, 2011
APP STRUCTUREBunch of supervisors
web server
Friday, June 10, 2011
APP STRUCTUREBunch of supervisors
web servertransport handlers
Friday, June 10, 2011
APP STRUCTUREBunch of supervisors
web servertransport handlers
Client code attaches here
Friday, June 10, 2011
WE USE A WEB SERVER
•We need a web server (the slide's title says just that (and also the previous slide))
•Oh, Carrying parameters and a connection around is annoying!
• Let's use parametrised modules!
Friday, June 10, 2011
PARAMETRISED MODULES
-‐module(test_module, [Param1]).some_method() -‐> Param1.
Equivalent to:
-‐module(test_non_pmod).some_method(Param1) -‐> Param1.
Friday, June 10, 2011
PARAMETRISED MODULES
1> X = test_module:new(horror), X:some_method().horror
2> test_non_pmod:some_method(sane).sane
Friday, June 10, 2011
PARAMETRISED MODULES
• They are great!
•We can use them as if they were objects!
• They let us carry everything as one large parameter!
• Let's do this!
Friday, June 10, 2011
PARAMETRISED MODULES
• They are great!
•We can use them as if they were objects!
• They let us carry everything as one large parameter!
• Let's do this!
Friday, June 10, 2011
What?
Friday, June 10, 2011
I'LL TELL YOU WHAT
3> dbg:tp({X, some_method, 0}, [...]).** exception error: no case clause matching {test_module,horror}
4> dbg:tp({test_module, some_method, 0}, [...]).* never matches anything *
5> dbg:tp({test_module, some_method, 1}, [...]).* will actually match stuff *
Friday, June 10, 2011
What is this I don't even...
Friday, June 10, 2011
I'LL TELL YOU WHAT
• The parameters are global and they ghost values, become implicit function arguments. Errors out of nowhere.
• They're based on a old fun hack ({Mod, Fun}:(Args))
• They mess up the concept of arity
• They mess up tracing (previous slide!)
• They were added because some library accepts callback modules and nothing else but might still need state around. No other reason.
Friday, June 10, 2011
I'll use them anyway(in my server)
Friday, June 10, 2011
YOU PROBABLY SHOULDN'TBut you might not have a choice, so let's keep going
Friday, June 10, 2011
WHAT ELSE DO WE HAVE?
• A supervision tree, of course!
• Some of the supervisors are tricky and must interact with servers and dynamic children and ...
•Who starts who? By which API?
•We could probably just forget about supervisors, link stuff together and make it simpler
• Let's do this!
Friday, June 10, 2011
IN THIS VERY SLIDE I PRETEND I MAKE THE CHANGES
Friday, June 10, 2011
APP STRUCTURE
Friday, June 10, 2011
APP STRUCTUREtransport handlers
were moved and no longer need a supervisor.
They only use links.
The code is more straightforward!
Friday, June 10, 2011
APP STRUCTUREtransport handlers
were moved and no longer need a supervisor.
They only use links.
The code is more straightforward!
Friday, June 10, 2011
What?... my code is so much easier to read now!
Friday, June 10, 2011
I'LL TELL YOU WHAT
• You need to add ad-hoc start/restart policies and make sure orderly shutdowns work fine with just links. Care to add tests?
• You can no longer benefit from systool's application upgrades and downgrades as they depend on supervisors
• You will need to take your app down!
Friday, June 10, 2011
It's okay, I'll do rolling upgrades through all nodesthis should avoid downtime
Friday, June 10, 2011
NOT WITH LIVE SESSIONS!Nobody likes to be disconnected during a conversation!
Would you disconnect this guy?
Friday, June 10, 2011
NOT WITH LIVE SESSIONS!Nobody likes to be disconnected!
Stolen from Yurii's talk earlier today
Friday, June 10, 2011
NOT WITH LIVE SESSIONS!Nobody likes to be disconnected!
Stolen from Yurii's talk earlier today
Friday, June 10, 2011
You're killing me. I'll leave the change in. Code is meant to be
read first!
Friday, June 10, 2011
OK, AS LONG AS YOU LISTEN TO THE NEXT POINT
Friday, June 10, 2011
SURE, I'M HAPPY WITH MY APP
• It's all done in OTP
•Now Easier to read
• Uses parametrized modules, hell yes!
• It's time to start it!
• Let's do this!
Friday, June 10, 2011
THIS IS GONNA BE FUN
main(_) -> appmon:start(), sasl:start(normal, []), socketio:start(normal,[]), {ok, Pid} = socketio_listener:start([ {http_port, 7878}, {default_http_handler,?MODULE}]), EventMgr = socketio_listener:event_manager(Pid), ok = gen_event:add_handler(EventMgr, ?MODULE,[]), receive _ -> ok end.
And it works!(believe me)
Friday, June 10, 2011
THIS IS GONNA BE FUN
main(_) -> appmon:start(), sasl:start(normal, []), socketio:start(normal,[]), {ok, Pid} = socketio_listener:start([ {http_port, 7878}, {default_http_handler,?MODULE}]), EventMgr = socketio_listener:event_manager(Pid), ok = gen_event:add_handler(EventMgr, ?MODULE,[]), receive _ -> ok end.
And it works!(believe me)
Friday, June 10, 2011
YOU, AGAIN!?You are worse than clippy
What is it this time?
Friday, June 10, 2011
I'LL TELL YOU WHAT
• The VM starts all applications under the Application Controller
• Starting one outside of it means it is not supervised by it
•No app failure strategy (permanent, transient, temporary)
•No access to 'env' variables
•No respect of start phasesor dependencies
Friday, June 10, 2011
AND IT GETS WORSE•With bad default values (or overly defensive code) for env
variables, bad things happen...
• In this case, infinitely many web sockets opened for each client(before a patch to change that, because I forgot to listen to this hint)
Friday, June 10, 2011
DO THIS INSTEAD
main(_) -> appmon:start(), application:start(sasl), application:start(misultin), application:start(socketio), {ok, Pid} = socketio_listener:start([ {http_port, 7878}, {default_http_handler,?MODULE}]), EventMgr = socketio_listener:event_manager(Pid), ok = gen_event:add_handler(EventMgr, ?MODULE,[]), receive _ -> ok end.
And it works better!(believe me)
Friday, June 10, 2011
Oh...
Friday, June 10, 2011
RIGHTYour OTP code is not worth much without that
Friday, June 10, 2011
One more thing...
Friday, June 10, 2011
DON'T LISTEN TO MEIf your product might not ship because of this.Making it work is #1. Making it pretty is not.
Friday, June 10, 2011
HAPPY HACKINGHopefully you won't regret this
Friday, June 10, 2011