Elixir Elevated: The Ups and Downs of OTP at ElixirConf2014
-
Upload
greg-vaughn -
Category
Software
-
view
493 -
download
5
description
Transcript of Elixir Elevated: The Ups and Downs of OTP at ElixirConf2014
Elixir Elevated!The Ups and Downs of OTP
Greg [email protected]!
twitter: @gregvaughn, github/irc: gvaughn
Student of Elixir and OTP!Hobbying with Elixir almost 13 months!Texan!Professional Programmer of 20 years!Across 6 languages!Employed by LivingSocial
Student of Elixir and OTP!Hobbying with Elixir almost 13 months!Texan!Professional Programmer of 20 years!Across 6 languages!Employed by LivingSocial
LivingSocial is Hiring!
OTP is …
Mature / Battle Tested for 16 (18?) years
Microservices
Object Oriented (NOT class oriented)
OTP is …
Mature / Battle Tested for 16 (18?) years
Microservices
Object Oriented (NOT class oriented)
Actor
OTP is …
Mature / Battle Tested for 16 (18?) years
Microservices
Object Oriented (NOT class oriented)
Actor
Framework (Hollywood Principle)
OTP is …
Mature / Battle Tested for 16 (18?) years
Microservices
Object Oriented (NOT class oriented)
Actor
Framework (Hollywood Principle)
Design Patterns
OTP is …
Mature / Battle Tested for 16 (18?) years
Microservices
Object Oriented (NOT class oriented)
Actor
Framework (Hollywood Principle)
Design Patterns
Robust
object oriented
OOP to me means only messaging, local retention and protection and !
hiding of state-process, and extreme late-binding of all things. — Alan Kay
object oriented
OOP to me means only messaging, local retention and protection and !
hiding of state-process, and extreme late-binding of all things. — Alan Kay
functional
a style of building the structure and elements of computer programs that treats computation as the evaluation of mathematical functions and avoids state and mutable data. — Wikipedia
object oriented
OOP to me means only messaging, local retention and protection and !
hiding of state-process, and extreme late-binding of all things. — Alan Kay
functional
a style of building the structure and elements of computer programs that treats computation as the evaluation of mathematical functions and avoids state and mutable data. — Wikipedia
concurrent
The conceptually simultaneous execution of more than one sequential program on a computer or network of computers. — McGraw-Hill Sci & Tech
Dictionary
Behaviours: Don’t call us, we’ll call you
defmodule MyCallback do use GenServer end
iex> {:ok, pid} = GenServer.start(MyCallback, [])
Behaviours: Don’t call us, we’ll call you
defmodule MyCallback do use GenServer end
iex> {:ok, pid} = GenServer.start(MyCallback, [])
defmodule GenServer do defmacro __using__(_) do quote do @behaviour :gen_server ! def init(args), do: {:ok, args} ! def handle_cast(msg, state), do: {:stop, {:bad_cast, msg}, state} ! def handle_call(msg, _from, state), do: {:stop, {:bad_call, msg}, state} ! def handle_info(_msg, state), do: {:noreply, state} ! def terminate(_reason, _state), do: :ok ! def code_change(_old, state, _extra), do: {:ok, state} ! defoverridable [init: 1, handle_call: 3, handle_info: 2, handle_cast: 2, terminate: 2, code_change: 3] end end … end
defmodule MyCallback do use GenServer @initial_state %{} ! def start_link do GenServer.start_link(__MODULE__, @initial_state) end ! def init(arg) do state = arg {:ok, state} end ! def do_it(pid, param) do GenServer.call(pid, {:do_it, param}) end ! def handle_call({:do_it, param}, _from, state) do payload = get_payload(param, state) new_state = update_state(param, state) {:reply, payload, new_state} end ! defp get_payload(param, state), do: “I DONE DID IT!” ! defp update_state(param, state), do: state end
defmodule MyCallback do use GenServer @initial_state %{} ! def start_link do GenServer.start_link(__MODULE__, @initial_state) end ! def init(arg) do state = arg {:ok, state} end ! def do_it(pid, param) do GenServer.call(pid, {:do_it, param}) end ! def handle_call({:do_it, param}, _from, state) do payload = get_payload(param, state) new_state = update_state(param, state) {:reply, payload, new_state} end ! defp get_payload(param, state), do: “I DONE DID IT!” ! defp update_state(param, state), do: state end
defmodule MyCallback do use GenServer @initial_state %{} ! def start_link do GenServer.start_link(__MODULE__, @initial_state) end ! def init(arg) do state = arg {:ok, state} end ! def do_it(pid, param) do GenServer.call(pid, {:do_it, param}) end ! def handle_call({:do_it, param}, _from, state) do payload = get_payload(param, state) new_state = update_state(param, state) {:reply, payload, new_state} end ! defp get_payload(param, state), do: “I DONE DID IT!” ! defp update_state(param, state), do: state end
defmodule MyCallback do use GenServer @initial_state %{} ! def start_link do GenServer.start_link(__MODULE__, @initial_state) end ! def init(arg) do state = arg {:ok, state} end ! def do_it(pid, param) do GenServer.call(pid, {:do_it, param}) end ! def handle_call({:do_it, param}, _from, state) do payload = get_payload(param, state) new_state = update_state(param, state) {:reply, payload, new_state} end ! defp get_payload(param, state), do: “I DONE DID IT!” ! defp update_state(param, state), do: state end
defmodule MyCallback do use GenServer @initial_state %{} ! def start_link do GenServer.start_link(__MODULE__, @initial_state) end ! def init(arg) do state = arg {:ok, state} end ! def do_it(pid, param) do GenServer.call(pid, {:do_it, param}) end ! def handle_call({:do_it, param}, _from, state) do payload = get_payload(param, state) new_state = update_state(param, state) {:reply, payload, new_state} end ! defp get_payload(param, state), do: “I DONE DID IT!” ! defp update_state(param, state), do: state end
Clie
nt P
roce
ssServer Process
A rider on any floor presses the up or down button!An elevator car arrives!Rider enters and presses a destination floor button
rider hall!signal
hall!signal car
carrider
floor hail
retrieve
arrival
arrivalgo to
A rider on any floor presses the up or down button!An elevator car arrives!Rider enters and presses a destination floor button
rider hall!signal
hall!signal car
carrider
floor hail
retrieve
arrival
arrivalgo to
Hailstruct
Let It Fail … and Respond
Separation of Concerns!
Think Long and Hard about Failure Response!
BEAM (not OS) Processes!
Finer Grained Control
Prepare to Fail
Car!Supervisor
Car 1 Car n…
one_for_one
Gen!Event
Hall!Signal
Bank!Supervisor
rest_for_one
Prepare to Fail
Gen!Event HS
Bank A!Supervisor
CSGen!
Event HS
Bank B!Supervisor
CS
Elevator!Supervisor
one_for_one
Prepare to Fail
Gen!Event HS
Bank A!Supervisor
CSGen!
Event HS
Bank B!Supervisor
CS
Elevator!Supervisor
one_for_one
GenEvent
GenEvent
Don’t Tripdefmodule MySupervisor do use Supervisor ! def init(…) do workers = worker(MyCallback, [p1, p2, [name: :myc]], [id: :mine]) supervise(workers, strategy: one_for_one) end end !defmodule MyCallback do use GenServer ! def start_link(p1, p2, opts \\ []) GenServer.start_link(__MODULE__, [p1, p2], opts) end ! def init([p1, p2]) do {:ok, %{p1: p1, p2: p2}} end end
Don’t Tripdefmodule MySupervisor do use Supervisor ! def init(…) do workers = worker(MyCallback, [p1, p2, [name: :myc]], [id: :mine]) supervise(workers, strategy: one_for_one) end end !defmodule MyCallback do use GenServer ! def start_link(p1, p2, opts \\ []) GenServer.start_link(__MODULE__, [p1, p2], opts) end ! def init([p1, p2]) do {:ok, %{p1: p1, p2: p2}} end end
apply: list of params
Don’t Tripdefmodule MySupervisor do use Supervisor ! def init(…) do workers = worker(MyCallback, [p1, p2, [name: :myc]], [id: :mine]) supervise(workers, strategy: one_for_one) end end !defmodule MyCallback do use GenServer ! def start_link(p1, p2, opts \\ []) GenServer.start_link(__MODULE__, [p1, p2], opts) end ! def init([p1, p2]) do {:ok, %{p1: p1, p2: p2}} end end
apply: list of params
single term for init/1
Trip-less Convention?defmodule MySupervisor do use Supervisor ! def init(…) do workers = worker(MyCallback, [{p1, p2}, name: :myc], [id: :mine]) supervise(workers, strategy: one_for_one) end end !defmodule MyCallback do use GenServer ! def start_link(init_params, opts \\ []) GenServer.start_link(__MODULE__, init_params, opts) end ! def init({p1, p2}) do {:ok, %{p1: p1, p2: p2}} end end
Takeaways
Behaviours vs. Callback Modules!
Watch your initialization steps!
Watch parameter and return value contracts!
Supervisors and Strategies!
Config
Thank you
Elixir Elevated!The Ups and Downs of OTP!!Greg [email protected]!twitter: @gregvaughn!github/irc: gvaughn
http://github.com/gvaughn/elixir_elevated/tree/elixirconf2014