job active sidekiq rails-activejob

active job sidekiq



¿Cómo configurar el conteo de reintentos para Sidekiq con ActiveJob? (6)

Desde la API de Rails, encontré que ActiveJob puede reintentar el intervalo de trabajo:

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

http://api.rubyonrails.org/classes/ActiveJob/Enqueuing.html

Pero si quiero establecer el número de reintentos, como el de Sidekiq:

include Sidekiq::Worker sidekiq_options :retry => 5

https://github.com/mperham/sidekiq/wiki/Error-Handling

¿Cómo hacer en este código de ejemplo?

class SiteScrapperJob < ActiveJob::Base rescue_from(ErrorLoadingSite) do retry_job queue: :low_priority end def perform(*args) # raise ErrorLoadingSite if cannot scrape end end

Ahora agregué esto a mi clase de trabajo:

Sidekiq.default_worker_options = { retry: 5 }

Pero no parece muy bueno.


Desde Rails 5.1, hay una forma integrada de hacerlo usando el método retry_on . Es un método general de ActiveJob, por lo que funcionará con cualquier backend de cola, no solo con Sidekiq.

Por ejemplo, para su trabajo específico podría hacer:

class SiteScraperJob < ActiveJob::Base retry_on ErrorLoadingSite, queue: :low_priority, attempts: 5 def perform(*args) # raise ErrorLoadingSite if cannot scrape end end

También puede establecer un intervalo de espera constante o una estrategia de espera exponencial, como se explica en los retry_on .


Hay una sidekiq-retry que hace el trabajo.

class SiteScrapperJob < ActiveJob::Base include ActiveJob::Retry.new(limit: 5, strategy: :exponential) def perform(*args) # raise ErrorLoadingSite if cannot scrape end end

Otra opción es usar el middleware sidekiq :

Primero defina el método de clase job_options que estará disponible en las subclases:

class ApplicationJob < ActiveJob::Base def self.job_options(options) @job_options = options end def self.get_job_options @job_options || {} end end

Agregue middleware que lea las opciones de trabajo de la clase de trabajos y las escriba en el elemento de trabajo para 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

Y finalmente

class SiteScrapperJob < ApplicationJob job_options retry: 5 def perform # your code end end


No se puede. Si quieres usar cosas específicas de Sidekiq, necesitas usar las API específicas de Sidekiq. ActiveJob no expone el mecanismo de reintento de Sidekiq.


Si solo usas sidekiq, nerver change backend, Monkey Patch puede ayudarte.

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

Entonces, puedes escribir como abajo:

class BaseJob < ActiveJob::Base sidekiq_options retry: 2, queue: :low sidekiq_retry_in { |count, _| 3 * count } def perform; end end

codificación feliz


También podría interesarle esta solución que utiliza serialize y deserialize api para almacenar el número de intentos.

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

Tómalo desde here .


Vea here los valores por defecto para Sidekiq. El retry atributo "acepta" un valor booleano y no un número como asumió.

Desde la combinación de active_job en Rails, este otro archivo puede ver que, una vez más, retry no acepta el número de reintentos.

Lo que dice la documentación es que, por trabajo, puede definir si el trabajo se reintenta o no.

También traté de encontrar si el archivo config/sidekiq.yml puede recibir este número y parece que no puede.

Finalmente,

Si no soluciona el error en 25 reintentos (aproximadamente 21 días), Sidekiq dejará de volver a intentarlo y moverá su trabajo a la Cola de trabajo muerta. Puede corregir el error y reintentar el trabajo manualmente en cualquier momento dentro de los próximos 6 meses utilizando la interfaz de usuario web.