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
Pero si quiero establecer el número de reintentos, como el de Sidekiq:
include Sidekiq::Worker
sidekiq_options :retry => 5
¿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.