Powered by AppSignal & Oban Pro
Would you like to see your link here? Contact us

Timers

ticker.livemd

Timers

Setup

defmodule Ticker do
  use GenServer

  require Logger

  defstruct interval_seconds: 2,
            count: 0,
            timer_ref: nil

  def start_link(_) do
    state = %__MODULE__{} |> Map.from_struct()
    GenServer.start_link(__MODULE__, state, id: __MODULE__)
  end

  def init(%{interval_seconds: interval} = state) do
    Process.register(self(), :ticker)
    {:ok, %{state | timer_ref: Process.send_after(self(), :tick, interval * 1000)}}
  end

  def handle_info(:tick, %{interval_seconds: interval} = state) do
    Logger.info("Tick #{state.count}")
    ref = Process.send_after(self(), :tick, interval * 1000)

    {
      :noreply,
      %{update_in(state, [:count], &(&1 + 1)) | timer_ref: ref}
    }
  end

  def handle_info(:cancel, state) do
    Logger.info("Cancelled! At #{state.count}")
    Process.cancel_timer(state.timer_ref)
    {:noreply, %{state | timer_ref: nil}}
  end
end

case Process.whereis(:ticker) do
  pid when is_pid(pid) -> Process.exit(pid, :kill)
  _ -> :not_found
end

{:ok, pid} = Ticker.start_link([])
Process.send_after(pid, :cancel, 5_000)