Sidekiq: manipulación masiva de jobs y procesos
Serie Sidekiq — parte 3 de 4
- Infra: iniciando, deteniendo, matando
- Diagnóstico por consola
- Estás aquí — Manipulación masiva
- Hacks de UI en el panel
Después de diagnosticar (parte 2), generalmente viene la parte invasiva: sacar un worker problemático del camino, reorganizar la queue, borrar jobs que ya no tienen sentido. Este post es la caja de herramientas para eso.
El
; nilal final de los bloques es solo para evitar querails consoleimprima miles de líneas cuando la colección es grande.
Seleccionando jobs en retry por nombre de clase
1
2
3
job_class_name = 'SidekiqTest::SidekiqTestWorker'
jobs = Sidekiq::RetrySet.new.select { |job| job.klass == job_class_name }; nil
jobs.size
Seleccionando jobs muertos por nombre de clase
1
2
3
job_class_name = 'SidekiqTest::SidekiqTestWorker'
jobs = Sidekiq::DeadSet.new.select { |job| job.klass == job_class_name }; nil
jobs.size
Seleccionando jobs encolados en una queue por nombre de clase
1
2
3
4
queue_name = 'default'
job_class_name = 'SidekiqTest::SidekiqTestWorker'
jobs = Sidekiq::Queue.new(queue_name).select { |job| job.klass == job_class_name }; nil
jobs.count
Reencolando jobs seleccionados para retry
1
jobs.each(&:retry)
Aplica a cualquier colección de jobs proveniente de RetrySet o DeadSet. Mueve todo de vuelta a la queue de origen.
Borrando jobs seleccionados
1
jobs.each(&:delete)
Mismo patrón, con la operación inversa. Úsalo cuando estés seguro de que podés descartar — no hay vuelta atrás.
Moviendo 1000 jobs de una clase a otra queue
1
2
3
4
5
6
7
8
9
10
queue_name = 'default'
new_queue_name = 'funnels_test_worker'
queue = Sidekiq::Queue.new(queue_name)
queue.first(1000).each do |job|
if job.klass == "SidekiqTest::SidekiqTestWorker"
SidekiqTest::SidekiqTestWorker.set(queue: new_queue_name).perform_async(*job.args)
job.delete
end
end; nil
Este es el snippet que más salva el día. Cuando un worker está hundiendo una queue compartida, en vez de pausar todo, yo:
- Creo una queue dedicada (
funnels_test_worker) - Muevo los jobs problemáticos a ella
- Levanto un proceso Sidekiq separado consumiendo esa queue con concurrencia reducida (ej: 1 thread)
El resto de la operación no lo nota — y puedo debuguear el worker con calma sin presionar la queue principal.
Pausando procesos para deploy (quiet)
1
2
ps = Sidekiq::ProcessSet.new
ps.each(&:quiet!)
quiet! hace que cada proceso deje de tomar jobs nuevos, pero termine los que ya están corriendo. La forma educada de drenar antes de bajar — buena para deploys que no usan orquestrador.
Deteniendo procesos vía API
1
2
ps = Sidekiq::ProcessSet.new
ps.each(&:stop!)
Equivalente al sidekiqctl stop de la parte 1, solo que por consola en vez de shell.
Limpiar todo el Redis de Sidekiq — BORRA TODO
1
Sidekiq.redis { |conn| conn.flushdb }
Bomba nuclear: borra todo lo que Sidekiq tiene en Redis (queues, retries, dead set, stats). Usalo solo cuando sabés que podés reprocesar con tranquilidad o estás en una máquina de desarrollo. En producción, esto es un incidente — solo hacelo con un plan de recuperación claro.
Próximo en la serie
Hacks de UI para el panel de Sidekiq — cuando la pantalla de retries tiene 100 mil ítems y la UI nativa no alcanza.