YOU ARE DOWNLOADING DOCUMENT

Please tick the box to continue:

Transcript
Page 1: 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

Page 2: Elixir Elevated: The Ups and Downs of OTP at ElixirConf2014

Student of Elixir and OTP!Hobbying with Elixir almost 13 months!Texan!Professional Programmer of 20 years!Across 6 languages!Employed by LivingSocial

Page 3: Elixir Elevated: The Ups and Downs of OTP at ElixirConf2014

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!

Page 4: Elixir Elevated: The Ups and Downs of OTP at ElixirConf2014

OTP is …

Page 5: Elixir Elevated: The Ups and Downs of OTP at ElixirConf2014

OTP is …

Mature / Battle Tested for 16 (18?) years

Page 6: Elixir Elevated: The Ups and Downs of OTP at ElixirConf2014

OTP is …

Mature / Battle Tested for 16 (18?) years

Microservices

Page 7: Elixir Elevated: The Ups and Downs of OTP at ElixirConf2014

OTP is …

Mature / Battle Tested for 16 (18?) years

Microservices

Object Oriented (NOT class oriented)

Page 8: Elixir Elevated: The Ups and Downs of OTP at ElixirConf2014

OTP is …

Mature / Battle Tested for 16 (18?) years

Microservices

Object Oriented (NOT class oriented)

Actor

Page 9: Elixir Elevated: The Ups and Downs of OTP at ElixirConf2014

OTP is …

Mature / Battle Tested for 16 (18?) years

Microservices

Object Oriented (NOT class oriented)

Actor

Framework (Hollywood Principle)

Page 10: Elixir Elevated: The Ups and Downs of OTP at ElixirConf2014

OTP is …

Mature / Battle Tested for 16 (18?) years

Microservices

Object Oriented (NOT class oriented)

Actor

Framework (Hollywood Principle)

Design Patterns

Page 11: Elixir Elevated: The Ups and Downs of OTP at ElixirConf2014

OTP is …

Mature / Battle Tested for 16 (18?) years

Microservices

Object Oriented (NOT class oriented)

Actor

Framework (Hollywood Principle)

Design Patterns

Robust

Page 12: Elixir Elevated: The Ups and Downs of OTP at ElixirConf2014

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

Page 13: Elixir Elevated: The Ups and Downs of OTP at ElixirConf2014

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

Page 14: Elixir Elevated: The Ups and Downs of OTP at ElixirConf2014

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

Page 15: Elixir Elevated: The Ups and Downs of OTP at ElixirConf2014

object oriented functional

concurrent

actors

Page 16: Elixir Elevated: The Ups and Downs of OTP at ElixirConf2014

Behaviours: Don’t call us, we’ll call you

defmodule MyCallback do use GenServer end

iex> {:ok, pid} = GenServer.start(MyCallback, [])

Page 17: Elixir Elevated: The Ups and Downs of OTP at ElixirConf2014

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

Page 18: Elixir Elevated: The Ups and Downs of OTP at ElixirConf2014

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

Page 19: Elixir Elevated: The Ups and Downs of OTP at ElixirConf2014

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

Page 20: Elixir Elevated: The Ups and Downs of OTP at ElixirConf2014

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

Page 21: Elixir Elevated: The Ups and Downs of OTP at ElixirConf2014

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

Page 22: Elixir Elevated: The Ups and Downs of OTP at ElixirConf2014

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

Page 23: Elixir Elevated: The Ups and Downs of OTP at ElixirConf2014

Elevators 101

Page 24: Elixir Elevated: The Ups and Downs of OTP at ElixirConf2014

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

Page 25: Elixir Elevated: The Ups and Downs of OTP at ElixirConf2014

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

Page 26: Elixir Elevated: The Ups and Downs of OTP at ElixirConf2014

Show Me The Code

Page 27: Elixir Elevated: The Ups and Downs of OTP at ElixirConf2014

Let It Fail … and Respond

Separation of Concerns!

Think Long and Hard about Failure Response!

BEAM (not OS) Processes!

Finer Grained Control

Page 28: Elixir Elevated: The Ups and Downs of OTP at ElixirConf2014

Prepare to Fail

Car!Supervisor

Car 1 Car n…

one_for_one

Page 29: Elixir Elevated: The Ups and Downs of OTP at ElixirConf2014

Prepare to Fail

Car!Supervisor

Car 1 Car n…

one_for_one

Hall!Signal

Page 30: Elixir Elevated: The Ups and Downs of OTP at ElixirConf2014

Prepare to Fail

Car!Supervisor

Car 1 Car n…

one_for_one

Gen!Event

Hall!Signal

Page 31: Elixir Elevated: The Ups and Downs of OTP at ElixirConf2014

Prepare to Fail

Car!Supervisor

Car 1 Car n…

one_for_one

Gen!Event

Hall!Signal

Bank!Supervisor

rest_for_one

Page 32: Elixir Elevated: The Ups and Downs of OTP at ElixirConf2014

Prepare to Fail

Gen!Event HS

Bank A!Supervisor

CSGen!

Event HS

Bank B!Supervisor

CS

Elevator!Supervisor

one_for_one

Page 33: Elixir Elevated: The Ups and Downs of OTP at ElixirConf2014

Prepare to Fail

Gen!Event HS

Bank A!Supervisor

CSGen!

Event HS

Bank B!Supervisor

CS

Elevator!Supervisor

one_for_one

GenEvent

GenEvent

Page 34: Elixir Elevated: The Ups and Downs of OTP at ElixirConf2014

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

Page 35: Elixir Elevated: The Ups and Downs of OTP at ElixirConf2014

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

Page 36: Elixir Elevated: The Ups and Downs of OTP at ElixirConf2014

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

Page 37: Elixir Elevated: The Ups and Downs of OTP at ElixirConf2014

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

Page 38: Elixir Elevated: The Ups and Downs of OTP at ElixirConf2014

Show Me The Code

Page 39: Elixir Elevated: The Ups and Downs of OTP at ElixirConf2014

Takeaways

Behaviours vs. Callback Modules!

Watch your initialization steps!

Watch parameter and return value contracts!

Supervisors and Strategies!

Config

Page 40: Elixir Elevated: The Ups and Downs of OTP at ElixirConf2014

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


Related Documents