A cast is an OTP asynchronous, fire-and-forget request: a client sends a message and immediately continues without waiting for a response. The server handles the request, updates its state, and loops with the new state. section 6.1.4 section 6.3
Use a cast when:
- The client does not need confirmation or a returned value. section 6.1.4
- Immediate responsiveness and scalability matter more than knowing whether processing succeeded. section 7.3.1 section 7.4
- Avoid it when the caller must know that the request arrived or completed; use a call when stronger consistency is required. section 7.4 section 11.3.4
- Control producer pressure carefully: casts can let messages accumulate in a server mailbox, consume memory, and eventually threaten the system. section 7.4 section 7.3.3
A cast-backed key-value update
A generic server exposes cast(pid, request), sends {:cast, request}, invokes handle_cast/2, and continues with the returned state. A key-value store can implement put as ServerProcess.cast(pid, {:put, key, value}) while retaining get as a synchronous call.
Listing 7.7 Database process (persistable_todo_cache/lib/todo/database.ex)
defmodule Todo.Database do
use GenServer
@db_folder "./persist"
def start do
GenServer.start(__MODULE__, nil,
name: __MODULE__ #1
)
end
def store(key, data) do
GenServer.cast(__MODULE__, {:store, key, data})
end
def get(key) do
GenServer.call(__MODULE__, {:get, key})
end
def init(_) do
File.mkdir_p!(@db_folder) #2
{:ok, nil}
end
def handle_cast({:store, key, data}, state) do #3
key #3
|> file_name() #3
|> File.write!(:erlang.term_to_binary(data)) #3
#3
{:noreply, state} #3
end #3
def handle_call({:get, key}, _, state) do #4
data = case File.read(file_name(key)) do #4
{:ok, contents} -> :erlang.binary_to_term(contents) #4
_ -> nil #4
end #4
#4
{:reply, data, state} #4
end
defp file_name(key) do
Path.join(@db_folder, to_string(key))
end
end
Inspect a GenServer database where store uses GenServer.cast and get uses GenServer.call, making the responsiveness-versus-certainty trade-off concrete. section 7.3.1
