2

我正在尝试在 rails 4.2 中创建一个以常规速率运行的 ActiveJob。第一次调用该作业,但它不会再次开始。我的代码在尝试调用 perform_later 后抛出了下面的异常。

日志输出

[ActiveJob] Enqueued ProcessInboxJob (Job ID: 76a63689-e330-47a1-af92-8e4838b508ae) to Inline(default)
[ActiveJob] [ProcessInboxJob] [76a63689-e330-47a1-af92-8e4838b508ae] Performing ProcessInboxJob from Inline(default)
ProcessInboxJob running...
[ActiveJob] [ProcessInboxJob] [76a63689-e330-47a1-af92-8e4838b508ae] [AWS S3 200 0.358441 0 retries] list_objects(:bucket_name=>"...",:max_keys=>1000)  

[ActiveJob] [ProcessInboxJob] [76a63689-e330-47a1-af92-8e4838b508ae] Enqueued ProcessInboxJob (Job ID: dfd3dd7a-06ab-4dba-9bbf-ce1ad606f7e5) to Inline(default) with arguments: {:wait=>30 seconds}
[ActiveJob] [ProcessInboxJob] [76a63689-e330-47a1-af92-8e4838b508ae] Performed ProcessInboxJob from Inline(default) in 599.72ms
Exiting
/Users/antarrbyrd/.rbenv/versions/2.1.2/lib/ruby/gems/2.1.0/gems/activejob-4.2.0/lib/active_job/arguments.rb:60:in `serialize_argument': Unsupported argument type: ActiveSupport::Duration (ActiveJob::SerializationError)

process_inbox_job.rb

class ProcessInboxJob < ActiveJob::Base
  queue_as :default
  #FREQUENCY = 3.minutes
  def perform()
    # do some work
  end
  # reschedule job
  after_perform do |job|
    self.class.perform_later(wait: 30.seconds)
  end
end
4

3 回答 3

2

语法是 self.class.set(wait: 30.seconds).perform_later。但这不是一种可靠的方法,就好像发生异常链中断一样。此外,您必须安排初始作业。如果你使用 resque,你可以使用https://rubygems.org/gems/activejob-scheduler

于 2015-01-13T17:13:08.090 回答
2

正如@bcd 所说,您必须使用self.class.set(wait: 30.seconds).perform_later支持排队的队列适配器,即不是默认(内联)适配器。

我发帖是为了对重新安排的问题提出不同的看法,这可能会对未来的读者有所帮助。

after_perform如果引发异常,将不会被调用,但这并不会使它成为重新安排工作的坏地方。如果您在工作中遇到异常,最好挽救它(使用类方法rescue_from),如果您的后端还没有这样做,则向自己发送通知。

然后,您可以尝试解决问题(在数据中或在您的代码中)并重试(如果可以)或再次将类似的作业排入队列。

对于调度部分,activejob-scheduler 很棒,它不仅适用于 resque,而且有一些缺点。

它使用 rufus-scheduler,它执行内存延迟,因此每当您的服务器重新启动时,您将丢失所有调度信息,这对于某些任务可能确实是一个问题(我在未来 1 个月安排任务并每周更新我的应用程序,这意味着每次都重新启动)。

您还将失去使用实际排队后端的所有优势,例如带有 backburner 的 beanstalk。

ActiveJob-scheduler 还声称在正确的时间执行作业,这是错误的。ActiveJob 适配器在指定时间运行,但根据您的设置,实际执行作业可能需要一些时间,例如,当您在另一台服务器上运行作业时。

最后,对于初始调度,您可以包含一个代码,用于检查工作是否在工作人员启动时存在,并在需要时进行调度。

总结一下,

是的,ActiveJob-Scheduler 很棒,但是你会失去一些 ActiveJob 功能,而且它并不能做所有事情。

于 2015-04-20T14:33:53.747 回答
0

根据您使用的排队系统,您可以尝试https://github.com/codez/delayed_cron_jobhttps://github.com/ondrejbartas/sidekiq-cron。使用 DJ cron,您可以使用类似 rails_admin 的 UI 来实际编辑 cron 正则表达式。Sidekiq-cron 为您提供 Sinatra Web UI,您可以在其中手动启动或暂停作业。

于 2016-01-27T04:22:56.223 回答