Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Sidekiq Pro Integration

This project uses sidekiq-pro ~> 5.0.0 on top of Sidekiq 5.2.10.

Enabled Features

  • Client reliability: Sidekiq::Client.reliable_push! is enabled outside test.
  • Server reliability: super_fetch! and reliable_scheduler! are enabled for server processes outside test.
  • Pro Web UI: config/routes.rb explicitly requires sidekiq/pro/web, so the existing /sidekiq admin UI includes Pro tabs such as Batches and queue pause/unpause controls.
  • Expiring jobs: sidekiq/pro/expiry is required in the Sidekiq initializer, so workers can use sidekiq_options expires_in: ....
  • Batch test support: RSpec adds Sidekiq::Batch::Server middleware so batch callbacks can run in Sidekiq::Testing.inline!.

Not Enabled By Default

  • Metrics: Pro Metrics is not enabled because this repo does not currently configure a StatsD or DogStatsD client.
  • Batch polling endpoint: the Rack middleware from sidekiq/rack/batch_status is not mounted. That endpoint would be public unless we add an authenticated boundary for it.

Reliability Notes

The enabled reliability features come from the Sidekiq Pro wiki:

  • reliable_push! reduces job loss when the client temporarily loses Redis connectivity.
  • super_fetch! keeps jobs in Redis until execution completes, improving crash recovery.
  • reliable_scheduler! atomically moves scheduled jobs into queues.

These are intentionally disabled in test to avoid masking test failures or changing Sidekiq testing semantics.

Batches

Use batches when the app needs to fan out work in parallel and run a callback once that work is complete.

Important rules from the Sidekiq Pro docs:

  • Use native Sidekiq workers, not ActiveJob, for batch workflows.
  • Do not disable retries for jobs inside a batch.
  • Only call batch.jobs once when initially creating a batch.
  • Jobs may reopen their own batch to add more work.
  • Callbacks may reopen the parent batch to create the next workflow step.

Simple Pattern

class PackageExportBatchWorker < ApplicationWorker
  sidekiq_options queue: :longprocess

  def self.enqueue!(export_id, package_ids)
    batch = Sidekiq::Batch.new
    batch.description = "Package export #{export_id}"
    batch.callback_queue = 'critical'
    batch.on(:success, 'PackageExportCallbacks#success', 'export_id' => export_id)

    batch.jobs do
      package_ids.each do |package_id|
        perform_async(export_id, package_id)
      end
    end
  end

  def perform(export_id, package_id)
    # do work
  end
end

class PackageExportCallbacks
  def success(_status, options)
    export = Export.find(options['export_id'])
    export.mark_completed!
  end
end

Multi-Step Workflow Pattern

class StartWorkflowWorker < ApplicationWorker
  sidekiq_options queue: :default

  def perform(record_id)
    batch.jobs do
      step_one = Sidekiq::Batch.new
      step_one.on(:success, 'WorkflowCallbacks#step_one_done', 'record_id' => record_id)
      step_one.jobs do
        FirstStepWorker.perform_async(record_id)
        SecondStepWorker.perform_async(record_id)
      end
    end
  end
end

class WorkflowCallbacks
  def step_one_done(status, options)
    parent = Sidekiq::Batch.new(status.parent_bid)
    parent.jobs do
      step_two = Sidekiq::Batch.new
      step_two.on(:success, 'WorkflowCallbacks#complete', options)
      step_two.jobs do
        FinalizeWorkflowWorker.perform_async(options['record_id'])
      end
    end
  end

  def complete(_status, options)
    # mark workflow complete
  end
end

Expiring Jobs

Use expiry when queued work becomes useless after some TTL.

class RefreshTemporaryCacheWorker < ApplicationWorker
  sidekiq_options queue: :default, expires_in: 30.minutes

  def perform(cache_key)
    # refresh cache entry
  end
end

For one-off enqueue behavior:

RefreshTemporaryCacheWorker.set(expires_in: 30.minutes).perform_async(cache_key)

Pro API Extensions

Sidekiq Pro extends the standard API after the gem is loaded. Examples:

queue = Sidekiq::Queue.new('critical')
queue.pause!
queue.unpause!
queue.delete_job(jid)
queue.delete_by_class(MyWorker)

Use these operations sparingly in admin or maintenance flows.

Pro Web UI

The app already mounts Sidekiq Web at /sidekiq behind admin_constraint in config/routes.rb. Because sidekiq/pro/web is required, that UI now includes Pro extensions such as:

  • batch pages
  • retry/dead/scheduled filtering
  • queue pause/unpause actions

Metrics

If we later want Pro Metrics, add a supported StatsD client and configure it in the Sidekiq initializer. For Sidekiq Pro 5.0.0, the gem supports both Sidekiq::Pro.statsd and Sidekiq::Pro.dogstatsd.