# encoding: utf-8

module HireFire
  module Macro
    module Resque
      extend self

      # Counts the amount of jobs in the (provided) Resque queue(s).
      #
      # @example Resque Macro Usage
      #   HireFire::Macro::Resque.queue # all queues
      #   HireFire::Macro::Resque.queue("email") # only email queue
      #   HireFire::Macro::Resque.queue("audio", "video") # audio and video queues
      #
      # @param [Array] queues provide one or more queue names, or none for "all".
      # @return [Integer] the number of jobs in the queue(s).
      #
      def queue(*queues)
        queues = queues.flatten.map(&:to_s)
        queues = ::Resque.queues if queues.empty?

        in_queues = queues.inject(0) do |memo, queue|
          memo += ::Resque.size(queue)
          memo
        end

        in_progress = ::Resque::Worker.all.inject(0) do |memo, worker|
          memo += 1 if queues.include?(worker.job["queue"])
          memo
        end

        in_queues + in_progress
      end
    end
  end
end


# encoding: utf-8

module HireFire
  module Macro
    module Resque
      extend self

      # Counts the amount of jobs in the (provided) Resque queue(s).
      #
      # @example Resque Macro Usage
      #   HireFire::Macro::Resque.queue # all queues
      #   HireFire::Macro::Resque.queue("email") # only email queue
      #   HireFire::Macro::Resque.queue("audio", "video") # audio and video queues
      #
      # @param [Array] queues provide one or more queue names, or none for "all".
      # @return [Integer] the number of jobs in the queue(s).
      #
      def queue(*queues)
        queues = queues.flatten.map(&:to_s)
        queues = ::Resque.queues if queues.empty?

        redis = ::Resque.redis
        decoder = ::Resque::Worker.new(:noop)

        ids = Array(redis.smembers(:workers)).compact
        raw_jobs = redis.pipelined { ids.map { |id| redis.get("worker:#{id}") } }
        jobs = raw_jobs.map { |raw_job| decoder.decode(raw_job) || {} }

        in_queues = redis.pipelined do
          queues.map { |queue| redis.llen("queue:#{queue}") }
        end.map(&:to_i).inject(&:+)

        in_progress = jobs.inject(0) do |memo, job|
          memo += 1 if queues.include?(job["queue"])
          memo
        end

        in_queues + in_progress
      end
    end
  end
end

Access Resque data through Redis directly so that we can pipeline network operations. This makes network-bound operations scalable, and they will no longer suffer from the n+1 issue.
Access Resque data through Redis directly so that we can pipeline network operations. This makes network-bound operations scalable, and they will no longer suffer from the n+1 issue.