Skip to content

Instantly share code, notes, and snippets.

@danielberkompas
Created October 26, 2016 17:59
Show Gist options
  • Star 40 You must be signed in to star a gist
  • Fork 9 You must be signed in to fork a gist
  • Save danielberkompas/7212ef0ba261e4a19a0b86ec1e109282 to your computer and use it in GitHub Desktop.
Save danielberkompas/7212ef0ba261e4a19a0b86ec1e109282 to your computer and use it in GitHub Desktop.
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
@ranyefet
Copy link

@danielberkompas How does it work on Heroku with multiple dynos?
How do you make sure that tasks are only run once globally and not per dyno?

Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment