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