Created
July 25, 2018 16:48
-
-
Save holyketzer/9545c5f39523f8a6bca3fee5656a458e to your computer and use it in GitHub Desktop.
Sidekiq throttled queueing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class CreateResourceThrottles < ActiveRecord::Migration[5.1] | |
def change | |
create_table :resource_throttles do |t| | |
t.string :throttle_key, null: false | |
t.string :resource_uid, null: false | |
t.boolean :active, null: false, default: false | |
t.index [:throttle_key, :resource_uid], unique: true | |
t.timestamps | |
end | |
end | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# sidekiq-throttled gem controls only concurrent execution | |
# and allow to enqueue many jobs in queue which can cause queues growth | |
# This throttler doesn't allow to put job in queue if the same job already in queue or processing | |
module EnqueueThrottler | |
extend ActiveSupport::Concern | |
module ClassMethods | |
def perform_async(resource_uid, *args) | |
if ResourceThrottle.capture!(self.name, resource_uid) | |
super | |
end | |
end | |
end | |
def self.prepended(base) | |
class << base | |
prepend ClassMethods | |
end | |
end | |
def perform(resource_uid, *args) | |
super | |
ensure | |
ResourceThrottle.release!(self.class.name, resource_uid) | |
end | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class ResourceThrottle < ApplicationRecord | |
validates :throttle_key, presence: true | |
validates :resource_uid, presence: true | |
validates :resource_uid, uniqueness: { scope: :throttle_key } | |
class << self | |
def capture!(throttle_key, resource_uid) | |
throttle = self.find_or_create_by!(throttle_key: throttle_key, resource_uid: resource_uid) | |
if !throttle.active | |
throttle.update!(active: true) | |
true | |
end | |
end | |
def release!(throttle_key, resource_uid) | |
throttle = self.find_or_create_by!(throttle_key: throttle_key, resource_uid: resource_uid) | |
throttle.update!(active: false) | |
end | |
end | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class SampleWorker | |
include Sidekiq::Worker | |
include Sidekiq::Throttled::Worker | |
prepend EnqueueThrottler | |
sidekiq_options retry: false, queue: :low | |
# Allow maximum 1 concurrent job per project at a time. uses gem `sidekiq-throttled` | |
sidekiq_throttle concurrency: { | |
limit: 1, | |
key_suffix: ->(project_id) { project_id } | |
} | |
def perform(project_id) | |
# perform heavy job | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment