mhenrixon/sidekiq-unique-jobs

View on GitHub
bin/bench

Summary

Maintainability
Test Coverage
#!/usr/bin/env ruby
# frozen_string_literal: true

# Trap interrupts to quit cleanly. See
# https://twitter.com/mitchellh/status/283014103189053442
Signal.trap("INT") { abort }

require "bundler/setup"
require "benchmark/ips"

require "sidekiq-unique-jobs"

require_relative "../spec/support/workers/my_unique_job"
include SidekiqUniqueJobs::Script::Caller
Sidekiq.redis(&:flushall)

SidekiqUniqueJobs.configure do |config|
  config.logger.level = Logger.const_get("INFO")
  config.debug_lua    = false
  config.max_history  = 1_000
  config.reaper_count  = 1_000
end

COUNT   = 10_000
DIGESTS = COUNT.times.each_with_object({}) { |n, hash| hash[n] = "digest-#{n}" }
JOB_IDS = COUNT.times.each_with_object({}) { |n, hash| hash[n] = "jid-#{n}" }
QUEUES  = Array.new(100) { |n| "custom-#{n}" }

def get_item(num)
  { "class" => "MyUniqueJob",
    "args" => [num, num],
    "queue" => QUEUES.sample,
    "jid" => JOB_IDS[num],
    "lock_digest" => DIGESTS[num] }
end

Benchmark.ips do |ips|
  ips.config(time: 5, warmup: 2)

  ips.report("the whole shebang in ruby") do
    COUNT.times do |num|
      item = get_item(num)
      if (num % 111).zero?
        item["at"] = Time.now.to_f + (rand * num)
        Sidekiq::Client.push(item)
      elsif (num % 121).zero?
        failed_at = Time.now.to_f - rand(* num)
        item["retry_count"] = 2
        item["failed_at"] = failed_at
        Sidekiq.redis do |conn|
          conn.zadd(SidekiqUniqueJobs::RETRY,
                    SidekiqUniqueJobs.now_f + 360, Sidekiq.dump_json(item))
        end
      else
        Sidekiq::Client.push(item)
      end
    end

    9001.times do
      key = SecureRandom.hex(12)
      SidekiqUniqueJobs::Lock.create(key, key)
    end

    SidekiqUniqueJobs::DeleteOrphans.call
  end

  ips.report("the whole shebang in lua") do
    COUNT.times do |num|
      item = get_item(num)
      if (num % 111).zero?
        item["at"] = Time.now.to_f + (rand * num)
        Sidekiq::Client.push(item)
      elsif (num % 121).zero?
        failed_at = Time.now.to_f - rand(* num)
        item["retry_count"] = 2
        item["failed_at"] = failed_at
        Sidekiq.redis do |conn|
          conn.zadd(
            SidekiqUniqueJobs::RETRY, SidekiqUniqueJobs.now_f + 360, Sidekiq.dump_json(item)
          )
        end
      else
        Sidekiq::Client.push(item)
      end
    end

    9001.times do
      key = SecureRandom.hex(12)
      SidekiqUniqueJobs::Lock.create(key, key)
    end

    Sidekiq.redis do |conn|
      call_script(
        :reap_orphans,
        conn,
        keys: [SidekiqUniqueJobs::DIGESTS, SidekiqUniqueJobs::SCHEDULE, SidekiqUniqueJobs::RETRY],
        argv: [SidekiqUniqueJobs.config.reaper_count],
      )
    rescue => ex
      conn.script(:kill)
    end
  end
end