Sha256: 506ec7f83251d2c5e09e9fd545b482dacf2d20937f4de5185f8403084d39daf9

Contents?: true

Size: 1.39 KB

Versions: 1

Compression:

Stored size: 1.39 KB

Contents

module CaptainConfig::SidekiqMiddlewareFactory
  # Since Sidekiq calls `.new` on the middleware class for every job we cannot
  # store state in the instance between jobs like we would with a Rack
  # middleware. Therefore we need to build a new class to hold that state.
  #
  # interval: - Minimum time (in seconds) that must pass between reloading
  #             configuration.
  def self.build(interval: 1.0)
    klass = Class.new do
      include SidekiqMiddleware
    end
    klass.setup(interval: interval)
    klass
  end

  module SidekiqMiddleware
    def self.included(klass)
      klass.extend(ClassMethods)
    end

    module ClassMethods
      attr_reader :interval, :last_loaded_at

      def setup(interval:)
        @interval = interval
        @mutex = Mutex.new
        @last_loaded_at = Time.at(0)
      end

      def needs_load?
        (Time.now - @last_loaded_at) >= @interval
      end

      def load
        @mutex.synchronize do
          # The instances of the middleware on each thread call `#needs_load?`
          # unsynchronized, so they may think a reload is needed when it isn't.
          return unless needs_load?

          service = CaptainConfig::Service.last_created_service
          service&.load

          @last_loaded_at = Time.now
        end
      end
    end

    def call(_worker, _job, _queue)
      self.class.load if self.class.needs_load?

      yield
    end
  end
end

Version data entries

1 entries across 1 versions & 1 rubygems

Version Path
captain_config-1.1.0 lib/captain_config/middlewares/sidekiq_middleware_factory.rb