2

I'm working on a Rails 5.2 project that requires a scheduled asynchronous task to run nightly. I've been looking at the differences between using the whenever gem to trigger an ActiveJob job, and using whenever to trigger an old-style rake task (/lib/tasks/some_task.rake) - I'm struggling to find much in the way of notable pros and/or cons either way. Taking the two basic example implementations below, what are the differences between the two strategies?

The differences that I can see, are that with ActiveJob, you get the added flexibility of selecting a queue for the job to run in, and triggering callbacks around the job, wheres with the rake task, you're limited to the single thread, and no callbacks are available.

Are there any other differences worth looking at?

ActiveJob

app/jobs/subscription_reminder_job.rb:

class SubscriptionReminderJob < ApplicationJob
  queue_as :default

  def perform
    Subscription.overdue.find_each do |overdue_subscription|
      UserMailer.subscription_reminder(overdue_subscription.user, overdue_subscription).deliver_later

      overdue_subscription.touch(:last_subscription_reminder_sent_at)
    end
  end
end

config/schedule.rb:

every :day, at: '12:00am' do
  runner "SubscriptionReminderJob.perform"
end

Rails Task

lib/tasks/send_subscription_reminders.rake:

task send_subscription_reminders: :environment do
  Subscription.overdue.find_each do |overdue_subscription|
    UserMailer.subscription_reminder(overdue_subscription.user, overdue_subscription).deliver_later

    overdue_subscription.touch(:last_subscription_reminder_sent_at)
  end
end

config/schedule.rb:

every :day, at: '12:00am' do
  rake "send_subscription_reminders"
end
simonlehmann
  • 852
  • 1
  • 10
  • 27
  • You want to judge the trade offs between two approaches to a solution to a problem. That is great! However, in order for anyone else to help you with this in a meaningful way, you need to provide rich detail about what the problem is. What are you trying to achieve? What will the job or task be doing? What is it's behaviour? Otherwise I can only speak in very general terms. When judging a tool you need to know what you'll be using the tool for. – Patrick Quigley Feb 18 '20 at 09:31
  • @PatrickQuigley Thanks for the feedback - the examples have been expanded upon to show iterating through a scope of records, dispatching an email, and updating an attribute. – simonlehmann Feb 18 '20 at 09:57
  • Added a answer based on what you've provided so far. It also prompts you to give more information. I can update the answer if you do provide that info however, there is a good chance that it'll give you enough food for thought for you to progress pal! Let me know how you get on. – Patrick Quigley Feb 20 '20 at 15:18
  • Did my answer help you at all @slehmann36? – Patrick Quigley Mar 14 '20 at 13:26

1 Answers1

0

What will peak load look like?

What about average load?

How reliable does it need to be?

Information like that is essential when judging what route to go down.

Answering based on what info is provided so far

You're wanting to send X emails daily, during presumably low usage periods of your system. Based on what you've provided so far this looks to be a simple use case really.

There isn't any major difference between the two approaches you've suggested. Rails is all about convention over configuration. Unless you've a very good reason not to, you should use the ActiveJob framework. It serves as an API for job infrastructure, allowing you to easily swap the queuing backend implementation whenever requirements change.

You've not suggested any requirement which would indicate breaking from convention would be useful here. Keep it simple and leverage what makes Rails so good, it's conventions do a lot of the work for you.

Intro to ActiveJob, snippet below taken from it.

The main point is to ensure that all Rails apps will have a job infrastructure in place. We can then have framework features and other gems build on top of that, without having to worry about API differences between various job runners such as Delayed Job and Resque. Picking your queuing backend becomes more of an operational concern, then. And you'll be able to switch between them without having to rewrite your jobs.

Which queue backend should you use? Start simple with sidekiq and go from there. Build iteratively. If you reach a stage where sidekiq is limiting you, ActiveJob makes switching it for another queue tool easy. Good times!

Patrick Quigley
  • 404
  • 2
  • 12