Sidekiq is one of the most popular open-source background job libraries for Ruby. As one of ActiveJob's most popular backends, it's often used to run asynchronous jobs in Rails applications.
It leans on Redis to manage queues and jobs, which makes it fast. Developers can run background jobs using Sidekiq with or without ActiveJob, and we'll explore both in this article.
Just as useful - Sidekiq scheduled jobs allow you to run a job after a given amount of time or at a given time. In this article, we will explore defining a background job, performing background jobs after a given time period as well performing them at a given time. You'll learn to do each of these scheduling methods both with ActiveJob
and without it.
Sidekiq scheduled jobs without ActiveJob
Using Sidekiq to write a Ruby background job with or without ActiveJob is very similar, but enqueuing the jobs is a bit different. In this section, we'll write a Ruby class that inherits from Sidekiq. Then, we'll explore a few ways to enqueue this job.
We won't explore Sidekiq Pro or Sidekiq Enterprise, but they offer advanced background jobs features including expiring unprocessed background jobs, job metric reporting, and even rate limiting.
First, you'll need to install the Sidekiq gem. Run:
gem install sidekiq
Sidekiq relies on Redis, so you'll need to install that.
brew install redis
Writing Sidekiq background jobs
Finally, we'll write a small Sidekiq job. In a new file called hello_job.rb
, paste the following:
require 'sidekiq'
class HelloJob
include Sidekiq::Job
def perform
puts "Hello from inside a background job!"
end
end
puts "hello from outside the job"
HelloJob.perform_async
puts "hello from after the job"
This class is a simple background job that prints out the message, Hello from inside a background job!". For this example, we print that text from outside the job, perform the job asynchronously, and print some text after that method call to indicate the order of execution.
Process background jobs with just Sidekiq
Because this job doesn't need ActiveJob, we can run it with only Redis.
Start Redis in the background using Homebrew:
brew services start redis
Then, run the background job with:
sidekiq -r ./hello_job.rb
The execution of the job is asynchronous, so it may execute before or after the "hello from after the job" text is printed to the console. In my case, the job executes after this text is printed.
Execution of the Sidekiq background jobs
Now, you can kill the sidekiq processes with CTRL + c
.
Scheduling a Sidekiq job with perform_in
Our first example defines the Sidekiq job and enqueues it in the same file. That enqueue method, perform_async
, runs the job in the background as soon as it can.
If you want to delay execution by an amount of time, enqueue the job with perform_in
instead. We'll change the earliest example to do this, scheduling the job for 1 minute from enqueue.
require 'sidekiq'
class HelloJob
include Sidekiq::Job
def perform
puts "Hello from inside a background job!"
end
end
puts "hello from outside the job"
HelloJob.perform_in(60)
puts "hello from after the job"
You can run this job by starting a Sidekiq worker with:
sidekiq -r ./hello_job.rb
Scheduling a Sidekiq job with perform_at
If you know when your job should execute, you should use the perform_at
method to enqueue it for a given time. The original example, when using this method, looks like this:
require 'sidekiq'
class HelloJob
include Sidekiq::Job
def perform
puts "Hello from inside a background job!"
end
end
puts "hello from outside the job"
HelloJob.perform_at(Time.now+60)
puts "hello from after the job"
Using Sidekiq with ActiveJob for Rails background jobs
ActiveJob exists to make it easy to create and run background jobs in Rails with an abstract backend. Sidekiq is a popular backend for managing these jobs, but changing to another option like Solid Queue is trivial thanks to this abstraction.
You can use Sidekiq for Rails scheduled jobs without ActiveJob, but we'll focus on using ActiveJob.
Setting up the Rails application
If you don't already have a Rails project, create one:
rails _7.1.1_ new background-job-example-app
Then, cd
into the newly created directory
cd background-job-example-app
Writing a background job with ActiveJob
Next, use a Rails generator to create a new job file:
rails generate job hello_world
This will create a new app/jobs/hello_world_job.rb
file, in which you should paste the following code:
class HelloWorldJob < ApplicationJob
queue_as :default
def perform(*args)
puts "Hello from inside a background job!"
end
end
Configuring ActiveJob and Sidekiq
Next, we'll set up ActiveJob to use Sidekiq. In config/application.rb
, set the queue adapter:
config.active_job.queue_adapter = :sidekiq
Finally, add the Sidekiq Gem to the Gemfile by running:
bundle add sidekiq
Configuring the Sidekiq UI
Sidekiq ships with the Sidekiq dashboard, which makes it easy to monitor job execution, you just have to mount it in config/routes.rb
file:
require 'sidekiq/web'
# or require 'sidekiq/pro/web'
# or require 'sidekiq-ent/web'
Myapp::Application.routes.draw do
mount Sidekiq::Web => "/sidekiq" # mount Sidekiq::Web in your Rails app
...
end
Running the background job with perform_later
If you haven't already, start Redis in the background using Homebrew:
brew services start redis
Start your Rails app by running rails server
and visit the Sidekiq UI at localhost:3000/sidekiq
In a separate terminal window, open a Rails console with rails c
and enqueue the new job with perform_later
:
HelloWorldJob.perform_later
Looking at the Sidekiq UI, you can see the number of jobs you've enqueued, completed jobs, and failed jobs. This is particularly helpful when debugging failed jobs or remediating an incident in a production environment.
The Sidekiq UI with one job executed and one enqueued
This example only demonstrated asynchronous job execution, not scheduled jobs. Enqueueing a job can be combined with a set method call to schedule a job for a time or amount of time in the future.
Running an ActiveJob job at a future time
Rather than calling HelloWorldJob.perform_later
in the Rails console, we can chain a set
method call to perform the job at some future time. To perform this job tomorrow night, run this in the Rails console:
HelloWorldJob.set(wait_until: Date.tomorrow.at_end_of_day).perform_later
This schedules the job for the DateTime
of just before midnight the day after it's run. We don't have to wait for the job to execute to see that it was scheduled without errors. The Sidekiq UI shows that the job is properly scheduled and waiting for its execution time.
The Sidekiq scheduled jobs UI showing 1 scheduled job
Running an ActiveJob job after some time
Scheduling a job with ActiveJob to run some time in the future relative to the current time is a similar process. In the Rails console, run:
HelloWorldJob.set(wait_until: 2.minutes).perform_later
This schedules the job for the time 2 minutes from the current time, and can be validated with the Sidekiq UI.
Monitoring Sidekiq with Honeybadger
Our Ruby gem monitors Sidekiq errors automatically, so all you need to do is install it). You can also monitor Sidekiq metrics with Honeybadger Insights if you use bundle exec honeybadger install API_KEY --insights
when installing the gem.
Honeybadger automatically monitors Sidekiq errors, giving you visibility into your background jobs. First, install the Honeybadger gem by adding it to your Gemfile:
gem 'honeybadger'
Next, run:
bundle install
Finally, set up the gem with your API key:
bundle exec honeybadger install <Your project API key>
You can also use Honeybadger Insights to monitor Sidekiq metrics directly. If you're installing the Gem for the first time, you can use this install command:
bundle exec honeybadger install API_KEY --insights
Leveraging Sidekiq for delayed jobs in Rails
Sidekiq is a powerful tool for handling background jobs in Ruby and Rails applications. Whether you choose to use it standalone or integrate it with ActiveJob, Sidekiq offers robust capabilities for asynchronous job processing and scheduling.
By learning how to write Sidekiq scheduled jobs, you can optimize your application's performance and improve user experience by offloading time-consuming operations to the background. Whether you're building a small application or building Ruby on Rails background jobs with Sidekiq, understanding Sidekiq is a crucial skill for any Ruby or Rails developer.
If you want to take advantage of Honeybadger's monitoring, whether for Sidekiq errors or metrics, sign up for a free trial today!