Packages
quantum
1.2.3
3.5.3
3.5.2
retired
3.5.1
retired
3.5.0
3.4.0
3.3.0
3.2.0
3.1.0
3.0.2
3.0.1
3.0.0
3.0.0-rc.3
3.0.0-rc.2
3.0.0-rc.1
2.4.0
2.3.4
2.3.3
2.3.2
2.3.1
retired
2.3.0
retired
2.2.7
2.2.6
2.2.5
retired
2.2.4
retired
2.2.3
retired
2.2.2
retired
2.2.1
retired
2.2.0
retired
2.1.3
retired
2.1.2
retired
2.1.1
retired
2.1.0
retired
2.1.0-beta.1
retired
2.0.4
retired
2.0.3
retired
2.0.2
retired
2.0.1
retired
2.0.0
retired
2.0.0-beta.2
retired
2.0.0-beta.1
retired
1.9.3
retired
1.9.2
retired
1.9.1
retired
1.9.0
retired
1.8.1
retired
1.8.0
retired
1.7.1
retired
1.7.0
retired
1.6.1
retired
1.6.0
retired
1.5.0
retired
1.4.0
retired
1.3.2
retired
1.3.1
retired
1.3.0
retired
1.2.4
retired
1.2.3
retired
1.2.2
retired
1.2.1
retired
1.2.0
retired
1.1.0
retired
1.0.4
retired
1.0.3
retired
1.0.2
retired
1.0.1
retired
1.0.0
retired
Cron-like job scheduler for Elixir.
Retired package: Security issue - v1 is no longer supported
Current section
Files
Jump to
Current section
Files
lib/quantum.ex
defmodule Quantum do
use GenServer
@typedoc "A function/0 to be called when cron expression matches"
@type fun0 :: (() -> Type)
@typedoc "A job is defined by a cron expression and a function/0"
@type job :: {String.t | Atom, fun0}
@doc "Adds a new job"
@spec add_job(String.t, fun0) :: :ok
def add_job(spec, job) do
GenServer.call(__MODULE__, {:add_job, convert(spec), job})
end
@doc "Returns the list of currently defined jobs"
@spec jobs :: [job]
def jobs do
GenServer.call(__MODULE__, :jobs)
end
def init(_) do
tick
jobs = Application.get_env(:quantum, :cron, [])
|> Enum.map(&convert/1)
|> Enum.filter(&reboot/1)
{:ok, %{jobs: jobs, d: nil, h: nil, m: nil, w: nil}}
end
def handle_call({:add_job, spec, job}, _from, state) do
{:reply, :ok, %{state | jobs: [{spec, job} | state.jobs]}}
end
def handle_call(:jobs, _from, state) do
{:reply, state.jobs, state}
end
def handle_info(:tick, state) do
{d, h, m} = tick
if state.d != d, do: state = %{state | d: d, w: rem(:calendar.day_of_the_week(d), 7)}
state = %{state | h: h, m: m}
Enum.each(state.jobs, fn({e, fun}) -> execute(e, fun, state) end)
{:noreply, state}
end
def handle_info(_, state), do: {:noreply, state}
defp convert({e, fun}), do: {convert(e), fun}
defp convert(e) when e |> is_atom, do: convert e |> Atom.to_string
defp convert(e), do: e |> String.downcase |> Quantum.Translator.translate
defp execute(e, fun, state) do
Task.start(Quantum.Executor, :execute, [e, fun, state])
end
defp reboot({"@reboot", fun}) do
Task.start(fun)
false
end
defp reboot(_), do: true
defp tick do
{d, {h, m, s}} = :calendar.now_to_universal_time(:os.timestamp)
Process.send_after(self, :tick, (60 - s) * 1000)
{d, h, m}
end
end