使用 ActiveJob 禁用自动重试,与 Sidekiq 一起使用
Disable automatic retry with ActiveJob, used with Sidekiq
有没有办法禁用 ActiveJob 和 Sidekiq 的自动重试?
我知道只有 Sidekiq,我们只需要输入
sidekiq_options :retry => false
如此处所述:https://github.com/mperham/sidekiq/wiki/Error-Handling#configuration
但它似乎不适用于 ActiveJob 和 Sidekiq。
我也知道这里建议的完全禁用重试的解决方案:
但这不是我需要的行为。
无法使用 ActiveJob 配置有关 Sidekiq 的任何内容。如果您不想使用默认值,请使用 Sidekiq Worker。
好的,谢谢你的回答。
仅供参考,我还在 ActiveJob Github 存储库中与此主题相关的问题中提出了问题:https://github.com/rails/activejob/issues/47
DHH 回答了我一个我没有测试过但可以完成工作的解决方案。
就个人而言,我最终将其放入初始化程序中以全局禁用 Sidekiq 重试并且效果很好:
Sidekiq.configure_server do |config|
config.server_middleware do |chain|
chain.add Sidekiq::Middleware::Server::RetryJobs, :max_retries => 0
end
end
我有同样的需求,即 ActiveJob 包装 Sidekiq 但想支持 max_retries。我把它放在初始化程序中。如果在 ActiveJob 作业上定义了#max_retries,它将用于设置重试。如果#ephemeral?已定义且 returns 为真,作业将不会重新运行,如果失败也不会转移到 'dead'。
class Foobar::SidekiqClientMiddleware
def call(worker_class, msg, queue, redis_pool)
aj_job = ActiveJob::Base.deserialize(msg['args'][0]) rescue nil
msg['retry'] = aj_job.respond_to?(:max_retries) ? aj_job.max_retries : 5
msg['retry'] = false if aj_job.respond_to?(:ephemeral?) && aj_job.ephemeral?
yield
end
end
Sidekiq.configure_client do |config|
config.redis = { url: "redis://#{redis_host}:6379/12" }
config.client_middleware do |chain|
chain.add Foobar::SidekiqClientMiddleware
end
end
Sidekiq.configure_server do |config|
config.redis = { url: "redis://#{redis_host}:6379/12" }
config.client_middleware do |chain|
chain.add Foobar::SidekiqClientMiddleware
end
end
注意:如果您的任何作业在执行时自行创建新作业,那么将其添加到客户端和服务器的中间件链实际上很重要。
您可以捕获异常而不做任何事情,而是重试或配置重试:
class ExampleJob < ActiveJob::Base
rescue_from(StandardError) do |exception|
Rails.logger.error "[#{self.class.name}] Hey, something was wrong with you job #{exception.to_s}"
end
def perform
raise StandardError, "error_message"
end
end
class ExampleJob < ActiveJob::Base
rescue_from(StandardError) do |exception|
retry_job wait: 5.minutes, queue: :low_priority
end
def perform
raise StandardError, "error_message"
end
end
对于 运行 重试,您可以使用 retry_on 方法 retry_on method doc
从 sidekiq 6.0.1
开始,可以将以下内容传递给 ActiveJob worker 以防止其重试:
class ExampleJob < ActiveJob::Base
sidekiq_options retry: false
def perform(*args)
# Perform Job
end
end
更多信息:https://github.com/mperham/sidekiq/wiki/Active-Job#customizing-error-handling
编辑:
根据 this 这需要 Rails 6.0.1
或更高版本。
如果你想为来自 gems 的 ActiveJob
(比如 ActionMailbox::RoutingJob
)禁用重试(或添加任何其他 Sidekiq 选项),你可以使用这种方法(Rails 6.0. 2+).
1) 使用所需的 Sidekiq 选项创建一个模块(使用 ActiveSupport::Concern
)
# lib/fixes/action_mailbox_routing_job_sidekiq_fix.rb
module ActionMailboxRoutingJobSidekiqFix
extend ActiveSupport::Concern
included do
sidekiq_options retry: false
end
end
2) 将其包含在作业 class 的初始化程序中。
# config/initializers/extensions.rb
require Rails.root.join('lib', 'fixes', 'action_mailbox_routing_job_sidekiq_fix')
Rails.configuration.to_prepare do
ActionMailbox::RoutingJob.include ::ActionMailboxRoutingJobSidekiqFix
end
有没有办法禁用 ActiveJob 和 Sidekiq 的自动重试?
我知道只有 Sidekiq,我们只需要输入
sidekiq_options :retry => false
如此处所述:https://github.com/mperham/sidekiq/wiki/Error-Handling#configuration
但它似乎不适用于 ActiveJob 和 Sidekiq。
我也知道这里建议的完全禁用重试的解决方案:
但这不是我需要的行为。
无法使用 ActiveJob 配置有关 Sidekiq 的任何内容。如果您不想使用默认值,请使用 Sidekiq Worker。
好的,谢谢你的回答。
仅供参考,我还在 ActiveJob Github 存储库中与此主题相关的问题中提出了问题:https://github.com/rails/activejob/issues/47
DHH 回答了我一个我没有测试过但可以完成工作的解决方案。
就个人而言,我最终将其放入初始化程序中以全局禁用 Sidekiq 重试并且效果很好:
Sidekiq.configure_server do |config|
config.server_middleware do |chain|
chain.add Sidekiq::Middleware::Server::RetryJobs, :max_retries => 0
end
end
我有同样的需求,即 ActiveJob 包装 Sidekiq 但想支持 max_retries。我把它放在初始化程序中。如果在 ActiveJob 作业上定义了#max_retries,它将用于设置重试。如果#ephemeral?已定义且 returns 为真,作业将不会重新运行,如果失败也不会转移到 'dead'。
class Foobar::SidekiqClientMiddleware
def call(worker_class, msg, queue, redis_pool)
aj_job = ActiveJob::Base.deserialize(msg['args'][0]) rescue nil
msg['retry'] = aj_job.respond_to?(:max_retries) ? aj_job.max_retries : 5
msg['retry'] = false if aj_job.respond_to?(:ephemeral?) && aj_job.ephemeral?
yield
end
end
Sidekiq.configure_client do |config|
config.redis = { url: "redis://#{redis_host}:6379/12" }
config.client_middleware do |chain|
chain.add Foobar::SidekiqClientMiddleware
end
end
Sidekiq.configure_server do |config|
config.redis = { url: "redis://#{redis_host}:6379/12" }
config.client_middleware do |chain|
chain.add Foobar::SidekiqClientMiddleware
end
end
注意:如果您的任何作业在执行时自行创建新作业,那么将其添加到客户端和服务器的中间件链实际上很重要。
您可以捕获异常而不做任何事情,而是重试或配置重试:
class ExampleJob < ActiveJob::Base
rescue_from(StandardError) do |exception|
Rails.logger.error "[#{self.class.name}] Hey, something was wrong with you job #{exception.to_s}"
end
def perform
raise StandardError, "error_message"
end
end
class ExampleJob < ActiveJob::Base
rescue_from(StandardError) do |exception|
retry_job wait: 5.minutes, queue: :low_priority
end
def perform
raise StandardError, "error_message"
end
end
对于 运行 重试,您可以使用 retry_on 方法 retry_on method doc
从 sidekiq 6.0.1
开始,可以将以下内容传递给 ActiveJob worker 以防止其重试:
class ExampleJob < ActiveJob::Base
sidekiq_options retry: false
def perform(*args)
# Perform Job
end
end
更多信息:https://github.com/mperham/sidekiq/wiki/Active-Job#customizing-error-handling
编辑:
根据 this 这需要 Rails 6.0.1
或更高版本。
如果你想为来自 gems 的 ActiveJob
(比如 ActionMailbox::RoutingJob
)禁用重试(或添加任何其他 Sidekiq 选项),你可以使用这种方法(Rails 6.0. 2+).
1) 使用所需的 Sidekiq 选项创建一个模块(使用 ActiveSupport::Concern
)
# lib/fixes/action_mailbox_routing_job_sidekiq_fix.rb
module ActionMailboxRoutingJobSidekiqFix
extend ActiveSupport::Concern
included do
sidekiq_options retry: false
end
end
2) 将其包含在作业 class 的初始化程序中。
# config/initializers/extensions.rb
require Rails.root.join('lib', 'fixes', 'action_mailbox_routing_job_sidekiq_fix')
Rails.configuration.to_prepare do
ActionMailbox::RoutingJob.include ::ActionMailboxRoutingJobSidekiqFix
end