从Rails API,我发现ActiveJob可以retry_job间隔:
my_job_instance.enqueue
my_job_instance.enqueue wait: 5.minutes
my_job_instance.enqueue queue: :important
my_job_instance.enqueue wait_until: Date.tomorrow.midnight
但如果我想设置重试次数,例如Sidekiq'
include Sidekiq::Worker
sidekiq_options :retry => 5
如何在此示例代码中执行此操作?
class SiteScrapperJob < ActiveJob::Base
rescue_from(ErrorLoadingSite) do
retry_job queue: :low_priority
end
def perform(*args)
# raise ErrorLoadingSite if cannot scrape
end
end
现在我把它添加到我的工作班:
Sidekiq.default_worker_options = { retry: 5 }
但似乎不太好。
答案 0 :(得分:16)
您也可能对使用serialize
和deserialize
api存储尝试次数的此解决方案感兴趣。
class DeliverWebhookJob < ActiveJob::Base
def serialize
super.merge('attempt_number' => (@attempt_number || 0) + 1)
end
def deserialize(job_data)
super
@attempt_number = job_data['attempt_number']
end
rescue_from(ErrorLoadingSite) do |exception|
retry_job(wait: 10) if @attempt_number < 5
end
def perform(*args)
# raise ErrorLoadingSite if cannot scrape
end
end
从here获取。
答案 1 :(得分:11)
你做不到。如果您想使用Sidekiq特定的东西,您需要使用Sidekiq特定的API。 ActiveJob不会暴露Sidekiq的重试机制。
答案 2 :(得分:10)
从Rails 5.1开始,有一种使用retry_on方法执行此操作的内置方法。它是一个通用的ActiveJob方法,因此它适用于任何排队后端,而不仅仅是Sidekiq。
例如,您可以执行以下任务:
class SiteScraperJob < ActiveJob::Base
retry_on ErrorLoadingSite, queue: :low_priority, attempts: 5
def perform(*args)
# raise ErrorLoadingSite if cannot scrape
end
end
您还可以设置常量等待间隔或指数等待策略,如docs中所述。
答案 3 :(得分:2)
请参阅here Sidekiq的默认值。属性retry
“接受”布尔值,而不是您所假设的数字。
从active_job合并到Rails,other file可以看到retry
再次接受重试次数。
documentation says那么,如果作业重试,您可以定义每个作业。
我还尝试查找config/sidekiq.yml
文件是否可以接收此号码,而且似乎不能。
最后,
如果你没有在25次重试(大约21天)内修复错误,Sidekiq将停止重试并将你的工作转移到Dead Job Queue。您可以使用Web UI在接下来的6个月内随时手动修复错误并手动重试作业。
答案 4 :(得分:2)
有一个sidekiq-retry宝石来完成工作
class SiteScrapperJob < ActiveJob::Base
include ActiveJob::Retry.new(limit: 5, strategy: :exponential)
def perform(*args)
# raise ErrorLoadingSite if cannot scrape
end
end
另一种选择是使用sidekiq middleware:
首先定义job_options类方法,该方法将在子类中使用:
class ApplicationJob < ActiveJob::Base
def self.job_options(options)
@job_options = options
end
def self.get_job_options
@job_options || {}
end
end
添加从作业类中读取job_options的中间件,并将它们写入sidekiq的作业项目:
module Sidekiq
class JobOptionsMiddleware
def call(job_wrapper, item, queue, redis_pool)
job = item['args'][0]['job_class'].constantize
job.get_job_options
.each{ |option, value| item[option] = value if item[option].nil? }
yield
end
end
# in sidekiq initializer
Sidekiq.configure_client do |config|
config.client_middleware do |chain|
chain.add Sidekiq::JobOptionsMiddleware
end
end
最后
class SiteScrapperJob < ApplicationJob
job_options retry: 5
def perform
# your code
end
end
答案 5 :(得分:1)
仅供参考,此问题已在Sidekiq 6.0发行版中得到修复。您可以在此处查看更改日志:https://github.com/mperham/sidekiq/blob/master/Changes.md
但是基本上,您可以通过使用选项哈希调用sidekiq_options
来传递相同的选项。谢谢Mike Perham。
答案 6 :(得分:-1)
如果你只是使用sidekiq,nerver改变后端,猴子补丁可以帮助你
module ActiveJob
module QueueAdapters
class SidekiqAdapter
def enqueue(job)
JobWrapper.sidekiq_options job.sidekiq_options_hash if job.sidekiq_options_hash
JobWrapper.sidekiq_retry_in job.sidekiq_retry_in_block if job.sidekiq_retry_in_block
Sidekiq::Client.push(
'class' => JobWrapper,
'wrapped' => job.class.to_s,
'queue' => job.queue_name,
'args' => [ job.serialize ]
)
end
def enqueue_at(job, timestamp)
JobWrapper.sidekiq_options job.sidekiq_options_hash if job.sidekiq_options_hash
JobWrapper.sidekiq_retry_in job.sidekiq_retry_in_block if job.sidekiq_retry_in_block
Sidekiq::Client.push(
'class' => JobWrapper,
'wrapped' => job.class.to_s,
'queue' => job.queue_name,
'args' => [ job.serialize ],
'at' => timestamp
)
end
end
end
class Base
class_attribute :sidekiq_options_hash
class_attribute :sidekiq_retry_in_block
def self.sidekiq_options(opts={})
self.sidekiq_options_hash = opts
end
def self.sidekiq_retry_in(&block)
self.sidekiq_retry_in_block = block
end
end
end
然后,您可以写如下:
class BaseJob < ActiveJob::Base
sidekiq_options retry: 2, queue: :low
sidekiq_retry_in { |count, _| 3 * count }
def perform; end
end
快乐编码