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.