lib/sidekiq/throttled.rb in sidekiq-throttled-0.8.0 vs lib/sidekiq/throttled.rb in sidekiq-throttled-0.8.1
- old
+ new
@@ -1,7 +1,10 @@
# frozen_string_literal: true
+# stdlib
+require "thread"
+
# 3rd party
require "sidekiq"
# internal
require "sidekiq/throttled/version"
@@ -38,10 +41,13 @@
# def perform
# # ...
# end
# end
module Throttled
+ MUTEX = Mutex.new
+ private_constant :MUTEX
+
class << self
# Hooks throttler into sidekiq.
#
# @return [void]
def setup!
@@ -66,16 +72,46 @@
def throttled?(message)
message = JSON.parse message
job = message.fetch("class") { return false }
jid = message.fetch("jid") { return false }
+ preload_constant! job
+
Registry.get job do |strategy|
return strategy.throttled?(jid, *message["args"])
end
false
rescue
false
+ end
+
+ private
+
+ # Tries to preload constant by it's name once.
+ #
+ # Somehow, sometimes, some classes are not eager loaded upon Rails init,
+ # leading to throttling config not being registered prior job perform.
+ # And that leaves us with concurrency limit + 1 situation upon Sidekiq
+ # server restart (becomes normal after all Sidekiq processes handled
+ # at leas onr job of that class).
+ #
+ # @return [void]
+ def preload_constant!(job)
+ MUTEX.synchronize do
+ @preloaded ||= {}
+ @preloaded[job] ||= constantize(job) || true
+ end
+ end
+
+ # Resolve constant from it's name
+ def constantize(str)
+ str.sub(/^::/, "").split("::").inject(Object) do |const, name|
+ const.const_get(name)
+ end
+ rescue
+ Sidekiq.logger.warn { "Failed to constantize: #{str}" }
+ nil
end
end
end
end