Running scheduled tasks in Elixir with Quantum

Quantum is a beautiful and configurable library that allows running scheduled tasks on an Elixir system/application. Even though the documentation may seem adequate to an experienced Elixir/Erlang programmer, being a newcomer it was a bit confusing to me. So, I’m trying my best to explain this so that when I forget, I have a reference…

If you’re future me or a lost soul, continue reading.

What is the problem we’re trying to solve exaclty?

On a software system, there are a few tasks that need scheduled running. Examples of such tasks would be, a database backup that runs everyday at 12 AM. Or, fetching data from some API that updates at 10 PM every day and you just call that API and populate your database. Or, you might need to check the connection with other services each minute. Or. think about renewing your website’s SSL certificate every 3 months. All of these tasks are traditionally handled by the cron jobs of Linux. But we can do better.

Let’s say, you’re deploying your application to 10 different servers. And you run identical scheduled jobs in each server because they are a fleet of identical systems. Yes, you can configure your cron jobs in each of those servers or you can ship your application with its own scheduler and job queue. So that you don’t have to do any extra configuration on an individual server. One less configuration means, one less scope to screw things up. (Don’t ask how many times I’ve messed up crontab in a production server)

Ok, but is shipping a scheduler with my app a good idea?

Well, it depends.

Even though I’m not qualified to talk about how BEAM handles concurrency and schedules the processes, I can link a blog post. Basically, the scheduler process is very light weight and it doesn’t block anything. It’s all handled by the magic we know as BEAM. So, you would barely notice any performace hit shipping a task scheduler with your Elixir application.

Tell me more about that Quantum thing.

According to Quantum‘s documentation Quantum is a “Cron-like job scheduler for Elixir.” Basically it let’s us run our Elixir/Erlang fucntions in a scheduled manner. I’m not going to cover everything about how to utilize this library in your application, you can read their documenation for that. I’ll only cover a few things that I wish I could figure out faster than I was able to when I first used this library.

1. Job format in config.exs file

So, in the Usage section of the documentation they tell you a job format like {"* * * * *", {Heartbeat, :send, []}} but it was really confusing for me to understand what those parameters were. I later figured out that inside the tuple, Heartbeat was the module name, :send is a fucntion inside that Heartbeat module and [] was the argument to that :send fucntion. So the job was bascially calling the Heartbeat.send/0 fucntion. In retrospect, it feels really dumb thinking how much I time I spent figuring this out.

2. You need a TimeZone database

So, like most of us your server timezone might be set to UTC. But you live in Bangladesh and you need to send a daily reminder to your collegues at 10 AM Asia/Dhaka time. Instead of doing the math that Asia/Dhaka time is actually UTC+6, you want to directly type 10 in your job configuration. You look into Quantum’s amazing documentation and find that it has time zone support. Before you jupm and copy the code block for TZ support, becareful and notice that you actually need another module Tzdata and config :elixir, :time_zone_database, Tzdata.TimeZoneDatabase this line in your config.exs file.

Good Bye!

These were the two problems I struggled a bit and spent more time than I should have. So, I’m just documenting them. If you have any other questions, problems or opinions that I’ve not listed here, please put them in the comments or email to me at [email protected] I’d love to hear your experience. I’m alvailable with @m4hi2 handle, almost everywhere. Thanks for reading. 😀