1
votes

I need to run an ActiveJob in my Rails 5 application as often as possible.

Up until now, I was using a cron job that was defined using the whenever gem (used Crono in the past).

This approach boots up the entire rails app before it does its thing, and then shuts down and does it all over again. I wish to avoid it, and instead have a persistent "service" that does the job.

I bumped into the Rufus Scheduler gem which seems nice, but then I started wondering if I need it at all.

So, my question is:

Are there any meaningful differences between these two options below:

# With Rufus
scheduler = Rufus::Scheduler.new
scheduler.every('1s') { puts 'hello' }
scheduler.join

# Without Rufus
loop { puts "hello" ; sleep 1 }

Note that either of these scripts will be executed with rails runner my_scheduler.rb as a docker container, and any solution must ensure the job runs once only (never two in parallel).

1
"Are there any meaningful differences" - yes, the first one doesn't lock up the main thread (or any thread, for that matter).Sergio Tulentsev
Since this is a service with one of these scripts only, and no other responsibilities - why does it matter if it locks or not? In fact, I want it to lock, wait until the job ends, and then sleep and repeat.DannyB
You asked, I answered. ¯\_(ツ)_/¯ In your case, the second option might be more preferable indeed (precisely because of the locking).Sergio Tulentsev
And thanks for that :) - it is a difference for sure, just not sure if meaningful for my case.DannyB
Oh, but it is. In your setup the rufus code will insta-terminate without doing anything.Sergio Tulentsev

1 Answers

2
votes

There are differences.

Rufus-scheduler every will try to run every 1s, so at t0 + 1, t0 + 2, t0 + 3, etc. While the "sleep" variant will run at t0, t0 + wt1 + 1, t0 + wt1 + 1 + wt2 + 1, ... (where wtN = work time for Nth call of puts hello).

Rufus-scheduler every will use rufus-scheduler work threads so that if there is an overlap (wt(Nb) > wt(Na)), Nb will occur anyway. This behaviour can be changed (see job options).

Rufus-scheduler interval is closer to your sleep option:

scheduler.interval('1s') { puts 'hello' }

It places 1 second (or whatever time interval you want) between each run of puts 'hello'.

For a simple do-sleep-loop, I'd go with the sleep option. But if you need more, rufus-scheduler has cron, interval, every and tuning options for them. And you can schedule multiple jobs.

scheduler.cron('0 1 1 * *') do
  # every first of the month at 1am
  flush_archive
end
scheduler.cron('0 8,13,19 * * mon-fri') do
  # every weekday at 8am, 1pm, 7pm
  clean_dishes
end
scheduler.interval('1s') do
  puts 'hello'
end