0
votes

Forgive me if I don't understand elixir really well as I am new to it...

I'm using quantum-elixir as a cron api to dynamically create cron jobs. When someone POSTS to a route I save the cron job details into my Ecto Repo and then simultaneously create a quantum job with Quantum.add_job.

In development when I close my server and restart it, i have to re-add all my cron jobs because they don't survive through a restart. So that got me thinking that if my application were to crash that would make me lose all the cron jobs. (I'm thinking about of scenarios where I host the app on Google compute engine and for whatever reason need to do a reset on the compute instance, ie upgrades on the box, etc.)

So I was wondering what the appropriate way to restart my app is while keeping these cron jobs?

Right now I have the following:

worker(Task,[MyApp.RebootTask, :reboot, []], restart: :transient)

in the start function of my application module.

Is this the right approach? What other considerations do I need to factor in?

Any guidance is greatly appreciated

2

2 Answers

2
votes

I query my db and create a list with the job definition of every item

%Quantum.Job{
      name: job_name,
      overlap: false,
      run_strategy: %Quantum.RunStrategy.Random{nodes: :cluster},
      schedule: Crontab.CronExpression.Parser.parse!(schedule),
      task: task,
      state: :active,
      timezone: "Europe/Zurich"
}

To have the jobs started at application startup, I do something like this

defmodule Alerts.Scheduler do


use Quantum.Scheduler, otp_app: :alerts
  require Logger

  @environmet_blacklist [:test]

  def init(opts) do
    case Enum.member?(@environmet_blacklist, Mix.env()) or IEx.started?() do
      true ->
        IO.inspect(opts)
        opts

      false ->
        delete_all_jobs()
        opts_with_jobs = get_startup_config(opts)
        opts_with_jobs |> IO.inspect()
        opts_with_jobs
    end
  end

  def get_startup_config(opts) do
    job_definition = Alerts.Business.Alerts.get_all_alert_jobs_config()
    (opts |> List.delete(List.keyfind(opts, :jobs, 0))) ++ [jobs: job_definition]
  end

In my application start

  def start(_type, _args) do
    [
      Alerts.Repo,
      AlertsWeb.Endpoint |> supervisor([]),
      if(System.get_env() != :test, do: Alerts.Scheduler),
      Alerts.VersionSupervisor |> supervisor([])
    ]
    |> Supervisor.start_link(strategy: :one_for_one, name: Alerts.Supervisor)
  end
0
votes

It doesn't look like Quantum persists dynamically-added cronjobs, since the more typical approach is to define your cronjobs (named or otherwise) in your config.exs.

Since you're already storing the job details with Ecto, it's just a matter of reading those details and readding them when your application starts. Since you're already using Quantum, the following in config/config.exs ought to do the trick:

config :quantum, cron: [
  "@reboot": &MyApp.some_function_to_read_and_readd_my_cronjobs/0
]