使用与Sidekiq一起使用的ActiveJob禁用自动重试

时间:2015-02-09 15:10:39

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

有没有办法禁用ActiveJob和Sidekiq的自动重试?

我知道只有Sidekiq,我们只需要把

sidekiq_options :retry => false

如此处所述:https://github.com/mperham/sidekiq/wiki/Error-Handling#configuration

但它似乎与ActiveJob和Sidekiq无关。

我也知道这里提出的重新启用重试的解决方案:https://stackoverflow.com/a/28216822/2431728

但这不是我需要的行为。

6 个答案:

答案 0 :(得分:17)

好的,谢谢你的回答。

仅供参考,我还在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

答案 1 :(得分:6)

async updateFields(userId: string, storyId: string, allItemsSeen: boolean, lastId?: string | null): Promise<void> { await this.db.runTransaction(async (transaction) => { const queryRef = this.refs.story(userId, storyId); const query = await transaction.get(queryRef); const data: any = {[ALL_ITEMS_SEEN]: allItemsSeen}; if (lastItemSeenId !== undefined) { data[LAST_ITEM_SEEN_ID] = lastItemSeenId; } if (!query.empty) { transaction.update(query.docs[0].ref, data); // is performed immediately. ========================================== transaction.set(query.docs[0].ref, data, {merge: true}); // the result is obtained only from the second execution of the operation } }); } 开始,可以将以下内容传递给ActiveJob工作者,以防止其重试:

sidekiq 6.0.1

更多信息:https://github.com/mperham/sidekiq/wiki/Active-Job#customizing-error-handling

编辑:

根据this,这也需要Rails class ExampleJob < ActiveJob::Base sidekiq_options retry: false def perform(*args) # Perform Job end end 或更高版本。

答案 2 :(得分:5)

无法使用ActiveJob配置Sidekiq的任何内容。如果您不想使用默认值,请使用Sidekiq Worker。

答案 3 :(得分:2)

你可以赶上异常而不做任何事情,而是重试或配置重试:

  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 wiki for retries with Active Job integration

答案 4 :(得分:1)

我有同样的需求,即ActiveJob包装Sidekiq但想要支持max_retries。我把它放在初始化器中。如果在ActiveJob作业上定义了#max_retries,则它将用于设置重试。如果#ephemeral?已定义并返回true,作业将不会重新运行,如果失败则不会转移到“死”。

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

注意:如果您的任何作业在执行时自行创建新作业,那么将其添加到客户端和服务器的中间件链中实际上非常重要。

答案 5 :(得分:0)

如果您要禁用来自宝石的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)将其包括在初始化器的作业类中。

# 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