Jonathan Bennett

Recurring Jobs in Rails with Solid Queue

So last time, we looked at installing Solid Queue. Today we’ll use it to move some work off the request cycle and into a recurring background job.

The Current Setup

Right now, the system triggers an update to the kids’ schedule during page load. Here’s a simplified version of what that looks like:

class DashboardsController
  def show
	@dashboard = Dashboard.find_by(slug: params[:id])
	@dashboard.account.update_kids_schedule # 👎
  end
end

This works, but it slows down the page and means schedules aren’t up-to-date until someone visits the dashboard. We can do better.

Setting Up Jobs

We’ll break this out into two jobs: one to enqueue a job for each kid, and one to handle each kid’s schedule update.

# app/jobs/update_all_kids_schedule_job.rb
class UpdateAllKidsScheduleJob < ApplicationJob
  queue_as :default

  def perform
	Kid.all.each do |kid|
	  UpdateIndividualKidsScheduleJob.perform_later(kid)
	end
  end
end

# app/jobs/update_individual_kids_schedule_job.rb
class UpdateIndividualKidsScheduleJob < ApplicationJob
  queue_as :default

  def perform(kid)
	kid.schedule_for(Date.current)
  end
end

Run Automatically

Solid Queue makes it easy to schedule recurring jobs. In production, running once per hour is plenty. In development, you might prefer something more aggressive for faster feedback:

# config/recurring.yml
development:
  update_kids_schedule:
    class: UpdateAllKidsScheduleJob
    schedule: every minute

production:
  update_kids_schedule:
    class: UpdateAllKidsScheduleJob
    schedule: every hour

We can now remove all calls to update_kids_schedule in the controllers.

And that’s it—Solid Queue handles the rest.

Next Steps

There’s more we could do here:

  • Enqueue updates when a kid’s schedule is manually changed
  • Add throttling or priority handling for large numbers of kids
  • Retry failures or alert when jobs don’t complete

But for now, we’ve offloaded this work from page loads and automated the updates.