Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Intro to OTP in Elixir

Intro to OTP in Elixir

September 8th, 2016 @ Full Stack Talks

https://youtu.be/CJT8wPnmjTM

Jesse J. Anderson

September 08, 2016
Tweet

More Decks by Jesse J. Anderson

Other Decks in Technology

Transcript

  1. iex(2)> pid = spawn(fn -> IO.puts “Hello Full Stack” end)

    Hello Full Stack #PID<0.65.0> iex(3)> Process.alive?(pid) false iex(4)>
  2. defmodule FantasyTeam.Basic do def start_link do spawn_link(__MODULE__, :loop, [%{}]) end

    def loop(state) do receive do {:add, name} -> player = FantasyTeam.Player.find(name) new_state = Map.put(state, name, player) loop(new_state) {:remove, name} -> new_state = Map.delete(state, name) loop(new_state) {:team, pid} -> send(pid, {:ok, state}) loop(state) end end end
  3. def loop(state) do receive do {:add, name} -> player =

    FantasyTeam.Player.find(name) new_state = Map.put(state, name, player) loop(new_state) {:remove, name} -> new_state = Map.delete(state, name) loop(new_state) {:team, pid} -> send(pid, state) loop(new_state)
  4. def loop(state) do receive do {:add, name} -> player =

    FantasyTeam.Player.find(name) new_state = Map.put(state, name, player) loop(new_state) {:remove, name} -> new_state = Map.delete(state, name) loop(new_state) {:team, pid} -> send(pid, state) loop(new_state)
  5. def loop(state) do receive do {:add, name} -> player =

    FantasyTeam.Player.find(name) new_state = Map.put(state, name, player) loop(new_state) {:remove, name} -> new_state = Map.delete(state, name) loop(new_state) {:team, pid} -> send(pid, state) loop(new_state)
  6. def loop(state) do receive do {:add, name} -> player =

    FantasyTeam.Player.find(name) new_state = Map.put(state, name, player) loop(new_state) {:remove, name} -> new_state = Map.delete(state, name) loop(new_state) {:team, pid} -> send(pid, state) loop(new_state)
  7. def loop(state) do receive do {:add, name} -> player =

    FantasyTeam.Player.find(name) new_state = Map.put(state, name, player) loop(new_state) {:remove, name} -> new_state = Map.delete(state, name) loop(new_state) {:team, pid} -> send(pid, state) loop(new_state)
  8. def loop(state) do receive do {:add, name} -> player =

    FantasyTeam.Player.find(name) new_state = Map.put(state, name, player) loop(new_state) {:remove, name} -> new_state = Map.delete(state, name) loop(new_state) {:team, pid} -> send(pid, state) loop(state)
  9. def loop(state) do receive do {:add, name} -> player =

    FantasyTeam.Player.find(name) new_state = Map.put(state, name, player) loop(new_state) {:remove, name} -> new_state = Map.delete(state, name) loop(new_state) {:team, pid} -> send(pid, state) loop(state)
  10. def loop(state) do receive do {:add, name} -> player =

    FantasyTeam.Player.find(name) new_state = Map.put(state, name, player) loop(new_state) {:remove, name} -> new_state = Map.delete(state, name) loop(new_state) {:team, pid} -> send(pid, state) loop(state)
  11. iex(1)> pid = FantasyTeam.Basic.start_link #PID<0.65.0> iex(2)> send(pid, {:add, “Russell Wilson”})

    {:add, “Russell Wilson”} iex(3)> send(pid, {:add, “Doug Baldwin”}) {:add, “Doug Baldwin”} iex(4)>
  12. iex(1)> pid = FantasyTeam.Basic.start_link #PID<0.65.0> iex(2)> send(pid, {:add, “Russell Wilson”})

    {:add, “Russell Wilson”} iex(3)> send(pid, {:add, “Doug Baldwin”}) {:add, “Doug Baldwin”} iex(4)> send(pid, {:remove, “Doug Baldwin”}) {:remove, “Doug Baldwin”} iex(5)>
  13. iex(1)> pid = FantasyTeam.Basic.start_link #PID<0.65.0> iex(2)> send(pid, {:add, “Russell Wilson”})

    {:add, “Russell Wilson”} iex(3)> send(pid, {:add, “Doug Baldwin”}) {:add, “Doug Baldwin”} iex(4)> send(pid, {:remove, “Doug Baldwin”}) {:remove, “Doug Baldwin”} iex(5)> send(pid, {:team, self}) {:team, #PID<0.123.0>} iex(6)>
  14. iex(1)> pid = FantasyTeam.Basic.start_link #PID<0.65.0> iex(2)> send(pid, {:add, “Russell Wilson”})

    {:add, “Russell Wilson”} iex(3)> send(pid, {:add, “Doug Baldwin”}) {:add, “Doug Baldwin”} iex(4)> send(pid, {:remove, “Doug Baldwin”}) {:remove, “Doug Baldwin”} iex(5)> send(pid, {:team, self}) {:team, #PID<0.123.0>} iex(6)> flush {:ok, %{“Russell Wilson” => %{position: “QB”, team: “SEA”}}
  15. defmodule FantasyTeam.Basic do def start_link do spawn_link(__MODULE__, :loop, [%{}]) end

    def loop(state) do receive do {:add, name} -> player = FantasyTeam.Player.find(name) new_state = Map.put(state, name, player) loop(new_state) {:remove, name} -> new_state = Map.delete(state, name) loop(new_state) {:team, pid} -> send(pid, {:ok, state}) loop(state) end end end
  16. defmodule FantasyTeam.MyGenServer do use GenServer # API def start_link do

    GenServer.start_link(__MODULE__, :ok, []) end def add(pid, name) do GenServer.cast(pid, {:add, name}) end def remove(pid, name) do GenServer.cast(pid, {:remove, name}) end def team(pid) do GenServer.call(pid, :team) end # Callbacks def init(:ok) do {:ok, %{}} end def handle_cast({:add, name}, state) do player = FantasyTeam.Player.find(name) new_state = Map.put(state, name, player) {:noreply, new_state} end def handle_cast({:remove, name}, state) do new_state = Map.delete(state, name) {:noreply, new_state} end def handle_call(:team, _from, state) do {:reply, state, state} end end defmodule FantasyTeam.Basic do def start_link do spawn_link(__MODULE__, :loop, [%{}]) end def loop(state) do receive do {:add, name} -> player = FantasyTeam.Player.find(name) new_state = Map.put(state, name, player) loop(new_state) {:remove, name} -> new_state = Map.delete(state, name) loop(new_state) {:team, pid} -> send(pid, {:ok, state}) loop(state) end end end
  17. defmodule FantasyTeam.MyGenServer do use GenServer defmodule FantasyTeam.Basic do def start_link

    do spawn_link(__MODULE__, :loop, [%{}]) end def loop(state) do receive do {:add, name} -> player = FantasyTeam.Player.find(name) new_state = Map.put(state, name, player) loop(new_state) {:remove, name} -> new_state = Map.delete(state, name) loop(new_state) {:team, pid} -> send(pid, {:ok, state}) loop(state) end end end
  18. def start_link do GenServer.start_link(__MODULE__, :ok, []) end # Callbacks def

    init(:ok) do {:ok, %{}} end def handle_cast({:add, name}, state) do player = FantasyTeam.Player.find(name) new_state = Map.put(state, name, player) {:noreply, new_state} end def handle_cast({:remove, name}, state) do new_state = Map.delete(state, name) {:noreply, new_state} end def handle_call(:team, _from, state) do {:reply, state, state} end def start_link do spawn_link(__MODULE__, :loop, [%{}]) end def loop(state) do receive do {:add, name} -> player = FantasyTeam.Player.find(name) new_state = Map.put(state, name, player) loop(new_state) {:remove, name} -> new_state = Map.delete(state, name) loop(new_state) {:team, pid} -> send(pid, {:ok, state}) loop(state) end end
  19. def start_link do GenServer.start_link(__MODULE__, :ok, []) end # Callbacks def

    init(:ok) do {:ok, %{}} end def handle_cast({:add, name}, state) do player = FantasyTeam.Player.find(name) new_state = Map.put(state, name, player) {:noreply, new_state} end def handle_cast({:remove, name}, state) do new_state = Map.delete(state, name) {:noreply, new_state} end def handle_call(:team, _from, state) do {:reply, state, state} end def start_link do spawn_link(__MODULE__, :loop, [%{}]) end def loop(state) do receive do {:add, name} -> player = FantasyTeam.Player.find(name) new_state = Map.put(state, name, player) loop(new_state) {:remove, name} -> new_state = Map.delete(state, name) loop(new_state) {:team, pid} -> send(pid, {:ok, state}) loop(state) end end
  20. def start_link do GenServer.start_link(__MODULE__, :ok, []) end # Callbacks def

    init(:ok) do {:ok, %{}} end def handle_cast({:add, name}, state) do player = FantasyTeam.Player.find(name) new_state = Map.put(state, name, player) {:noreply, new_state} end def handle_cast({:remove, name}, state) do new_state = Map.delete(state, name) {:noreply, new_state} end def handle_call(:team, _from, state) do {:reply, state, state} end def start_link do spawn_link(__MODULE__, :loop, [%{}]) end def loop(state) do receive do {:add, name} -> player = FantasyTeam.Player.find(name) new_state = Map.put(state, name, player) loop(new_state) {:remove, name} -> new_state = Map.delete(state, name) loop(new_state) {:team, pid} -> send(pid, {:ok, state}) loop(state) end end
  21. def start_link do GenServer.start_link(__MODULE__, :ok, []) end # Callbacks def

    init(:ok) do {:ok, %{}} end def handle_cast({:add, name}, state) do player = FantasyTeam.Player.find(name) new_state = Map.put(state, name, player) {:noreply, new_state} end def handle_cast({:remove, name}, state) do new_state = Map.delete(state, name) {:noreply, new_state} end def handle_call(:team, _from, state) do {:reply, state, state} end def start_link do spawn_link(__MODULE__, :loop, [%{}]) end def loop(state) do receive do {:add, name} -> player = FantasyTeam.Player.find(name) new_state = Map.put(state, name, player) loop(new_state) {:remove, name} -> new_state = Map.delete(state, name) loop(new_state) {:team, pid} -> send(pid, {:ok, state}) loop(state) end end
  22. def start_link do GenServer.start_link(__MODULE__, :ok, []) end # Callbacks def

    init(:ok) do {:ok, %{}} end def handle_cast({:add, name}, state) do player = FantasyTeam.Player.find(name) new_state = Map.put(state, name, player) {:noreply, new_state} end def handle_cast({:remove, name}, state) do new_state = Map.delete(state, name) {:noreply, new_state} end def handle_call(:team, _from, state) do {:reply, state, state} end def start_link do spawn_link(__MODULE__, :loop, [%{}]) end def loop(state) do receive do {:add, name} -> player = FantasyTeam.Player.find(name) new_state = Map.put(state, name, player) loop(new_state) {:remove, name} -> new_state = Map.delete(state, name) loop(new_state) {:team, pid} -> send(pid, {:ok, state}) loop(state) end end
  23. def start_link do GenServer.start_link(__MODULE__, :ok, []) end # Callbacks def

    init(:ok) do {:ok, %{}} end def handle_cast({:add, name}, state) do player = FantasyTeam.Player.find(name) new_state = Map.put(state, name, player) {:noreply, new_state} end def handle_cast({:remove, name}, state) do new_state = Map.delete(state, name) {:noreply, new_state} end def handle_call(:team, _from, state) do {:reply, state, state} end def start_link do spawn_link(__MODULE__, :loop, [%{}]) end def loop(state) do receive do {:add, name} -> player = FantasyTeam.Player.find(name) new_state = Map.put(state, name, player) loop(new_state) {:remove, name} -> new_state = Map.delete(state, name) loop(new_state) {:team, pid} -> send(pid, {:ok, state}) loop(state) end end
  24. def start_link do GenServer.start_link(__MODULE__, :ok, []) end # Callbacks def

    init(:ok) do {:ok, %{}} end def handle_cast({:add, name}, state) do player = FantasyTeam.Player.find(name) new_state = Map.put(state, name, player) {:noreply, new_state} end def handle_cast({:remove, name}, state) do new_state = Map.delete(state, name) {:noreply, new_state} end def handle_call(:team, _from, state) do {:reply, state, state} end def start_link do spawn_link(__MODULE__, :loop, [%{}]) end def loop(state) do receive do {:add, name} -> player = FantasyTeam.Player.find(name) new_state = Map.put(state, name, player) loop(new_state) {:remove, name} -> new_state = Map.delete(state, name) loop(new_state) {:team, pid} -> send(pid, {:ok, state}) loop(state) end end
  25. def start_link do GenServer.start_link(__MODULE__, :ok, []) end # Callbacks def

    init(:ok) do {:ok, %{}} end def handle_cast({:add, name}, state) do player = FantasyTeam.Player.find(name) new_state = Map.put(state, name, player) {:noreply, new_state} end def handle_cast({:remove, name}, state) do new_state = Map.delete(state, name) {:noreply, new_state} end def handle_call(:team, _from, state) do {:reply, state, state} end def start_link do spawn_link(__MODULE__, :loop, [%{}]) end def loop(state) do receive do {:add, name} -> player = FantasyTeam.Player.find(name) new_state = Map.put(state, name, player) loop(new_state) {:remove, name} -> new_state = Map.delete(state, name) loop(new_state) {:team, pid} -> send(pid, {:ok, state}) loop(state) end end
  26. def start_link do GenServer.start_link(__MODULE__, :ok, []) end # Callbacks def

    init(:ok) do {:ok, %{}} end def handle_cast({:add, name}, state) do player = FantasyTeam.Player.find(name) new_state = Map.put(state, name, player) {:noreply, new_state} end def handle_cast({:remove, name}, state) do new_state = Map.delete(state, name) {:noreply, new_state} end def handle_call(:team, _from, state) do {:reply, state, state} end def start_link do spawn_link(__MODULE__, :loop, [%{}]) end def loop(state) do receive do {:add, name} -> player = FantasyTeam.Player.find(name) new_state = Map.put(state, name, player) loop(new_state) {:remove, name} -> new_state = Map.delete(state, name) loop(new_state) {:team, pid} -> send(pid, {:ok, state}) loop(state) end end
  27. def start_link do GenServer.start_link(__MODULE__, :ok, []) end # Callbacks def

    init(:ok) do {:ok, %{}} end def handle_cast({:add, name}, state) do player = FantasyTeam.Player.find(name) new_state = Map.put(state, name, player) {:noreply, new_state} end def handle_cast({:remove, name}, state) do new_state = Map.delete(state, name) {:noreply, new_state} end def handle_call(:team, _from, state) do {:reply, state, state} end def start_link do spawn_link(__MODULE__, :loop, [%{}]) end def loop(state) do receive do {:add, name} -> player = FantasyTeam.Player.find(name) new_state = Map.put(state, name, player) loop(new_state) {:remove, name} -> new_state = Map.delete(state, name) loop(new_state) {:team, pid} -> send(pid, {:ok, state}) loop(state) end end
  28. defmodule FantasyTeam.MyGenServer do use GenServer # API def start_link do

    GenServer.start_link(__MODULE__, :ok, []) end def add(pid, name) do GenServer.cast(pid, {:add, name}) def def remove(pid, name) do GenServer.cast(pid, {:remove, name}) end def team(pid) do GenServer.call(pid, :team) end # Callbacks ...
  29. defmodule FantasyTeam.MyGenServer do use GenServer # API def start_link do

    GenServer.start_link(__MODULE__, :ok, []) end def add(pid, name) do GenServer.cast(pid, {:add, name}) def def remove(pid, name) do GenServer.cast(pid, {:remove, name}) end def team(pid) do GenServer.call(pid, :team) end # Callbacks ...
  30. defmodule FantasyTeam.MyGenServer do use GenServer # API def start_link do

    GenServer.start_link(__MODULE__, :ok, []) end def add(pid, name) do GenServer.cast(pid, {:add, name}) def def remove(pid, name) do GenServer.cast(pid, {:remove, name}) end def team(pid) do GenServer.call(pid, :team) end # Callbacks ...
  31. defmodule FantasyTeam.MyGenServer do use GenServer # API def start_link do

    GenServer.start_link(__MODULE__, :ok, []) end def add(pid, name) do GenServer.cast(pid, {:add, name}) def def remove(pid, name) do GenServer.cast(pid, {:remove, name}) end def team(pid) do GenServer.call(pid, :team) end # Callbacks ...
  32. defmodule FantasyTeam.MyGenServer do use GenServer # API def start_link do

    GenServer.start_link(__MODULE__, :ok, []) end def add(pid, name) do GenServer.cast(pid, {:add, name}) def def remove(pid, name) do GenServer.cast(pid, {:remove, name}) end def team(pid) do GenServer.call(pid, :team) end # Callbacks ...
  33. defmodule FantasyTeam.MyGenServer do use GenServer # API def start_link do

    GenServer.start_link(__MODULE__, :ok, []) end def add(pid, name) do GenServer.cast(pid, {:add, name}) def def remove(pid, name) do GenServer.cast(pid, {:remove, name}) end def team(pid) do GenServer.call(pid, :team) end # Callbacks ...
  34. defmodule FantasyTeam.MyGenServer do use GenServer # API def start_link do

    GenServer.start_link(__MODULE__, :ok, []) end def add(pid, name) do GenServer.cast(pid, {:add, name}) def def remove(pid, name) do GenServer.cast(pid, {:remove, name}) end def team(pid) do GenServer.call(pid, :team) end # Callbacks ...
  35. defmodule FantasyTeam.MyGenServer do use GenServer # API def start_link do

    GenServer.start_link(__MODULE__, :ok, []) end def add(pid, name) do GenServer.cast(pid, {:add, name}) def def remove(pid, name) do GenServer.cast(pid, {:remove, name}) end def team(pid) do GenServer.call(pid, :team) end # Callbacks ...
  36. defmodule FantasyTeam.MyGenServer do use GenServer # API def start_link do

    GenServer.start_link(__MODULE__, :ok, []) end def add(pid, name) do GenServer.cast(pid, {:add, name}) def def remove(pid, name) do GenServer.cast(pid, {:remove, name}) end def team(pid) do GenServer.call(pid, :team) end # Callbacks ...
  37. defmodule FantasyTeam.MyGenServer do use GenServer # API def start_link do

    GenServer.start_link(__MODULE__, :ok, []) end def add(pid, name) do GenServer.cast(pid, {:add, name}) def def remove(pid, name) do GenServer.cast(pid, {:remove, name}) end def team(pid) do GenServer.call(pid, :team) end # Callbacks ...
  38. defmodule FantasyTeam.MyGenServer do use GenServer # API def start_link do

    GenServer.start_link(__MODULE__, :ok, []) end def add(pid, name) do GenServer.cast(pid, {:add, name}) def def remove(pid, name) do GenServer.cast(pid, {:remove, name}) end def team(pid) do GenServer.call(pid, :team) end # Callbacks ...
  39. defmodule FantasyTeam.MyGenServer do use GenServer # API def start_link do

    GenServer.start_link(__MODULE__, :ok, []) end def add(pid, name) do GenServer.cast(pid, {:add, name}) def def remove(pid, name) do GenServer.cast(pid, {:remove, name}) end def team(pid) do GenServer.call(pid, :team) end # Callbacks def init(:ok) do {:ok, %{}} end def handle_cast({:add, name}, state) do player = FantasyTeam.Player.find(name) new_state = Map.put(state, name, player) {:noreply, new_state} end def handle_cast({:remove, name}, state) do new_state = Map.delete(state, name) {:noreply, new_state} end def handle_call(:team, _from, state) do {:reply, state, state} end end
  40. defmodule FantasyTeam.SingleServer do use GenServer @name __MODULE__ # API def

    start_link do GenServer.start_link(__MODULE__, :ok, name: @name) end def add(name) do GenServer.cast(@name, {:add, name}) def def remove(name) do GenServer.cast(@name, {:remove, name}) end def team do GenServer.call(@name, :team) end # Callbacks ... defmodule FantasyTeam.MyGenServer do use GenServer # API def start_link do GenServer.start_link(__MODULE__, :ok, []) end def add(pid, name) do GenServer.cast(pid, {:add, name}) def def remove(pid, name) do GenServer.cast(pid, {:remove, name}) end def team(pid) do GenServer.call(pid, :team) end # Callbacks ...
  41. defmodule FantasyTeam.SingleServer do use GenServer @name __MODULE__ # API def

    start_link do GenServer.start_link(__MODULE__, :ok, name: @name) end def add(name) do GenServer.cast(@name, {:add, name}) def def remove(name) do GenServer.cast(@name, {:remove, name}) end def team do GenServer.call(@name, :team) end # Callbacks ... defmodule FantasyTeam.MyGenServer do use GenServer # API def start_link do GenServer.start_link(__MODULE__, :ok, []) end def add(pid, name) do GenServer.cast(pid, {:add, name}) def def remove(pid, name) do GenServer.cast(pid, {:remove, name}) end def team(pid) do GenServer.call(pid, :team) end # Callbacks ...
  42. defmodule FantasyTeam.SingleServer do use GenServer @name __MODULE__ # API def

    start_link do GenServer.start_link(__MODULE__, :ok, name: @name) end def add(name) do GenServer.cast(@name, {:add, name}) def def remove(name) do GenServer.cast(@name, {:remove, name}) end def team do GenServer.call(@name, :team) end # Callbacks ... defmodule FantasyTeam.MyGenServer do use GenServer # API def start_link do GenServer.start_link(__MODULE__, :ok, []) end def add(pid, name) do GenServer.cast(pid, {:add, name}) def def remove(pid, name) do GenServer.cast(pid, {:remove, name}) end def team(pid) do GenServer.call(pid, :team) end # Callbacks ...
  43. defmodule FantasyTeam.SingleServer do use GenServer @name __MODULE__ # API def

    start_link do GenServer.start_link(__MODULE__, :ok, name: @name) end def add(name) do GenServer.cast(@name, {:add, name}) def def remove(name) do GenServer.cast(@name, {:remove, name}) end def team do GenServer.call(@name, :team) end # Callbacks ... defmodule FantasyTeam.MyGenServer do use GenServer # API def start_link do GenServer.start_link(__MODULE__, :ok, []) end def add(pid, name) do GenServer.cast(pid, {:add, name}) def def remove(pid, name) do GenServer.cast(pid, {:remove, name}) end def team(pid) do GenServer.call(pid, :team) end # Callbacks ...
  44. defmodule FantasyTeam.SingleServer do use GenServer @name __MODULE__ # API def

    start_link do GenServer.start_link(__MODULE__, :ok, name: @name) end def add(name) do GenServer.cast(@name, {:add, name}) def def remove(name) do GenServer.cast(@name, {:remove, name}) end def team do GenServer.call(@name, :team) end # Callbacks ... defmodule FantasyTeam.MyGenServer do use GenServer # API def start_link do GenServer.start_link(__MODULE__, :ok, []) end def add(pid, name) do GenServer.cast(pid, {:add, name}) def def remove(pid, name) do GenServer.cast(pid, {:remove, name}) end def team(pid) do GenServer.call(pid, :team) end # Callbacks ...
  45. defmodule FantasyTeam.SingleServer do use GenServer @name __MODULE__ # API def

    start_link do GenServer.start_link(__MODULE__, :ok, name: @name) end def add(name) do GenServer.cast(@name, {:add, name}) def def remove(name) do GenServer.cast(@name, {:remove, name}) end def team do GenServer.call(@name, :team) end # Callbacks ... defmodule FantasyTeam.MyGenServer do use GenServer # API def start_link do GenServer.start_link(__MODULE__, :ok, []) end def add(pid, name) do GenServer.cast(pid, {:add, name}) def def remove(pid, name) do GenServer.cast(pid, {:remove, name}) end def team(pid) do GenServer.call(pid, :team) end # Callbacks ...
  46. iex(1)> FantasyTeam.SingleServer.start_link {:ok, #PID<0.65.0>} iex(2)> FantasyTeam.SingleServer.add(“Russell Wilson”) :ok iex(3)> FantasyTeam.SingleServer.add(“Doug

    Baldwin”) :ok iex(4)> FantasyTeam.SingleServer.remove(“Doug Baldwin”) :ok iex(5)> FantasyTeam.SingleServer.team %{“Russell Wilson” => %{position: “QB”, team: “SEA”}} iex(6)>
  47. defmodule FantasyTeam.MyAgent do def start_link do Agent.start_link(fn -> %{} end)

    end def add(pid, name) do player = FantasyTeam.Player.find(name) Agent.get_and_update(pid, fn(x) -> {player, Map.put(x, name, player)} end) :ok end def remove(pid, name) do Agent.update(pid, fn(x) -> Map.delete(x, name) end) end def team(pid) do Agent.get(pid, fn(x) -> x end) end end