Class: Sidekiq::LimitFetch::Global::Selector

Inherits:
Object
  • Object
show all
Defined in:
lib/sidekiq/limit_fetch/global/selector.rb

Overview

Executes the limit_fetch Lua script against Redis to atomically check concurrency limits and pop jobs from queues.

Constant Summary collapse

ATTRS =

Attributes to send to the Lua script.

%w[process_limit limit busy].freeze

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(capsule) ⇒ Selector

Returns a new instance of Selector.

Parameters:

  • capsule (Sidekiq::Capsule)


16
17
18
# File 'lib/sidekiq/limit_fetch/global/selector.rb', line 16

def initialize(capsule)
  @capsule = capsule
end

Instance Attribute Details

#capsuleObject (readonly)

Returns the value of attribute capsule.



13
14
15
# File 'lib/sidekiq/limit_fetch/global/selector.rb', line 13

def capsule
  @capsule
end

Class Method Details

.redis_scriptString

Returns:

  • (String)


52
53
54
# File 'lib/sidekiq/limit_fetch/global/selector.rb', line 52

def self.redis_script
  @redis_script ||= File.read("#{__dir__}/limit_fetch.lua").freeze
end

.redis_script_shaString

Returns:

  • (String)


47
48
49
# File 'lib/sidekiq/limit_fetch/global/selector.rb', line 47

def self.redis_script_sha
  @redis_script_sha ||= OpenSSL::Digest::SHA1.hexdigest(redis_script).freeze
end

Instance Method Details

#limit_fetch(queue_rnames) ⇒ String?

Returns Sidekiq job string (if job is found).

Parameters:

  • queue_rnames (Array<String>)

    queue names in Redis (ex: ‘queue:email’, ‘queue:payments’, etc.)

Returns:

  • (String, nil)

    Sidekiq job string (if job is found)



23
24
25
26
27
28
29
30
31
# File 'lib/sidekiq/limit_fetch/global/selector.rb', line 23

def limit_fetch(queue_rnames)
  keys = queue_rnames.each_with_object([]) do |queue, result|
    result << queue
    ATTRS.each { |attr| result << "sidekiq:limit_fetch:#{queue}:#{attr}" }
  end

  capsule_uuid = Global.capsule[capsule.name].uuid
  redis_eval(keys.size, *keys, capsule_uuid)
end

#redis_evalObject

Run the ‘limit_fetch.lua` script.



34
35
36
37
38
39
40
41
42
43
44
# File 'lib/sidekiq/limit_fetch/global/selector.rb', line 34

def redis_eval(...)
  capsule.redis do |redis|
    sha = self.class.redis_script_sha
    redis.call("EVALSHA", sha, ...)
  rescue RedisClient::CommandError => e
    raise unless e.message.include?("NOSCRIPT")

    script = self.class.redis_script
    redis.call("EVAL", script, ...)
  end
end