0x7fs
11/9/2016 - 11:41 PM

A simple mix task scheduler for Elixir apps

A simple mix task scheduler for Elixir apps

defmodule MyApp.Scheduler do
  @moduledoc """
  Schedules a Mix task to be run at a given interval in milliseconds.

  ## Options

  - `:task`: The name of the Mix task to run.
  - `:args`: A list of arguments to pass to the Mix task's `run/1` function.
  - `:interval`: The time interval in millisconds to rerun the task.

  ## Example

  In a supervisor:

      worker(MyApp.Scheduler, [[[
        task: "contest.pick_winners",
        args: [],
        interval: 60000
      ]]], id: :contest_winners)

  On its own:

      MyApp.Scheduler.start_link([task: "ping", args: [], interval: 3000])
  """

  use GenServer

  require Logger

  def start_link(opts) do
    {:ok, pid} = GenServer.start_link(__MODULE__, opts)
    :timer.apply_interval(opts[:interval], __MODULE__, :perform, [pid])
    {:ok, pid}
  end

  def perform(scheduler) do
    GenServer.cast(scheduler, :perform)
  end

  def handle_cast(:perform, opts) do
    Logger.info(~s{Scheduler running "mix #{opts[:task]}" with args #{inspect(opts[:args])}})
    Mix.Task.run(opts[:task], opts[:args])
    Mix.Task.reenable(opts[:task])
    {:noreply, opts}
  end
end