【问题标题】:create recurring activejob fails创建重复活动作业失败
【发布时间】:2015-03-11 16:30:09
【问题描述】:

我正在尝试在 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

【问题讨论】:

  • 你确定要在拨打.perform_later之后再拨打.perform吗?
  • @ptd 非常喜欢查看 gem 的文档。删除它也不会改变结果

标签: ruby-on-rails ruby rails-activejob


【解决方案1】:

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

【讨论】:

    【解决方案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 功能,而且它并不能做所有事情。

    【讨论】:

      【解决方案3】:

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

      【讨论】:

      • 使用self.class.set 会引发未实现的错误active_job/queue_adapters/inline_adapter.rb:18:in enqueue_at':将来使用排队后端对作业进行排队。阅读更多guides.rubyonrails.org/v4.2.0/active_job_basics.html (NotImplementedError)`
      • 您需要使用不同的适配器,因为内联适配器不支持安排稍后执行的作业
      猜你喜欢
      • 1970-01-01
      • 2023-03-26
      • 1970-01-01
      • 2019-10-21
      • 2018-01-21
      • 1970-01-01
      • 1970-01-01
      • 2019-07-13
      • 1970-01-01
      相关资源
      最近更新 更多