Powered by AppSignal & Oban Pro

1. Raw process message exchange

1_raw_process_message_exchange.livemd

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