Running Quantum in an Elixir Cluster
- 2 minutes read - 386 wordsIn one of the projects that I work on, for the sake of availability and reliability, we are running our Phoenix app in a cluster of 3 servers using libcluster. Initially, it was just running on a single server and I had configured Quantum to run our recurring tasks on a cron like schedule. This worked well, and I had no issues with the setup. When we decided to move to a clustered setup, there was a consideration concerning Quantum. I didn’t want the jobs to run on multiple servers, I wanted to have a single server responsible for handling all the scheduled jobs so as to keep duplicate jobs from running. I looked around and found someone who had written about using Highlander to make sure there was only a single instance of Quantum running on the cluster at a time. I decided to try this out.
The first thing that I need to do was add Highlander to the project by adding it to the mix.exs
file.
def deps do
[
...
{:highlander, "~> 0.2.1"},
...
]
end
Next you need to configure your application.ex
file to allow Highlander to control the Quantum application in the cluster.
defmodule MyApp.Application do
use Application
def start(_type, _args) do
children = [
MyApp.Repo,
{Phoenix.PubSub, name: MyApp.PubSub},
MyAppWeb.Endpoint,
# libcluster setup
{Cluster.Supervisor,
[Application.get_env(:libcluster, :topologies), [name: MyApp.ClusterSupervisor]]},
# Highlander set to control the Quantum scheduler process
{Highlander, MyApp.Scheduler}
]
opts = [strategy: :one_for_one, name: MyApp.Supervisor]
Supervisor.start_link(children, opts)
end
def config_change(changed, _new, removed) do
MyAppWeb.Endpoint.config_change(changed, removed)
:ok
end
end
Here’s what the Quantum scheduler file looks like.
defmodule MyApp.Scheduler do
@moduledoc """
Quantum scheduler
"""
use Quantum, otp_app: :my_app
end
One important note is when creating your Quantum jobs, you need to specify the run strategy as Local, so the jobs only run locally. Otherwise it might attempt to run them on other nodes which don’t have Quantum runnning on them.
weekly_fulfillment_report: [
schedule: "30 17 * * 1",
run_strategy: Quantum.RunStrategy.Local,
task: {MyApp.Reports, :fulfilled_order_report, []}
],
That’s it! Now only a single Quantum instance will run inside the cluster. If the node goes down that is running Quantum, Highlander will start it up on a different node in the cluster. It is pretty slick and works great.
Hopefully that gives you enough information to get Quantum runnning in your cluster!