Introduce Calls and Casts

Learn how to introduce calls and casts in GenServer.

GenServer calls

More often than not, we want a meaningful response when we send a GenServer process a message. We might query the process’s state, or we might want to see the result of a command we’ve sent it. This is where calls come in.

GenServer calls are synchronous. They can return any arbitrary value to the caller, and if the caller is waiting for a return, it blocks until it gets one. handle_call/3 is the GenServer callback that handles calls. It’s similar to handle_info/2 in that its pattern matches a message as its first argument.

It’s different from handle_info/2 since it doesn’t accept messages sent directly from other processes. Instead, it’s triggered whenever we call GenServer.call/2.

Let’s try this out. In lib/islands_engine/game.ex, we add a clause of handle_call/3 that looks like this:

def handle_call(:demo_call, _from, state) do 
  {:reply, state, state}
end

Our aim is to have it return to the initial server state.

The key here is the first argument, :demo_call. This is the pattern that determines which clause of handle_call/3 to execute. We’ll see where it comes from shortly. Don’t worry about the other arguments. GenServer provides them internally.

The return value is different from the one we use in handle_info/2. It indicates that we’ll be replying to the caller. The middle element is the actual reply, and the third element is what we want the state of the GenServer process to be.

Our Game module now looks like this:

Get hands-on with 1200+ tech skills courses.