The project is in a healthy, maintained state
A mechanism to mark Sidekiq Jobs to be disposed of by Job ID, Batch ID, or Job Class. Disposal here means to either `:kill` the Job (send to the Dead queue) or `:discard` it (throw it away), at the time the job is picked up and processed by Sidekiq.
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
 Dependencies

Runtime

~> 7.0
 Project Readme

Sidekiq::Disposal

Gem Version CI

A Sidekiq extension to mark Sidekiq Jobs to be disposed of based on the Job ID, Batch ID, or Job Class. Disposal here means to either :kill the Job (send to the Dead queue) or :discard it (throw it away), at the time the job is picked up and processed by Sidekiq. A disposed Job's #perform method will not be called.

Disposing of queued Jobs is particularly useful as a mitigation technique during an incident. For example, an issue with a 3rd party API that causes Jobs of a certain Class to take longer than expected/normal to run. Or a code change/edge case that unexpectedly fans out more than expected, enqueuing a large volume of Jobs which then drown out other Jobs. Or… any number of other ways that some Job, Batch, or Job Class has been enqueued, but you don't want it to actually run.

sidekiq-disposal has your back!

Installation

Install the gem and add to the application's Gemfile by executing:

bundle add sidekiq-disposal

If bundler is not being used to manage dependencies, install the gem by executing:

gem install sidekiq-disposal

Usage

From a console (Rails console, or the like) you need a Sidekiq::Disposal::Client instance, which is used to #mark a Job, Batch, or Job Class to be disposed.

client = Sidekiq::Disposal::Client.new

Marking to Kill

A Job marked to be killed means it will be moved to the Dead queue.

# Mark a specific Job to be killed by specifying its Job ID
client.mark(:kill, :jid, some_job_id)

# Mark a Batch of Jobs to be killed, by Batch ID
client.mark(:kill, :bid, some_batch_id)

# Mark an entire Job Class to be killed
client.mark(:kill, :bid, "SomeJobClass")

A Job, Batch, or Job Class can also be #unmarked for disposal via a corresponding API.

# Un-mark a specific Job from being killed, by Job ID
client.unmark(:kill, :jid, some_job_id)

# Un-mark a Batch of Jobs from being killed, by Batch ID
client.unmark(:kill, :bid, some_batch_id)

# Un-mark an entire Job Class from being killed
client.unmark(:kill, :bid, "SomeJobClass")

Marking to Discard

Similarly, a Job, Batch, or Job Class can be marked to be discarded. Discarded jobs are thrown away by Sidekiq - think of them as simply being deleted from the queue, without ever being run.

# Mark a specific Job to be discarded by specifying its Job ID
client.mark(:discard, :jid, some_job_id)

# Mark a Batch of Jobs to be discarded, by Batch ID
client.mark(:discard, :bid, some_batch_id)

# Mark an entire Job Class to be discarded
client.mark(:discard, :bid, "SomeJobClass")

And again, there is a corresponding API for un-marking a Job, Batch, or Job Class from being discarded.

# Un-mark a specific Job from being discarded, by Job ID
client.unmark(:discard, :jid, some_job_id)

# Un-mark a Batch of Jobs from being discarded, by Batch ID
client.unmark(:discard, :bid, some_batch_id)

# Un-mark an entire Job Class from being discarded
client.unmark(:discard, :bid, "SomeJobClass")

Un-marking All

Clearing all :kill or :discard marks can be done in one fell swoop as well.

client.unmark_all(:kill)

# or …

client.unmark_all(:discard)

Configuration

With sidekiq-disposal installed, register its Sidekiq server middleware. Typically this is done via config/initializers/sidekiq.rb in a Rails app.

Sidekiq.configure_server do |config|
  config.server_middleware do |chain|
    chain.add Sidekiq::Disposal::ServerMiddleware
  end
end

This piece of middleware checks each job, after it's been dequeued, but before its #perform has been called, to see if it should be disposed of. If the job is marked for disposal (by Job ID, Batch ID, or Job Class), a corresponding error is raised by the middleware.

A Job marked :kill will raise a Sidekiq::Disposal::JobKilled error, while one marked :discard will raise Sidekiq::Disposal::JobDiscarded. Out of the box, these errors will cause Sidekiq's error handling and retry mechanism to kick in, re-enqueueing the Job. And round-and-round it will go until the default error/death handling kicks in.

To avoid this, you need to handle those specific Sidekiq::Disposal errors accordingly.

Adjust the base Sidekiq Job class, often called ApplicationJob or similar, so the sidekiq_retry_in uses a block similar to this:

sidekiq_retry_in do |_count, exception, jobhash|
  case exception
  when Sidekiq::Disposal::JobKilled
    # Optionally log/collect telemetry here too…
    :kill
  when Sidekiq::Disposal::JobDiscarded
    # Optionally log/collect telemetry here too…
    :discard
  end
end

NOTE: If is not a base job, consider adding one, or you'll need to add this to every job you want to be disposable.

Returning :kill from this method will cause Sidekiq to immediately move the Job to the Dead Queue. Similarly, returning :discard will cause Sidekiq to discard the job on the floor. Either way, the Job's #perform is never called.

Non-Disposable Jobs

By default all Jobs are disposable, meaning they can be marked to be :kill-ed or :discard-ed. However, checking if a specific Job should be disposed of is not free; it requires round trip(s) to Redis. Therefore, you might want to make some Jobs non-disposable to avoid these extra round trips. Or because there are some Jobs that simply should never be disposed of for… reasons.

This is done via a Job's sidekiq_options.

sidekiq_options disposable: false

With that in place, the server middleware will ignore the Job, and pass it down the middleware Chain. No extra Redis calls, no funny business.

Development

After checking out the repo, run bin/setup to install dependencies. Then, run bin/rspec to run the tests. You can also run bin/console for an interactive prompt that will allow you to experiment.

To install this gem onto your local machine, run bin/rake install. To release a new version, update the version number in version.rb, and then run bin/rake release, which will create a git tag for the version, push git commits and the created tag, and push the .gem file to rubygems.org.

Contributing

Bug reports and pull requests are welcome on GitHub at https://github.com/hibachrach/sidekiq-disposal.

License

The gem is available as open source under the terms of the MIT License.