Sidekiq extension that adds the ability to debounce job execution.
Worker will postpone its execution after wait time
have elapsed since the last time it was invoked.
Useful for implementing behavior that should only happen after the input has stopped arriving.
For example: sending one email with multiple notifications.
Add this line to your application's Gemfile:
gem 'sidekiq-debouncer'
And then execute:
$ bundle
Add middlewares to sidekiq:
Sidekiq.configure_client do |config|
config.client_middleware do |chain|
chain.add Sidekiq::Debouncer::Middleware::Client
end
end
Sidekiq.configure_server do |config|
config.client_middleware do |chain|
chain.add Sidekiq::Debouncer::Middleware::Client
end
config.server_middleware do |chain|
chain.add Sidekiq::Debouncer::Middleware::Server
end
end
Add debounce option to worker with by
and time
keys:
class MyWorker
include Sidekiq::Worker
sidekiq_options(
debounce: {
by: -> (args) { args[0] }, # debounce by first argument only
time: 5 * 60
}
)
def perform(group)
group.each do
# do some work with group
end
end
end
You can also pass symbol as debounce.by
matching class method.
class MyWorker
include Sidekiq::Worker
sidekiq_options(
debounce: {
time: 5 * 60,
by: :debounce_method
}
)
def self.debounce_method(job_args)
job_args[0]
end
def perform(group)
group.each do
# do some work with group
end
end
end
Keep in mind that the result of the debounce method will be converted to string, so make sure it doesn't return any objects that don't implement to_s
method.
In the application, call MyWorker.perform_async(...)
as usual. Everytime you call this function, MyWorker
's execution will be postponed by 5 minutes. After that time MyWorker
will receive a method call perform
with an array of arguments that were provided to the MyWorker.perform_async(...)
calls.
To avoid keeping leftover keys in redis, all additional keys are created with TTL. It's 24 hours by default and should be ok in most of the cases. If you are debouncing your jobs in higher interval than that, you can overwrite this setting:
Sidekiq.configure_client do |config|
config.client_middleware do |chain|
chain.add Sidekiq::Debouncer::Middleware::Client, ttl: 60 * 60 * 24 * 30 # 30 days
end
end
Add require 'sidekiq/debouncer/web'
after require 'sidekiq/web'
.
In order to test the behavior of sidekiq-debouncer
it is necessary to disable testing mode. It is the limitation of internal implementation.
Sidekiq::Debouncer will not debounce the jobs in testing mode, instead they'll be executed like normal jobs (pushed to fake queue or executed inline depending on settings).
Server middleware needs to be added to Sidekiq::Testing
chain:
Sidekiq::Testing.server_middleware do |chain|
chain.add Sidekiq::Debouncer::Middleware::Server
end
MIT Licensed. See LICENSE.txt for details.
This gem was renamed from sidekiq-debouce
due to name conflict on rubygems.