Schedule Background Job in Elixir via GenServer. Part 1: Run at least once an hour (day/minute/etc)

Anastasiya Dyachenko
3 min readJan 3, 2021

All parts:

  1. Schedule Background Job in Elixir via GenServer. Part 1: Run at least once an hour (day/minute/etc)
  2. Schedule Background Job in Elixir via GenServer. Part 2: Run at most once an hour (day/minute/etc)
  3. Schedule Background Job in Elixir via GenServer. Part 3: Run at the specific time of day (week/month/etc): coming soon
  4. Schedule Background Job in Elixir via GenServer. Part 4: Run according to a complex schedule: coming soon

Elixir provides a built-in easy way to schedule a job. Let’s take a look!

The simplest way to run a job periodically is to use a unified interval.

First of all, we set a timeout in the init/1 callback, by passing the third element to the return tuple. GenServer’s timeout will send a :timeout message to the process, so we define handle_info(:timeout, state) callback. And the handle_info/2 callback is also ended with the timeout in the return tuple, that way we enter the loop.

So the process will work like this:

Timeouts can also be set the same way, by passing the last element to a return value, in the handle_call/3 , handle_cast/2 , handle_continue/2 and handle_info/2 callbacks. Timeouts dimension is milliseconds, same as erlang’s timer module provides. Be aware that allowable maximum timeout equals maximum integer value in milliseconds, which is 2,147,483,647 or 24 days 20 hours 31 minutes 23 seconds and 647 milliseconds. Beyond this limit a GenServer will fail with the error: :timeout_value .

But timeout() couldn’t be set together with:hibernate or {:continue, term()} opts. In that case, you can use Process.send_after(self(), :timeout, @timeout) , it is another way to do the same:

If you want to run the code immediately after start without waiting an hour before the first run, you could rewrite the part with init/1 callback with handle_continue/2 :

Altered process flowchart:

When to use this method:

  • if you don’t care about the exact once per interval execution of the code
  • when the code is not related to a specific time of the day(week/month/etc)

Honestly, we cannot provide at least once per interval execution guaranty neither because the server may lay down for longer than the interval due to errors or deployment of an update, keep that in mind.

However, we can provide at most once execution guaranty by memorizing the last run timestamp.

--

--