Scheduled function - Task or Agent?

In a tick based game, I needed a timer to send periodic events. But I wanted to be able to pause/resume the interval. So Maybe You can use this …

defmodule Whatever.Ticker do
  use GenServer
  require Logger
  @name __MODULE__
  
  defstruct ... tick_interval: 500, ticker_ref: :none
...
  def handle_cast(:start_timer, %{tick_interval: tick_interval, ticker_ref: ticker_ref} = state) 
    when ticker_ref == :none do
    Logger.debug "#{@name} started"
    
    {:ok, new_ticker_ref} = :timer.send_after(tick_interval, :tick)
    {:noreply, %{state | ticker_ref: new_ticker_ref}}
  end

  def handle_cast(:start_timer, state), do: {:noreply, state}

  def handle_cast(:stop_timer, %{ticker_ref: ticker_ref} = state) 
    when ticker_ref == :none do
    {:noreply, state}
  end

  def handle_cast(:stop_timer, %{ticker_ref: ticker_ref} = state) do
    Logger.debug "#{@name} cancelled"
    
    :timer.cancel(ticker_ref)
    {:noreply, %{state | ticker_ref: :none}}
  end
...
end

You store the ticker ref in state, then you can cancel it. I also stored interval, because I wanted to be able to accelerate the game after some time. I saw this here http://www1.erlang.org/examples/small_examples/index.html from Joe Armstrong, Tetris sample.

You can define the interval to 15 minutes.

I hope this help

3 Likes