Skip to main content

Sidekiq-Cron Upgrade Guide (1.10.1 → 2.3.1)

This guide documents the upgrade of sidekiq-cron from version 1.10.1 to 2.3.1 in the Reports application.

Summary

On October 29, 2024, we upgraded sidekiq-cron from version 1.10.1 to 2.3.1. This major version upgrade brings several improvements and requires awareness of breaking changes, though our application code did not require modifications.

What Changed

Gem Versions Updated

GemOld VersionNew Version
sidekiq-cron1.10.12.3.1
sidekiq7.1.47.3.9
fugit1.11.11.12.1
et-orbi1.2.111.4.0
globalid1.2.11.3.0
redis-client0.17.00.26.1
connection_pool2.4.12.5.4
minitest5.25.55.26.0

New Dependency

  • cronex (0.15.0) - A new dependency added in sidekiq-cron 2.x for enhanced cron expression parsing

Breaking Changes

1. Minimum Sidekiq Version

Requirement: Sidekiq 6.5.0 or higher

Our application was already using Sidekiq 7.1.4, so this requirement was already met.

2. Minimum Redis Version

Requirement: Redis 4.0 or higher

Ensure your Redis server is at least version 4.0.

3. New Configuration Options

Sidekiq-cron 2.x introduces new configuration options that can be used in job definitions:

Retry Configuration

You can now specify retry behavior directly in your cron job definition:

Sidekiq::Cron::Job.new(
name: 'my_job',
cron: '0 * * * *',
class: 'MyJob',
retry: 5 # or false to disable retries
)

Namespace Support

Jobs can now be organized into namespaces:

Sidekiq::Cron::Job.new(
name: 'my_job',
cron: '0 * * * *',
class: 'MyJob',
namespace: 'default' # organize jobs by namespace
)

4. Enhanced Cron Expression Support

Sidekiq-cron 2.x uses fugit 1.11.1+ which provides improved natural language support for cron schedules. Our existing cron expressions continue to work without modification.

Impact on Our Application

Configuration Files

  • config/schedule.yml: No changes required. All existing cron job definitions work without modification.
  • config/initializers/sidekiq.rb: Schedule loading had to be reworked, see Schedule loading per environment.

Schedule loading per environment

In 1.x, cron_schedule_file in config/sidekiq.yml was enough to keep the gem from autoloading the schedule, which let the initializer load config/schedule.yml explicitly in production only.

In 2.x that key is no longer read from sidekiq.yml. The gem reads it from its own configuration object and loads the schedule from an :startup hook on the Sidekiq server, so the entry became dead configuration and the production schedule was registered on every environment running a Sidekiq server — staging and review apps included.

The gem is now the only thing that loads the schedule, gated by environment:

# config/initializers/sidekiq.rb
Sidekiq::Cron.configure { |config| config.enabled = Reports.production? }

Because cron jobs are persisted in Redis, disabling the load does not remove entries registered while the schedule was still loading everywhere: those keep firing until they are deleted. Clear them once per affected environment, from the Sidekiq Cron web UI at /jobs/cron or from a console:

Sidekiq::Cron::Job.all('*').select { |job| job.source == 'schedule' }.each(&:destroy)

Filter on source rather than using Sidekiq::Cron::Job.destroy_all!: jobs registered dynamically by EmailCampaign are dynamic and must survive.

Application Code

  • app/models/email_campaign.rb: No changes required. The _schedule and _unschedule methods continue to work as expected.

Tests

All existing tests pass without modification:

  • spec/models/email_campaign_spec.rb (37 examples, 0 failures)
  • spec/controllers/email_campaigns_controller_spec.rb

Verification Steps

To verify the upgrade was successful:

  1. Check gem version:

    bundle show sidekiq-cron
    # Should output: .../sidekiq-cron-2.3.1
  2. Run tests:

    bundle exec rspec spec/models/email_campaign_spec.rb
  3. Verify scheduled jobs load correctly:

    bundle exec rails console
    > Sidekiq::Cron::Job.all
  4. Check Sidekiq Web UI:

    • Navigate to /sidekiq/cron in your application
    • Verify all scheduled jobs are listed and active

Migration Checklist

  • Verify Sidekiq version >= 6.5.0 (We had 7.1.4)
  • Update Gemfile to specify sidekiq-cron ~> 2.3
  • Run bundle update sidekiq-cron
  • Review cron job definitions (No changes needed)
  • Run test suite (All tests pass)
  • Verify jobs load in console (Confirmed)
  • Document breaking changes (This guide)

Recommendations for Future Jobs

When creating new cron jobs, consider using the new features:

  1. Explicit Retry Configuration: Set the retry option to control retry behavior:

    job = Sidekiq::Cron::Job.new(
    name: 'my_job',
    cron: '0 * * * *',
    class: 'MyJob',
    active_job: true,
    retry: 3 # Retry up to 3 times on failure
    )
  2. Namespaces for Organization: Use namespaces to group related jobs:

    job = Sidekiq::Cron::Job.new(
    name: 'import_job',
    cron: '0 * * * *',
    class: 'ImportJob',
    active_job: true,
    namespace: 'imports' # Group import-related jobs
    )

Resources

Support

If you encounter issues related to scheduled jobs after this upgrade, check:

  1. Redis server logs for connection issues
  2. Sidekiq logs for job execution errors
  3. Sidekiq Web UI (/sidekiq/cron) for job status
  4. Rails logs for application-specific errors

Rollback Procedure

If you need to rollback to the previous version:

  1. Update Gemfile to use the old version:

    gem 'sidekiq-cron', '~> 1.10'
  2. Run bundle update:

    bundle update sidekiq-cron
  3. Restart the application and Sidekiq workers

Note: Rolling back is not recommended as version 2.x is actively maintained and includes security updates.