1. Raw process message exchange
Message exchange basic
Simple example of message exchanging between two Elixir processes.
defmodule RawProcess do
def listen do
receive do
msg ->
IO.puts("Received raw message: #{msg}")
# Recursive, keep the process alive
listen()
end
end
end
pid = spawn(RawProcess, :listen, [])
#PID<0.161.0>
The below call will match with the second arm from receive function.
send(pid, "Test message")
"Test message"
The below call will match with the first arm from receive function.
Process.exit(pid, :kill)
Received raw message: Test message
true
Response to caller
defmodule RawProcessWithResponse do
def listen do
receive do
{:ping, %{sender: sender, msg: msg}} ->
IO.puts("Receive ping message from #{inspect(sender)}, msg=#{msg}")
listen()
end
end
end
pid = spawn(RawProcessWithResponse, :listen, [])
#PID<0.171.0>
send(pid, {:ping, %{sender: self(), msg: "ping"}})
{:ping, %{msg: "ping", sender: #PID<0.153.0>}}
Process.exit(pid, :kill)
Receive ping message from #PID<0.153.0>, msg=ping
true
Simple KeyValueStorage using raw process
defmodule RawProcessKeyValueStorage do
def start() do
spawn(fn -> loop(%{}) end)
end
defp loop(state) do
receive do
{:put, key, value, caller} ->
new_state = Map.put(state, key, value)
send(caller, {:ok, key, value})
loop(new_state)
{:get, key, caller} ->
value = Map.get(state, key, :not_found)
send(caller, {:ok, value})
loop(state)
end
end
end
pid = RawProcessKeyValueStorage.start()
#PID<0.181.0>
send(pid, {:get, :foo, self()})
receive do
val -> IO.puts("Response: #{inspect(val)}")
end
send(pid, {:put, :foo, "bar", self()})
receive do
val -> IO.puts("Response: #{inspect(val)}")
end
send(pid, {:get, :foo, self()})
receive do
val -> IO.puts("Response: #{inspect(val)}")
end
Response: {:ok, :not_found}
Response: {:ok, :foo, "bar"}
Response: {:ok, "bar"}
:ok
Process.exit(pid, :kill)
true