Sidekiq: manipulação em massa de jobs e processos
Série Sidekiq — parte 3 de 4
- Infra: iniciando, parando, matando
- Diagnóstico pelo console
- Você está aqui — Manipulação em massa
- Hacks de UI no painel
Depois de diagnosticar (parte 2), normalmente vem a parte invasiva: tirar um worker problemático da frente, reorganizar a fila, deletar jobs que não fazem mais sentido. Esse post é a caixa de ferramentas pra isso.
O
; nilno final dos blocos é só pra evitar orails consoleimprimir milhares de linhas quando a coleção é grande.
Selecionando jobs em retry pelo nome da classe
1
2
3
job_class_name = 'SidekiqTest::SidekiqTestWorker'
jobs = Sidekiq::RetrySet.new.select { |job| job.klass == job_class_name }; nil
jobs.size
Selecionando jobs mortos pelo nome da classe
1
2
3
job_class_name = 'SidekiqTest::SidekiqTestWorker'
jobs = Sidekiq::DeadSet.new.select { |job| job.klass == job_class_name }; nil
jobs.size
Selecionando jobs enfileirados em uma fila pelo nome da classe
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
Reenfileirando jobs selecionados pra retry
1
jobs.each(&:retry)
Aplica em qualquer coleção de jobs vinda do RetrySet ou DeadSet. Move tudo de volta pra fila de origem.
Deletando jobs selecionados
1
jobs.each(&:delete)
Mesmo padrão, com a operação inversa. Use depois que você tem certeza que pode descartar — não tem volta.
Movendo 1000 jobs de uma classe pra outra fila
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
Esse é o snippet que mais salva o dia. Quando um worker está derrubando uma fila compartilhada, em vez de pausar tudo, eu:
- Crio uma fila dedicada (
funnels_test_worker) - Movo os jobs problemáticos pra ela
- Subo um processo Sidekiq separado consumindo essa fila com concorrência reduzida (ex: 1 thread)
O resto da operação não sente — e eu posso debugar o worker com calma sem pressionar a fila principal.
Pausando processos pra deploy (quiet)
1
2
ps = Sidekiq::ProcessSet.new
ps.each(&:quiet!)
quiet! faz cada processo parar de pegar jobs novos, mas terminar os que estão rodando. Forma educada de drenar antes de derrubar — bom pra deploys que não usam orquestrador.
Parando processos via API
1
2
ps = Sidekiq::ProcessSet.new
ps.each(&:stop!)
Equivalente ao sidekiqctl stop da parte 1, só que via console em vez de shell.
Limpar todo o Redis do Sidekiq — APAGA TUDO
1
Sidekiq.redis { |conn| conn.flushdb }
Bomba nuclear: apaga tudo que o Sidekiq tem no Redis (filas, retries, dead set, stats). Use só quando você sabe que pode reprocessar com tranquilidade ou está numa máquina de dev. Em produção, isso é incidente — só faça com plano de recuperação claro.
Próximo da série
Hacks de UI pro painel do Sidekiq — quando a tela de retries tem 100 mil itens e a UI nativa não dá conta.