我正在尝试在常规速率运行的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
答案 0 :(得分:2)
语法是self.class.set(wait:30.seconds).perform_later。但这并不是一种可靠的方式,就好像链断裂发生异常一样。您还必须安排初始作业。 如果您使用resque,则可以使用https://rubygems.org/gems/activejob-scheduler
答案 1 :(得分: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功能而且它不会做任何事情。
答案 2 :(得分:0)
根据您使用的排队系统,您可以尝试https://github.com/codez/delayed_cron_job或https://github.com/ondrejbartas/sidekiq-cron。使用DJ cron,您可以使用像rails_admin这样的UI来实际编辑cron正则表达式。 Sidekiq-cron为您提供Sinatra Web UI,您可以手动启动作业或暂停作业。