GenServer is an OTP protocol. OTP works by assuming that your module defines a number of callback functions (six, in the case of a GenServer). If you were writing a GenServer in Erlang, your code would have to contain implementations of all six.
When you add the line ‘use GenServer‘ to a module, Elixir creates default implementations of these six callback functions. All we have to do is override the ones where we add our own application-specific behavior. Our examples so far have used the three callbacks ‘init‘, ‘handle_call‘, and ‘handle_cast‘. Here’s a full list:
Called by GenServer when starting a new server. The parameter is the second argument passed to start_link. It should return {:ok, state} on success, or {:stop, reason} if the server could not be started.
You can specify an optional timeout using {:ok, state, timeout}, in which case GenServer sends the process a :timeout message whenever no message is received in a span of timeout ms. (The message is passed to the handle_info function.)
The default GenServer implementation sets the server state to the argument you pass.
Invoked when a client uses GenServer.call(pid, request). The from parameter is a tuple containing the PID of the client and a unique tag. The state parameter is the server state.
On success it returns {:reply, result, new_state}. The list that follows this one,, shows other valid responses.
The default implementation stops the server with a :bad_call error, so you’ll need to implement handle_call for every call request type your server implements.
Called in response to GenServer.cast(pid, request).
A successful response is {:noreply, new_state}. It can also return {:stop, reason, new_state}.
The default implementation stops the server with a :bad_cast error.
Called to handle incoming messages that are not call or cast requests. For example, timeout messages are handled here. So are termination messages from any linked processes. In addition, messages sent to the PID using send (so they bypass GenServer) will be routed to this function.
Called when the server is about to be terminated. However, as we’ll discuss in the next chapter, once we add supervision to our servers, we don’t have to worry about this.
Updates a running server without stopping the system. However, the new version of the server may represent its state differently from the old version. The code_change callback is invoked to change from the old state format to the new.
Used to customize the state display of the server. The conventional response is [data: [{’State’, state_info}]].
The call and cast handlers return standardized responses. Some of these responses can contain an optional :hibernate or timeout parameter. If hibernate is returned, the server state is removed from memory but is recovered on the next request. This saves memory at the expense of some CPU. The timeout option can be the atom :infinite (which is the default) or a number. If the latter, a :timeout message is sent if the server is idle for the specified number of milliseconds.
The first two responses are common between call and cast.
{ :noreply, new_state [ , :hibernate | timeout ] }
Signal that the server is to terminate.
Only handle_call can use the last two.
Send response to the client.
Send the response and signal that the server is to terminate.