Отключить автоматическую повторную попытку с помощью ActiveJob, используемого с Sidekiq

Есть ли способ отключить автоматическую повторную попытку с ActiveJob и Sidekiq?

Я знаю, что только с Sidekiq, мы просто должны поставить

sidekiq_options :retry => false

как упомянуто здесь: https://github.com/mperham/sidekiq/wiki/Error-Handling#configuration

но, похоже, он не работает с ActiveJob и Sidekiq.

Я также знаю решение для полного отключения повтора, предложенное здесь: qaru.site/info/618319/...

Но это не то поведение, которое мне нужно.

Ответ 1

Хорошо, спасибо за ответ.

Просто для информации, я также задал вопрос в проблеме, связанной с этой темой в репозитории 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

Ответ 2

Невозможно настроить что-либо о Sidekiq с помощью ActiveJob. Используйте стороннего работника, если вы не хотите использовать настройки по умолчанию.

Ответ 3

Вы можете догнать исключение и ничего не делать, вместо этого повторите попытку или настройте повтор:

  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 doc

Sidekiq wiki для повторных попыток с интеграцией Active Job

Ответ 4

У меня была такая же потребность, то есть ActiveJob, обертывающая Sidekiq, но желая поддерживать max_retries. Я положил это в инициализатор. Если #max_retries определено в задании ActiveJob, оно будет использоваться для установки повторений. Если #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

Примечание: на самом деле важно добавить это в цепочку промежуточного программного обеспечения как для клиента, так и для сервера, если какое-либо из ваших заданий создает новые задания самостоятельно по мере их выполнения.