The ABCs of OTP

141

Transcript of The ABCs of OTP

Page 1: The ABCs of OTP
Page 2: The ABCs of OTP
Page 3: The ABCs of OTP
Page 4: The ABCs of OTP
Page 5: The ABCs of OTP

What is OTP anyway?

Page 6: The ABCs of OTP

What is OTP anyway?

(basically)

Collection of libraries

Hierarchy of supervisors & workers

Page 7: The ABCs of OTP

Main OTP Libraries

Supervisor

Page 8: The ABCs of OTP

Main OTP Libraries

Supervisor

GenServer

Page 9: The ABCs of OTP

Main OTP Libraries

Supervisor

GenServer

Agent & Task

Page 10: The ABCs of OTP

Main OTP Components

(and other stuff like GenStage, GenEvent, GenFSM, etc)

Page 11: The ABCs of OTP

Main OTP Components

(and other stuff like GenStage, GenEvent, GenFSM, etc)

Page 12: The ABCs of OTP

Main OTP Components

(and other stuff like GenStage, GenEvent, GenFSM, etc)

Page 13: The ABCs of OTP

Main OTP Components

(and other stuff like GenStage, GenEvent, GenFSM, etc)

(and more stuff like Application, ETS, Mnesia)

Page 14: The ABCs of OTP

Main OTP Components

(and other stuff like GenStage, GenEvent, GenFSM, etc)

(and more stuff like Application, ETS, Mnesia)

(even more stuff like Dialyzer, gen_tcp, Observer)

Page 15: The ABCs of OTP

Main OTP Components

Supervisor

GenServer

Agent & Task

Page 16: The ABCs of OTP

Processes

Page 17: The ABCs of OTP

iex(1)>

Page 18: The ABCs of OTP

iex(1)> spawn(fn -> IO.puts(“Hello ElixirDaze”) end)

Page 19: The ABCs of OTP

iex(1)> spawn(fn -> IO.puts(“Hello ElixirDaze”) end)

Hello ElixirDaze

#PID<0.64.0>

iex(2)>

Page 20: The ABCs of OTP

iex(2)>

Page 21: The ABCs of OTP

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

Page 22: The ABCs of OTP

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

Hello ElixirDaze

#PID<0.65.0>

iex(3)>

Page 23: The ABCs of OTP

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

Hello ElixirDaze

#PID<0.65.0>

iex(3)> Process.alive?(pid)

Page 24: The ABCs of OTP

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

Hello ElixirDaze

#PID<0.65.0>

iex(3)> Process.alive?(pid)

false

iex(4)>

Page 25: The ABCs of OTP

Error Handling

Page 26: The ABCs of OTP
Page 27: The ABCs of OTP

Supervisors

Page 28: The ABCs of OTP
Page 29: The ABCs of OTP
Page 30: The ABCs of OTP
Page 31: The ABCs of OTP

“The Zen of Erlang”

Page 32: The ABCs of OTP
Page 33: The ABCs of OTP
Page 34: The ABCs of OTP
Page 35: The ABCs of OTP
Page 36: The ABCs of OTP
Page 37: The ABCs of OTP
Page 38: The ABCs of OTP
Page 39: The ABCs of OTP
Page 40: The ABCs of OTP
Page 41: The ABCs of OTP
Page 42: The ABCs of OTP

Messages

Page 43: The ABCs of OTP

FantasyTeam

Page 44: The ABCs of OTP

State

Page 45: The ABCs of OTP

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

Page 46: The ABCs of OTP

defmodule FantasyTeam.Basic do

def start_link do spawn_link(__MODULE__, :loop, [%{}]) end

def loop(state) do

...

Page 47: The ABCs of OTP

defmodule FantasyTeam.Basic do

def start_link do spawn_link(__MODULE__, :loop, [%{}]) end

def loop(state) do

...

Page 48: The ABCs of OTP

defmodule FantasyTeam.Basic do

def start_link do spawn_link(__MODULE__, :loop, [%{}]) end

def loop(state) do

...

Page 49: The ABCs of OTP

defmodule FantasyTeam.Basic do

def start_link do spawn_link(__MODULE__, :loop, [%{}]) end

def loop(state) do

...

Page 50: The ABCs of OTP

defmodule FantasyTeam.Basic do

def start_link do spawn_link(__MODULE__, :loop, [%{}]) end

def loop(state) do

...

Page 51: The ABCs of OTP

defmodule FantasyTeam.Basic do

def start_link do spawn_link(__MODULE__, :loop, [%{}]) end

def loop(state) do

...

> FantasyTeam.Basic.loop(%{})

Page 52: The ABCs of OTP

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)

Page 53: The ABCs of OTP

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)

Page 54: The ABCs of OTP

FantasyTeam.Player.find("Russell Wilson")

%{ active: "1", college: "Wisconsin", display_name: "Russell Wilson", dob: “1988-11-29”, fname: "Russell", height: "5-11", jersey: "3", lname: "Wilson", player_id: "1847", position: "QB", team: "SEA", weight: "206" }

Page 55: The ABCs of OTP

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)

Page 56: The ABCs of OTP

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)

Page 57: The ABCs of OTP

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)

Page 58: The ABCs of OTP

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)

Page 59: The ABCs of OTP

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)

Page 60: The ABCs of OTP

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)

Page 61: The ABCs of OTP

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)

Page 62: The ABCs of OTP

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)

Page 63: The ABCs of OTP

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

Page 64: The ABCs of OTP

iex(1)>

Page 65: The ABCs of OTP

iex(1)> pid = FantasyTeam.Basic.start_link

#PID<0.65.0>

iex(2)>

Page 66: The ABCs of OTP

iex(1)> pid = FantasyTeam.Basic.start_link

#PID<0.65.0>

iex(2)> send(pid, {:add, “Russell Wilson”})

{:add, “Russell Wilson”}

iex(3)>

Page 67: The ABCs of OTP

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)>

Page 68: The ABCs of OTP

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)>

Page 69: The ABCs of OTP

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)>

Page 70: The ABCs of OTP

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”, ...}}

Page 71: The ABCs of OTP

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

Page 72: The ABCs of OTP

GenServer

Page 73: The ABCs of OTP

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

Page 74: The ABCs of OTP

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

Page 75: The ABCs of OTP

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

Page 76: The ABCs of OTP

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

Page 77: The ABCs of OTP

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

Page 78: The ABCs of OTP

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

Page 79: The ABCs of OTP

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

Page 80: The ABCs of OTP

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

Page 81: The ABCs of OTP

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

Page 82: The ABCs of OTP

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

Page 83: The ABCs of OTP

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

Page 84: The ABCs of OTP

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

Page 85: The ABCs of OTP

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

Page 86: The ABCs of OTP

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

Page 87: The ABCs of OTP

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

Page 88: The ABCs of OTP

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

Page 89: The ABCs of OTP

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

Page 90: The ABCs of OTP

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

Page 91: The ABCs of OTP

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

Page 92: The ABCs of OTP

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

Page 93: The ABCs of OTP

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

Page 94: The ABCs of OTP

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

Page 95: The ABCs of OTP

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

Page 96: The ABCs of OTP

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

...

Page 97: The ABCs of OTP

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

...

Page 98: The ABCs of OTP

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

...

Page 99: The ABCs of OTP

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

...

Page 100: The ABCs of OTP

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

...

Page 101: The ABCs of OTP

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

...

Page 102: The ABCs of OTP

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

...

Page 103: The ABCs of OTP

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

...

Page 104: The ABCs of OTP

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

...

Page 105: The ABCs of OTP

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

...

Page 106: The ABCs of OTP

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

...

Page 107: The ABCs of OTP

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

...

Page 108: The ABCs of OTP

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

Page 109: The ABCs of OTP

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}) end

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}) end

def remove(pid, name) do GenServer.cast(pid, {:remove, name}) end

def team(pid) do GenServer.call(pid, :team) end

# Callbacks

...

Page 110: The ABCs of OTP

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}) end

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}) end

def remove(pid, name) do GenServer.cast(pid, {:remove, name}) end

def team(pid) do GenServer.call(pid, :team) end

# Callbacks

...

Page 111: The ABCs of OTP

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}) end

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}) end

def remove(pid, name) do GenServer.cast(pid, {:remove, name}) end

def team(pid) do GenServer.call(pid, :team) end

# Callbacks

...

Page 112: The ABCs of OTP

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}) end

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}) end

def remove(pid, name) do GenServer.cast(pid, {:remove, name}) end

def team(pid) do GenServer.call(pid, :team) end

# Callbacks

...

Page 113: The ABCs of OTP

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}) end

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}) end

def remove(pid, name) do GenServer.cast(pid, {:remove, name}) end

def team(pid) do GenServer.call(pid, :team) end

# Callbacks

...

Page 114: The ABCs of OTP

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}) end

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}) end

def remove(pid, name) do GenServer.cast(pid, {:remove, name}) end

def team(pid) do GenServer.call(pid, :team) end

# Callbacks

...

Page 115: The ABCs of OTP

iex(1)>

Page 116: The ABCs of OTP

iex(1)> FantasyTeam.SingleServer.start_link

{:ok, #PID<0.65.0>}

iex(2)>

Page 117: The ABCs of OTP

iex(1)> FantasyTeam.SingleServer.start_link

{:ok, #PID<0.65.0>}

iex(2)> FantasyTeam.SingleServer.add(“Russell Wilson”)

:ok

iex(3)>

Page 118: The ABCs of OTP

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)>

Page 119: The ABCs of OTP

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)>

Page 120: The ABCs of OTP

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)>

Page 121: The ABCs of OTP

Agents & Tasks

Page 122: The ABCs of OTP

defmodule FantasyTeam.MyAgent do @name __MODULE__

def start_link do Agent.start_link(fn -> %{} end) end

def add(name) do player = FantasyTeam.Player.find(name) Agent.update(@name, fn(x) -> Map.put(x, name, player)} end) end

def remove(name) do Agent.update(@name, fn(x) -> Map.delete(x, name) end) end

def team do Agent.get(@name, fn(x) -> x end) end end

Page 123: The ABCs of OTP

defmodule FantasyTeam.MyAgent do @name __MODULE__

def start_link do Agent.start_link(fn -> %{} end) end

def add(name) do player = FantasyTeam.Player.find(name) Agent.update(@name, fn(x) -> Map.put(x, name, player)} end) end

def remove(name) do Agent.update(@name, fn(x) -> Map.delete(x, name) end) end

def team do Agent.get(@name, fn(x) -> x end) end end

Page 124: The ABCs of OTP

Supervisors

Page 125: The ABCs of OTP

defmodule FantasyTeam.MySupervisor do use Supervisor

def start_link do Supervisor.start_link(__MODULE__, []) end

def init([]) do children = [ worker(FantasyTeam.SingleServer, []) ]

supervise(children, strategy: :one_for_one) end end

Page 126: The ABCs of OTP

defmodule FantasyTeam.MySupervisor do use Supervisor

def start_link do Supervisor.start_link(__MODULE__, []) end

def init([]) do children = [ worker(FantasyTeam.SingleServer, []) ]

supervise(children, strategy: :one_for_one) end end

Page 127: The ABCs of OTP

defmodule FantasyTeam.MySupervisor do use Supervisor

def start_link do Supervisor.start_link(__MODULE__, []) end

def init([]) do children = [ worker(FantasyTeam.SingleServer, []) ]

supervise(children, strategy: :one_for_one) end end

Page 128: The ABCs of OTP

defmodule FantasyTeam.MySupervisor do use Supervisor

def start_link do Supervisor.start_link(__MODULE__, []) end

def init([]) do children = [ worker(FantasyTeam.SingleServer, []) ]

supervise(children, strategy: :one_for_one) end end

Page 129: The ABCs of OTP

defmodule FantasyTeam.MySupervisor do use Supervisor

def start_link do Supervisor.start_link(__MODULE__, []) end

def init([]) do children = [ worker(FantasyTeam.SingleServer, []) ]

supervise(children, strategy: :one_for_one) end end

Page 130: The ABCs of OTP

defmodule FantasyTeam.MySupervisor do use Supervisor

def start_link do Supervisor.start_link(__MODULE__, []) end

def init([]) do children = [ worker(FantasyTeam.SingleServer, []) ]

supervise(children, strategy: :one_for_one) end end

Page 131: The ABCs of OTP

defmodule FantasyTeam.MySupervisor do use Supervisor

def start_link do Supervisor.start_link(__MODULE__, []) end

def init([]) do children = [ worker(FantasyTeam.SingleServer, []) ]

supervise(children, strategy: :one_for_one) end end

Page 132: The ABCs of OTP

defmodule FantasyTeam.MySupervisor do use Supervisor

def start_link do Supervisor.start_link(__MODULE__, []) end

def init([]) do children = [ worker(FantasyTeam.SingleServer, []) ]

supervise(children, strategy: :one_for_one) end end

Page 133: The ABCs of OTP

defmodule FantasyTeam.MySupervisor do use Supervisor

def start_link do Supervisor.start_link(__MODULE__, []) end

def init([]) do children = [ worker(FantasyTeam.SingleServer, []) ]

supervise(children, strategy: :one_for_one) end end

Page 134: The ABCs of OTP

defmodule FantasyTeam.MySupervisor do use Supervisor

def start_link do Supervisor.start_link(__MODULE__, []) end

def init([]) do children = [ worker(FantasyTeam.SingleServer, []) ]

supervise(children, strategy: :one_for_one) end end

Page 135: The ABCs of OTP

defmodule FantasyTeam.MySupervisor do use Supervisor

def start_link do Supervisor.start_link(__MODULE__, []) end

def init([]) do children = [ worker(FantasyTeam.SingleServer, []) ]

supervise(children, strategy: :one_for_one) end end

Page 136: The ABCs of OTP

defmodule FantasyTeam.MySupervisor do use Supervisor

def start_link do Supervisor.start_link(__MODULE__, []) end

def init([]) do children = [ worker(FantasyTeam.SingleServer, []) ]

supervise(children, strategy: :one_for_one) end end

Page 137: The ABCs of OTP

defmodule FantasyTeam.MySupervisor do use Supervisor

def start_link do Supervisor.start_link(__MODULE__, []) end

def init([]) do children = [ worker(FantasyTeam.SingleServer, []) ]

supervise(children, strategy: :one_for_one) end end

Page 138: The ABCs of OTP

Recap

Page 139: The ABCs of OTP
Page 140: The ABCs of OTP

r

Page 141: The ABCs of OTP

bit.ly/abcs-of-otpOTP / ELIXIR RESOURCES

@jessejandersonFOLLOW ME