sidekiq_utils¶ ↑
Sidekiq powers our background processing needs at AngelList. As we introduced Sidekiq in a legacy codebase and it started to handle significant job throughput, we developed a number of utilities to make working with Sidekiq easier that we'd love to share.
Additional Serialization¶ ↑
Adds support for automatically serializing and deserializing additional argument types for your workers: * Class
* Symbol
(both by themselves and as hash keys) * ActiveSupport::HashWithIndifferentAccess
To use this utility, you need to include the client and server middlewares. Be sure to include the client middleware on the server as well.
Configuration¶ ↑
Sidekiq.configure_server do |config| config.server_middleware do |chain| chain.add ::SidekiqUtils::Middleware::Server::AdditionalSerialization end config.client_middleware do |chain| chain.add ::SidekiqUtils::Middleware::Client::AdditionalSerialization end end Sidekiq.configure_client do |config| config.client_middleware do |chain| chain.add ::SidekiqUtils::Middleware::Client::AdditionalSerialization end end
A note of caution for users of the sidekiq-unique-jobs gem¶ ↑
sidekiq-unique-jobs will fail to properly determine job uniqueness if you don't hook the middlewares in the correct order. If you use both sidekiq-unique-jobs and the additional serialization utility, be sure to hook your middlewares in the following way:
Sidekiq.configure_server do |config| # unwrap arguments first config.server_middleware do |chain| chain.add ::SidekiqUtils::Middleware::Server::AdditionalSerialization end # then determine unique jobs SidekiqUniqueJobs.configure_server_middleware # first determine uniqueness SidekiqUniqueJobs.configure_client_middleware # then wrap arguments config.client_middleware do |chain| chain.add ::SidekiqUtils::Middleware::Client::AdditionalSerialization end end Sidekiq.configure_client do |config| # first determine uniqueness SidekiqUniqueJobs.configure_client_middleware # then wrap arguments config.client_middleware do |chain| chain.add ::SidekiqUtils::Middleware::Client::AdditionalSerialization end end
Deprioritize¶ ↑
Adds an easy ability to divert jobs added within a block to a lower-priority queue. This is useful, for example, in cron jobs. All jobs added within the block will be added to the low
queue instead of their default queue.
Configuration¶ ↑
Sidekiq.configure_server do |config| config.client_middleware do |chain| chain.add SidekiqUtils::Middleware::Client::Deprioritize end end Sidekiq.configure_client do |config| config.client_middleware do |chain| client_middlewares.each do |middleware| chain.add SidekiqUtils::Middleware::Client::Deprioritize end end end
Usage¶ ↑
SidekiqUtils::Deprioritize.workers(SolrIndexWorker) do 10_000.times do # these will all go to the `low` queue SolrIndexWorker.perform_async(User, rand(10_000)) end end
Enqueued jobs helper¶ ↑
A simple tool to inspect and manipulate Sidekiq queues from the console:
> SidekiqUtils::EnqueuedJobsHelper.counts => {"default"=>{}, "high"=>{"AlgoliaIndexWorker[JobProfile]"=>1}, "low"=>{"AlgoliaIndexWorker[JobProfile]"=>1}} > SidekiqUtils::EnqueuedJobsHelper.delete(queue: 'low', job_class: 'AlgoliaIndexWorker', first_argument: JobProfile) # first_argument is optional
Find optional¶ ↑
Lots of jobs become moot when a record cannot be found; however, because Sidekiq is very fast and it's easy to forget to enqueue jobs in after_commit
hooks, sometimes the record isn't found simply because the transaction in which it was inserted has not been committed yet. This will retry a find_optional
call exactly once after 30 seconds if the record cannot be found.
Configuration¶ ↑
Sidekiq.configure_server do |config| config.server_middleware do |chain| chain.add SidekiqUtils::Middleware::Server::FindOptional end end
Usage¶ ↑
class SolrIndexWorker include Sidekiq::Worker def perform(user_id) user = find_optional(User, user_id) end end
Latency monitor¶ ↑
This will monitor queue latency and report to Slack channels if the latency exceeds the configured threshold.
Configuration¶ ↑
Create a config/sidekiq_utils.yml
file in your project:
repeat_alert_every: 60 # repeat identical alerts every x minutes alert_thresholds: # in minutes default: 10 high: 5 low: 60 slack: username: 'Sidekiq alerts' icon: 'alarm_clock' team: 'foobar' token: 'xxx' channels_to_alert: - "#devops-alerts" - "#sidekiq-alerts"
Usage¶ ↑
Simply call SidekiqUtils::LatencyAlert.check!
at regular intervals.
Throughput monitor¶ ↑
This will keep track of how many jobs of which worker class have run in the past week, as well as when it was last run.
Configuration¶ ↑
Sidekiq.configure_server do |config| config.server_middleware do |chain| chain.add SidekiqUtils::Middleware::Server::ThroughputMonitor end end Sidekiq::Web.register SidekiqUtils::WebExtensions::ThroughputMonitor Sidekiq::Web.tabs["Throughput"] = "throughput"
Usage¶ ↑
This will add a “Throughput” tab to your Sidekiq admin which will display job throughput information.