ruby on rails - retries - cómo eliminar un trabajo en sidekiq
sidekiq scheduler (7)
Estoy usando sidekiq en mi aplicación de rieles. Los usuarios de mi aplicación crean informes que inician un trabajo de sidekiq. Sin embargo, a veces los usuarios desean poder cancelar informes de "procesamiento". Eliminar el informe es fácil, pero también necesito poder eliminar el trabajo de sidekiq.
Hasta ahora he podido obtener una lista de trabajadores así:
workers = Sidekiq::Workers.new
y cada trabajador tiene argumentos que incluyen un report_id para que pueda identificar qué trabajo pertenece a qué informe. Sin embargo, no estoy seguro de cómo eliminar realmente el trabajo. Se debe tener en cuenta que deseo eliminar el trabajo si actualmente está ocupado o configurarlo en reintento.
De acuerdo con esta página de documentación de Sidekiq para eliminar un trabajo con un solo ID, debe iterar la cola y llamar a .delete
.
queue = Sidekiq::Queue.new("mailer")
queue.each do |job|
job.klass # => ''MyWorker''
job.args # => [1, 2, 3]
job.delete if job.jid == ''abcdef1234567890''
end
También hay un complemento llamado sidekiq-status que le brinda la posibilidad de cancelar un solo trabajo
scheduled_job_id = MyJob.perform_in 3600
Sidekiq::Status.cancel scheduled_job_id #=> true
Hay una forma sencilla de eliminar un trabajo si conoce el ID de trabajo:
job = Sidekiq::ScheduledSet.new.find_job(job_id)
begin
job.delete
rescue
Rails.logger.error "Job: (job_id: #{job_id}) not found while deleting jobs."
end
La forma más sencilla que encontré para hacer esto es:
Sidekiq::ScheduledSet.new.each do |_job|
next unless [online_jid, offline_jid].include? _job.jid
status = _job.delete
end
donde [job_id] es el JID que pertenece al informe. Seguido por:
job = Sidekiq::ScheduledSet.new.find_job([job_id])
No encontré la necesidad de recorrer toda la cola como se describe en otras respuestas aquí.
Puede eliminar el filtrado de trabajos sidekiq por clase de trabajo y argumentos:
class UserReportsWorker
include Sidekiq::Worker
def perform(report_id)
# ...
end
end
jobs = Sidekiq::ScheduledSet.new.select do |retri|
retri.klass == "UserReportsWorker" && retri.args == [42]
end
jobs.each(&:delete)
Si desea cancelar un trabajo programado, no estoy seguro acerca de la respuesta de @ KimiGao, pero esto es lo que adapté de la documentación de API actual de Sidekiq:
jid = MyCustomWorker.perform_async
r = Sidekiq::ScheduledSet.new
jobs = r.select{|job| job.jid == jid }
jobs.each(&:delete)
Espero eso ayude.
Tuve el mismo problema, pero la diferencia es que necesitaba cancelar un trabajo programado, y mi solución es:
job.delete
Yo tuve el mismo problema. ¡Lo resolví registrando el ID de trabajo cuando lo inicializo y creando otra función cancel!
para borrarlo.
Aquí está el código:
after_enqueue do |job|
sidekiq_job = nil
queue = Sidekiq::Queue.new
sidekiq_job = queue.detect do |j|
j.item[''args''][0][''job_id''] == job.job_id
end
if sidekiq_job.nil?
scheduled = Sidekiq::ScheduledSet.new
sidekiq_job = scheduled.detect do |j|
j.item[''args''][0][''job_id''] == job.job_id
end
end
if sidekiq_job.present?
booking = job.arguments.first
booking.close_comments_jid = sidekiq_job.jid
booking.save
end
end
def perform(booking)
# do something
end
def self.cancel!(booking)
queue = Sidekiq::Queue.new
sidekiq_job = queue.find_job(booking.close_comments_jid)
if sidekiq_job.nil?
scheduled = Sidekiq::ScheduledSet.new
sidekiq_job = scheduled.find_job(booking.close_comments_jid)
end
if sidekiq_job.nil?
# Report bug in my Bug Tracking tool
else
sidekiq_job.delete
end
end