Mar 28 2016
Work on a web app long enough, and you’ll come across some sort of task that needs to be accomplished by your app at regular intervals. Some examples might include pruning inactive user accounts, sending reminder emails, or running custom analytics.
My first introduction to these sorts of tasks was at a previous job. A Rails app needed to run a task at regular intervals, and used a gem called Clockwork. At first glance, this seems to be a decent solution to the problem – a lightweight Ruby daemon which triggers your code at regular intervals, using a nice DSL. However, after using it for a while, I decided it perhaps wasn’t the perfect tool. First of all, it adds a dependency to your app, and you need to take the time to learn the API and how to use it. You also need to monitor the Clockwork process to ensure that it restarts after a crash. You also need to ensure that the Clockwork process runs on a single app server; otherwise your job will be run multiple times. Plus, it turns out that timezones are hard.
When a recent requirement came up that could be solved by a periodic task, I ruled
Clockwork out, and decided to use some other common tools to accomplish the same goal.
As you may have surmised, I ended up using
cron to invoke
curl, and hit a
private URL in my app. While I’m sure many folks can point out downsides to such
an approach, it has a lot of appeal to me:
- Uses very basic, well-understood software that ships with most (all?) Linux systems.
- Hits your webapp, so you don’t have to deal with setting up a DB connection pool, logging, etc.
Cron syntax inscrutable to you? A quick Google search
should clear it up nicely. Don’t want to expose a sensitive or resource-intensive
task via a public URL? Use basic auth to secure it, returning a 404 if the auth
is missing. As a bonus,
cron will use your systems time, so you don’t have to worry
about the scheduled job missing a beat during DST (yes, this did in fact happen to me).