Skip to content

venturehacks/sidekiq_utils

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

39 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

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.

About

Tools that make working with a major Sidekiq installation more fun.

Resources

License

Stars

Watchers

Forks

Packages

No packages published