Multiple intervals for GenServer

I want to invoke 2 different tasks with different times intervals in GenServer, one every 20 seconds, other every 30 minutes. I know how send a message to yourself and that’ll allow to run GenServer every N seconds/minutes/whatever. But in my case I have 2 time intervals. How would I go about implementing that?

You can have multiple timers.

This is using erlang code. I am sure elixir has an equivalent but can’t remember :confused: This should give you an idea though

{:ok, tref1}  = :timer.send_interval(:timer.seconds(20), self(), :short_interval)
{:ok, tref2} =  :timer.send_interval(:timer.minutes(30), self(), :long_interval)

The tref is a reference to the timer so you can cancel them if you want to.

NOTE: Edited to use send_interval instead of send_after

That’s only a part of my question.

Ok,

So in GenServer init you start the timers. You may want to store the tref in the state.

The timers will send you a message at the given interval. In your GenServer your you implement handle_info(…) to intercept these messages and perform the job you want.

Note that send_interval will send every X seconds. This means even if your task actually hasn’t finished in that time and then you might want have a flag in your state to keep track if you are already running. Alternatively use send_after instead to manually re-start the timer after you have performed a particular task.

1 Like

PS: Sorry - just noticed you’re discussing repeating timers

To avoid duplication I lean towards a simple

self() ! short_interval % Erlang
self() ! long_interval

.

Kernel.send self(), :short_interval # Elixir
Kernel.send self(), :long_interval

in init/1 to get things started and therefore leaving the timer specific code in the handle_info/2 function clauses.

The functions for managing one-off timers in Elixir are Process.send_after/4 and Process.cancel_timer/1 - just today I posted some sample code that uses them here.

1 Like

Yes, this is good advice

There is also always my library TaskAfter that combines all timers to a single set if you need to have a lot going, in addition to being able to run a task or send a message or whatever as well, has a lot of features.

Though I’d probably use Quantum to manage the timers since it sounds like you want something more cron-like based on your description, just have it call something that sends the message. :slight_smile: