does elixir have its only function for send_interval?

Viewed 90

In Process module, I haven't found function like erlang's function such as timer:send_interval. Does it exist or I have to call :timer:send_interval?

1 Answers

:timer.send_interval/2 is prone to the message box overloading if the handler takes more time to process than the interval. That’s why in we use the following approach with Process.send_after/4.

defmodule MyMod do
  use GenServer

  @impl GenServer
  def init(state) do
    state =
      state
      |> Map.put_new(:interval, 5_000)
      |> Map.put_new(:schedule, nil)

    # optional; to be called if the first message
    #           from outside expects the periodic
    #           function to be called at least once
    # {:noreply, state} = handle_info(:work, state)
    {:ok, state}
  end

  @impl GenServer
  def handle_info(:work, state) do
    # process periodic event

    # optional; to allow calling it from outside without
    #           setting many subsequent timers
    # if is_reference(state.schedule),
    #   do: Process.cancel_timer(state.schedule)

    {:noreply, Map.put(state, :schedule, schedule_work(state.interval))}
  end

  @spec schedule_work(interval :: non_neg_integer()) :: :error | reference()
  defp schedule_work(interval) when is_integer(interval) and interval > 0,
    do: Process.send_after(self(), :work, interval)

This approach guarantees that the interval would last between the time when the previous message has been handled and the new message.

Sidenote: to call functions from , one uses the same dot notation as calling domestic functions (module[dot]function), e. g.: :timer.send_interval not :timer:send_interval.

Related