A lot of people ask which library is my go-to for scheduling jobs in Elixir. To be honest, I don't usually need any 3rd-party deps for this!
Just using GenServer
This site has a scheduler that runs daily at midnight and gives a point of "green elixir" to members each day and other users once a week. I named the module Campsite.Scheduler
(and included it in the children block of application.ex
:
defmodule Campsite.Scheduler do
use GenServer
@full_day 3600 * 24 * 1000
@admin_green_rate 5
def start_link(_opts) do
GenServer.start_link(__MODULE__, %{}, name: CampScheduler)
end
def init(state) do
schedule_daily()
{:ok, state}
end
def handle_info(:daily, state) do
if Date.day_of_week(DateTime.utc_now()) == 1 do
award_green_to_all()
else
award_green_to_members()
end
schedule_daily()
{:noreply, state}
end
# ... internal app logic
defp schedule_daily() do
{:ok, midnight} = Time.new(0, 0, 0)
ms_past_midnight = abs(Time.diff(midnight, Time.utc_now(), :millisecond))
ms_until_midnight = @full_day - ms_past_midnight
Process.send_after(self(), :daily, ms_until_midnight)
end
end
All in all, it's not very complex, but there is some arithmetic to calculate the time until midnight. In an app where there are a lot of cron-like calculations, it might make sense to reach for erlcron.
Using Quantum
A newer option is quantum. It's built on top of GenServer and GenStage and comes with a convenient cron-like syntax and quite a bit of robustness out of the box. To use it...
-
add
{:quantum, "~> 3.0"}
(or the current version) to your deps inmix.exs
-
create a scheduler module with
use Quantum, otp_app: :app_name
-
configure the new scheduler in
config.exs
to add jobs to it
Example scheduler:
defmodule Campsite.QuantumScheduler do
use Quantum, otp_app: :campsite
end
Example config.exs
block for the above scheduler:
config :campsite, Campsite.QuantumScheduler,
jobs: [
# prints the time (truncated to the second) every 3 seconds
{{:extended, "*/3 * * * * *"}, fn ->
DateTime.utc_now()
|> DateTime.truncate(:second)
|> IO.puts()
end},
]
No Comments