19 June 2018. Erlang OTP 21.0 has been released today and I’m going to
describe how new :gen_server handle_continue callback works.
Erlang 21.0 and Elixir 1.6.6-otp-21 installed using asdf version manager
Initial state of our GenServer is 0 and it implements single handle_info that
increments state by 1 and logs new value.
Inside init callback we are sending three :inc_and_log messages to
GenServer itself and logging additional message, so when we start it we can
see following logs:
Nothing special so far.
Let’s modify handle_info return value and add new handle_continue callback.
When we start our GenServer now, we can see different values in logs:
The reason for this is that when any callback returns {:continue, term} then
handle_continue is invoked immediately. In other words after every
handle_info there was handle_continue which incremented state value one more time.
Let’s imagine call that returns current state and calculates new one.
Process invoking call doesn’t need to know new state, but it’s blocked until calculation ends.
It also can’t be solved by moving calculation to handle_info callback because
it can’t be guaranteed that there are no other messages waiting for being processed.
It’s a kind of situation where handle_continue is very convenient:
There's no support for handle_continue in elixir yet. It means that @impl true
before handle_continue will result in compilation warning.
(EDIT: this is no longer true for Elixir v1.7)