Engineering

Quick look at new :gen_server handle_continue callback

Quick look at new :gen_server handle_continue callback

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.

Setup

Erlang 21.0 and Elixir 1.6.6-otp-21 installed using asdf version manager

Let’s write something basic

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.

Continue

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.

More realistic use case

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:

Last thing

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)