Recreate a simple GenServer implementation
Because:
People who
DISCLAIMER: From now on, we won't talk about OS but Erlang processes
spawn(fn ->
Process.sleep(2000)
IO.puts(2 * 2)
end)
# Execution:
# ...wait 2 seconds...
# 4
# PID<0.84.0>
Cool, but useless. Would be awesome to take some parameters
Starting from scratch
background_job = fn(value) ->
spawn(fn ->
Process.sleep(2_000)
IO.puts(value * 2)
end)
end
# Execution:
# > background_job.(4)
# ... Wait 2 seconds...
# 8
# PID<0.87.0>
Better. We can trigger tasks in background.
What about communication?
Starting from scratch
background_job = fn(value, caller) ->
spawn(fn ->
Process.sleep(2_000)
send(caller, {:done, value * 2})
end)
end
# Execution:
# > background_job.(4, self())
# PID<0.87.0>
# > receive do
# > {:done, result} -> IO.puts("Result is #{result}")
# > end
# Result is 8
# :ok
Yay! we can now send and receive messages but what about not dying after each call?
Exchanging messages
defmodule Multiplicator do
def start(initial_value) do
spawn(fn -> loop(initial_value) end)
end
defp loop(result) do
receive do
{multiplicator, caller} ->
result = result * multiplicator
send(caller, {:done, result})
loop(result)
end
end
end
# Execution:
# > pid = Multiplicator.start(1)
# PID<0.87.0>
# > send(pid, {2, self()})
# > receive do
# > {:done, result} -> IO.puts("Result is #{result}")
# > end
# Result is 2
# > send(pid, {21, self()})
# > receive ....
# Result is 42
Let's move to an editor
https://github.com/kdisneur/processes
What we've seen previously in theory but now with a real use case
Pros
Cons
git checkout 9f788ca
We partially fixed the cons from Step 2
Pros
Cons
git checkout 0e32b1f
Generic
Specific
git checkout a1d6436
Well done! We just (re)created a basic GenServer
In a perfect world, we could now add new features more easily (new servers, or news messages)
git checkout 78e87e7