Search code examples
erlanggen-server

How to perform actions periodically with Erlang's gen_server?


I want to start a gen_server that additionally, will perform one action every minute.

What is the best way to schedule that?


Solution

  • You have two easy alternatives, use timer:send_interval/2 or erlang:send_after/3. send_interval is easier to setup, while send_after (when used in the Erlang module) is more reliable since it is a built-in function, see the Efficiency Guide.

    Using send_after also ensures that the gen_server process is not overloaded. If you were using the send_interval function you would get a message regardless if the process can keep up or not. With send_after being called just before the return in handle_info you only schedule a new message once you handled the previous one. If you want more accurate time tracking you can still schedule a send_after with the time set dynamically to something lower than ?INTERVAL (or even 0) to catch up.

    I would recommend something along the following lines in your gen_server:

    -define(INTERVAL, 60000). % One minute
    
    init(Args) ->
       ... % Start first timer
       erlang:send_after(?INTERVAL, self(), trigger),
       ...
    
    handle_info(trigger, State) ->
       ... % Do the action
       ... % Start new timer
       erlang:send_after(?INTERVAL, self(), trigger),
       ...
    

    Instead of trigger you could send something with a state if it is needed, like {trigger, Count} or something.