resque-status和resque-scheduler用于延迟作业

时间:2013-08-09 04:06:13

标签: ruby-on-rails resque

我在之前的代码中使用resque-scheduler进行延迟作业:

Resque.enqueue_in(options[:delay].seconds, self, context)

现在我想要包含resque-status来完成这项工作,但不知道它们如何协同工作。最新的resque-status源代码支持调度程序,如源代码所示:

https://github.com/quirkey/resque-status/blob/master/lib/resque/plugins/status.rb

# Wrapper API to forward a Resque::Job creation API call into a Resque::Plugins::Status call.
# This is needed to be used with resque scheduler
# http://github.com/bvandenbos/resque-scheduler
def scheduled(queue, klass, *args)
  self.enqueue_to(queue, self, *args)
end

但我不确定如何使用它。我应该调用SampleJob.scheduled(queue,myclass,:delay => delay)而不是SampleJob.create(options)吗?

=============================================== =======================

此外,还支持resque-status(以及其他自定义作业):

https://github.com/bvandenbos/resque-scheduler

某些像resque-status这样的Resque扩展使用具有略微不同的API签名的自定义作业类。 Resque-scheduler不会尝试支持所有现有和未来的自定义作业类,而是支持计划标记,因此您可以扩展自定义类并使其支持计划作业。

让我们假装我们有一个名为FakeLeaderboard的JobWithStatus类

class FakeLeaderboard < Resque::JobWithStatus
  def perform
    # do something and keep track of the status
  end
end

然后是时间表:

create_fake_leaderboards:
  cron: "30 6 * * 1"
  queue: scoring
  custom_job_class: FakeLeaderboard
  args:
  rails_env: demo
  description: "This job will auto-create leaderboards for our online demo and the status will update as the worker makes progress"

但似乎只适用于经常性工作。我可以找到cron的参数,但不能延迟。那么如何处理延迟的工作?

谢谢!

2 个答案:

答案 0 :(得分:0)

我遇到了同样的问题,我通过实施一个为“统计”工作提供跑步者的模块自行解决。

module Resque # :nodoc:

  # Module to include in your worker class to get resque-status
  # and resque-scheduler integration
  module ScheduledJobWithStatus

    extend ActiveSupport::Concern

    included do
      # Include status functionalities
      include Resque::Plugins::Status
    end

    # :nodoc:
    module ClassMethods

      # This method will use a custom worker class to enqueue jobs
      # with resque-scheduler plugin with status support
      def enqueue_at(timestamp, *args)
        class_name = self.to_s # store class name since plain class object are not "serializable"
        Resque.enqueue_at(timestamp, JobWithStatusRunner, class_name, *args)
      end

      # Identical to enqueue_at but takes number_of_seconds_from_now
      # instead of a timestamp.
      def enqueue_in(number_of_seconds_from_now, *args)
        enqueue_at(Time.now + number_of_seconds_from_now, *args)
      end

    end
  end

  # Wrapper worker for enqueuing
  class JobWithStatusRunner
    # default queue for scheduling jobs with status
    @queue = :delayed

    # Receive jobs from {Resque::ScheduledJobWithStatus} queue them in Resque
    # with support for status informations
    def self.perform(status_klass, *args)
      # Retrieve original worker class
      klass = status_klass.to_s.constantize
      # Check if supports status jobs
      unless klass.included_modules.include? Resque::Plugins::Status
        Rails.logger.warn("Class #{klass} doesn't support jobs with status")
        return false
      end
      Rails.logger.debug("Enqueing jobs #{klass} with arguments #{args}")
      klass.create(*args)
    rescue NameError
      Rails.logger.error("Unable to enqueue jobs for class #{status_klass} with args #{args}")
      false
    end
  end

end

通过这种方式,您可以使用以下简单语法将作业排入队列:

# simple worker class
class SleepJob

  # This provides integrations with both resque-status and resque-scheduler
  include Resque::ScheduledJobWithStatus

  # Method triggered by resque
  def perform
    total = (options['length'] || 60).to_i
    1.upto(total) { |i| at(i, total, "At #{i} of #{total}"); sleep(1) }
  end

end

# run the job delayed
SleepJob.enqueue_in(5.minutes)
# or
SleepJob.enqueue_at(5.minutes.from_now)

只需将模块放入resque初始化程序或lib文件夹中即可。在后一种情况下,请记住在某处需要它。

答案 1 :(得分:0)

resque-scheduler只要为您的工作人员创建作业消耗,就会在提供的类上调用scheduled方法。 它还很好地将队列名称和类名称作为字符串传递,因此您可以创建一个类级别方法来处理预定的作业创建。

虽然Fabio的答案将解决问题,但回答您的具体问题有点过于设计。 假设您拥有JobWithStatus所有resque-status工作人员继承的课程,则只需添加scheduled方法即可使其与resque-scheduler一起使用,如下所示:

class JobWithStatus
  include Resque::Plugins::Status

  def self.scheduled(queue, klass, *args)
    Resque.constantize(klass).create(*args)
  end
end