Skip to main content
Apresentado por Chris Oliver para o GoRails. Republicado no AppSignal em 19 de setembro de 2026. Background jobs comuns levam você do serial para o paralelo e param por aí. O Rails enfileira vários jobs, eles são executados, e nada sabe quando o último terminou. O problema aparece sempre que a próxima etapa depende de todos os resultados anteriores. Provisionar um cluster é o exemplo mais claro. Você cria três servidores web. O load balancer não pode ser reconfigurado até que cada um deles exista e tenha um endereço IP. Você não pode adicionar endereços que ainda não tem, e cada servidor leva um tempo imprevisível para ficar pronto. Batches do Sidekiq resolvem isso. Você agrupa um conjunto de jobs em um batch e registra um callback que roda uma vez quando o batch é concluído. Serial, para paralelo, e de volta a serial.

O que este tutorial aborda

  • Agrupar jobs em um batch e registrar um callback de sucesso.
  • Por que o callback fica em sua própria classe, não em um bloco.
  • Passar contexto para um callback que roda em outra máquina.

Requisitos

Batches são um recurso do Sidekiq Pro. A gem open source sidekiq-batch implementa a mesma API, o que é útil para experimentar o padrão. Para produção, o Sidekiq Pro é a opção com melhor suporte.

Escreva os jobs em Sidekiq puro

Batches são um recurso do Sidekiq, não do Active Job. Jobs que fazem parte de um batch devem usar o Sidekiq diretamente. Assim, o próprio encapsulamento do Active Job não fica entre o batch e seus jobs. Converter um job é uma mudança de duas linhas. Inclua Sidekiq::Job em vez de herdar de ApplicationJob, e enfileire com perform_async em vez de perform_later.
Sidekiq::Job é o nome atual. Código mais antigo e screencasts mais antigos usam Sidekiq::Worker, que ainda funciona como alias.

Crie o batch

Crie o batch onde o trabalho é disparado e enfileire os jobs dentro de batch.jobs:
O Sidekiq rastreia os jobs enfileirados dentro desse bloco. Quando o último tem sucesso, ele executa o callback uma vez. on(:complete) é o outro callback que você pode registrar. Ele dispara quando todos os jobs terminaram, tenham eles tido sucesso ou não. Use :success quando a próxima etapa depender do sucesso do trabalho.

Escreva o callback como uma classe

O callback é uma classe, não um bloco. No momento em que um batch é concluído, o processo que o criou já não existe mais. O callback roda como seu próprio job do Sidekiq, possivelmente em outra máquina, minutos depois. Nenhuma requisição, nenhuma variável local e nenhuma instância de model continua no escopo. Um bloco capturaria um estado que já não existe. Por isso, o Sidekiq instancia sua classe de callback do zero e passa a ela o status do batch e o hash de options que você registrou:
Esse hash de options é todo o canal para contexto. Qualquer coisa que o callback precise para encontrar o caminho de volta ao registro em que está trabalhando deve ir ali. Mantenha apenas identificadores, porque ele é serializado.

Encadeie batches

Um callback pode criar outro batch. O encadeamento é como você constrói um workflow com mais de duas etapas. Crie os servidores. No callback, configure-os como um novo batch. Nesse callback, marque o cluster como ativo.

Monitore batches com o AppSignal

O AppSignal instrumenta o Sidekiq por meio da sua integração com o Sidekiq e reporta os jobs no namespace background. Batches mudam o que vale a pena observar:
  • O callback é o job que importa. Um batch só é útil se o callback rodar. Deixe o rastreamento de erros avisar você quando ele levantar uma exception. Um callback que falha silenciosamente deixa um workflow pela metade, com os jobs anteriores todos reportando sucesso. Ele roda como um job do Sidekiq, então o AppSignal o instrumenta automaticamente. Adicione eventos de instrumentação para ver para onde vai o tempo dele.
  • Uma única falha interrompe o batch. Com um callback on(:success), um único job com falha significa que o callback nunca roda. A falha vai aparecer como uma issue; a ausência do callback não vai aparecer em lugar nenhum, a menos que você procure por ela.
  • Workflows longos merecem um check-in. Batches de vários estágios que precisam ser concluídos em um agendamento se encaixam bem em check-ins. Um check-in reporta a execução que não aconteceu, em vez da execução que falhou.
  • Marque os jobs com o batch. Adicione o ID do batch ou do workflow como uma tag. Então, quando estiver descobrindo qual estágio travou, você pode reunir todos os jobs de uma mesma execução. O AppSignal armazena os argumentos de cada job como parâmetros.

Transcrição

Transcrito a partir do vídeo e levemente editado. As legendas automáticas entenderam errado vários nomes de produtos e de API, e esses foram corrigidos.
0:02 E aí, pessoal? Neste episódio vamos falar sobre como construir background workers avançados com batches do Sidekiq. Isso é muito legal, porque permite pegar um conjunto de background jobs em execução e agrupá-los. Então, quando terminam, você pode chamar um callback e realmente ir da execução serial para paralela e de volta para serial. Normalmente, quando você usa background jobs, você vai do Rails, que roda em serial, para paralelo, e pronto.0:33 Mas isso é importante para workflows complexos, porque muitas vezes, tipo quando você está construindo algo como o Hatchbox, uma das coisas que você precisa ter em mente ao fazer coisas complexas é que, por exemplo, ao fazer coisas em segundo plano como criar e configurar servidores, às vezes elas precisam esperar um bloco de trabalho terminar. Por exemplo, com um cluster de servidores, você pode ter um load balancer que delega para vários servidores web. E, nesse caso, queremos adicionar um servidor web a ele. Então teríamos um load balancer e dois servidores web, e este também está funcionando como nosso cron, nossos background workers e servidor de banco de dados. Mas você pode imaginar que qualquer configuração assim vai ter problemas parecidos.1:18 O problema é quando você vai fazer o trabalho no backend. Se você enviar isso, vamos saber que você adicionou um servidor web, então precisamos criar esse novo servidor no DigitalOcean. Então podemos disparar esse job para fazer isso. E vamos saber que precisamos atualizar o load balancer e reconfigurá-lo com o endereço IP desse novo servidor web. No entanto, se formos adicionar, digamos, vários desses de uma vez, não conseguiríamos fazer isso tão facilmente.1:45 E o motivo é que, ao criar esses dois servidores web no DigitalOcean, eles podem levar um tempo aleatório para serem criados. E não conseguimos configurar o load balancer imediatamente. E não poderíamos simplesmente dizer: ok, configure todas as máquinas, crie as novas máquinas, porque esse load balancer precisa esperar até que os novos servidores web sejam criados e tenhamos endereços IP para eles. Não podemos adicionar os endereços IP deles ao load balancer se não os tivermos. E esse é o nosso problema.2:16 Precisamos criar todos esses servidores em um batch e esperar até que todos terminem, e então podemos configurar todas as máquinas. Assim temos todas as informações necessárias para fazer a configuração. É aí que os batches do Sidekiq entram em cena. Agora vamos falar sobre batches do Sidekiq. Esse é um recurso pro do Sidekiq.2:35 Então isso vai custar dinheiro, mas com certeza vale a pena, e vem com outros recursos incríveis que seriam praticamente necessários para qualquer aplicação de produção que use background workers avançados como esse. Você também tem a opção de usar uma versão open source dos batches do Sidekiq, que adiciona a mesma API. Vou mostrar essa para vocês, só para que possam clonar esse repositório e experimentar também, mas provavelmente vocês vão querer usar o Sidekiq Pro. Batches são muito legais. Basicamente, você escreve uma pequena configuração como esta e cria um novo batch, define uma descrição se quiser, mas o mais importante é que você pode criar um callback.3:16 Callbacks provavelmente vão parecer um pouco estranhos para vocês, mas o motivo de isso estar em outra classe, onde seus callbacks são definidos, é que tudo isso está rodando em background workers que podem rodar em máquinas diferentes, e você não vai ter acesso a onde isso foi executado originalmente. Então, quando é bem-sucedido e chama o callback, você não vai ter mais aquela requisição Rails original ou instância de model. Isso pode estar em uma máquina totalmente separada. E por isso você vai precisar criar uma nova instância de classe para colocar dentro disso. E aí você basicamente só usa esse bloco jobs para criar todos os seus novos workers, e é basicamente isso.3:59 E seus jobs vão rodar nesse batch, e então vamos instanciar essa classe de callback, seja lá como você a definir. Ela vai receber quaisquer opções extras que você queira adicionar, então você pode ter isso. Mas é basicamente isso. Vamos dar uma olhada em um exemplo. Vamos tentar usar esse conceito como exemplo só para você conseguir entender bem.4:20 Então o que eu tenho aqui é uma aplicação Rails novinha, e eu adicionei algumas gems a ela usando o template Jumpstart. Mas principalmente vamos adicionar o Sidekiq Batch. Então você pode usar o Sidekiq Pro ou o Sidekiq Batch. Esse aqui vai permitir que vocês clonem esse repositório e deem uma olhada. Então vamos usar esse.4:38 Depois só precisamos criar alguns jobs, ou pelo menos um lugar que vai criar o batch. Eu fiz isso dentro de um job mesmo. Então eu tenho um job que cria um batch e roda esses jobs. Mas você poderia fazer isso dentro dos seus models, controllers, plain old Ruby objects, onde quiser criar o batch. Todo esse código, obviamente, vai rodar no Sidekiq.4:58 Então todo o trabalho dos workers vai rodar ali. Vamos criar um job rapidinho. Vamos dizer, editar app/jobs/create_server_job.rb. Então nosso CreateServerJob vai ter o método perform. E precisamos incluir o Sidekiq Worker aqui.5:19 E o motivo de querermos usar isso em vez do Active Job é que, com batches do Sidekiq, você quer garantir que está usando só o Sidekiq. Você não quer nada do Active Job interferindo nisso, e vai funcionar muito, muito melhor dessa forma se você estiver interagindo só com o Sidekiq. Então você pode precisar converter alguns dos seus jobs para Sidekiq puro, mas é realmente fácil. A única coisa que você realmente precisa mudar é essa linha aqui: não herdar do Active Job e usar perform_async em vez de perform_later com o Active Job. É basicamente isso.5:55 E aqui você quer fazer algum trabalho. Então você quer fazer seu trabalho em paralelo. É basicamente isso. Você não precisa fazer nada muito sofisticado aqui. E onde você quiser disparar esses workers é onde você quer criar o código do job ou do batch.6:13 Então vamos criar outro job chamado CreateClusterJob. class CreateClusterJob, perform. E é aqui que queremos criar nosso batch. Então vamos escrever batch = Sidekiq::Batch.new, batch.description = "Creating cluster". E depois também vamos escrever batch.on :success.6:36 Queremos chamar algum tipo de callback. Então você pode dar um nome de classe aqui. Você também pode, pelo menos com o Sidekiq Batch, dar uma string aqui, e ela também vai ser constantizada. Então, se tivéssemos apenas uma classe chamada Created aqui, class Created, poderíamos fazer isso. Precisaríamos, claro, colocá-la em um namespace.6:58 CreateClusterJob::Created. Assim temos acesso a isso muito facilmente. Também podemos fazer isso apenas como uma classe. E aí você pode, opcionalmente, passar um hash de options. Então, se você precisasse que o cluster ID fosse passado, poderia fazer isso também.7:18 Então você poderia fazer algo assim, passando o cluster ID. Não temos um model Cluster, então vou usar 999 aqui. Assim temos um exemplo para vocês verem. E depois dizemos batch.jobs do.7:28 E aqui precisamos enfileirar nossos outros jobs. Então, para simplificar, vamos dizer 5.times. Vamos fazer isso aqui. Pegamos o número ali.7:41 CreateServerJob.perform_async, passando i. E é isso. Isso vai garantir que eles sejam adicionados. E ao fazer isso, ele vai enfileirar os jobs e começar a executá-los.8:02 E aí, dentro da sua classe de callback, você só precisa dizer on_success. E, opcionalmente, você também pode fazer um def on_complete, se quiser. Há uma nuance ou diferença entre os dois. Eu sempre usei on_success. Então é isso que vamos usar aqui.8:20 Os dois recebem um status e options. Então você pode imprimir o status e as options também. As options devem ser exatamente o hash que você passou. E o status vai ser o status do Sidekiq. Então vamos colocar um separador aqui e escrever “created cluster”.8:40 Ponto. Então devemos ver isso sempre que esses jobs de servidor terminarem. Então esse é o trabalho que você vai querer fazer em paralelo. Vamos apenas dar um sleep por um tempo aleatório entre 1 e 10 segundos. E depois vamos imprimir “creating server…”8:59 E podemos passar o ID que recebemos aqui. E depois, quando terminar, “created”. Só para vermos nos nossos logs as linhas exatas de servidor que correspondem entre si. Assim podemos contá-las e garantir que está tudo correto. Porque devemos ver isso só uma vez.9:26 Devemos ver isso ser impresso quantas vezes chamarmos. Então 5 vezes nesse caso, 10 vezes se você mudar para 10, o que for. E agora temos esse job basicamente disparando vários outros. E esse código vai rodar assim que terminar, só uma única vez.9:47 E ele também vai rodar dentro do Sidekiq. Então essa é outra coisa para ter em mente. É por isso que essa classe é instanciada: porque ela roda em qualquer servidor em que for rodar dentro do Sidekiq. Então ela não vai ter acesso a nenhuma das variáveis de instância ou outras coisas locais. Porque essa vai ser uma instância novinha dessa classe Created quando ela rodar.10:07 É por isso que você precisa ter a capacidade de passar essas options para acessar, digamos, o ID do seu cluster quando isso terminar, para descobrir qual cluster você precisa marcar como ativo, por exemplo. Dito isso, podemos ir para o console do Rails e testar isso. Vamos iniciar o Sidekiq. Está rodando agora, e vamos dizer CreateClusterJob.new.perform. Se tudo tiver dado certo, devemos ver cinco jobs enfileirados.10:34 Essa é a ideia desses jobs. Sidekiq, e aqui podemos vê-los rodando. Então temos os servidores de zero a quatro, então cinco deles, e você pode ver que eles estão rodando, na ordem em que o Sidekiq os processa primeiro. Você pode ver que o três terminou antes de alguns dos outros, e tudo isso foi concluído com sucesso.10:56 Então vemos que cinco jobs começaram e cinco jobs terminaram. E então, bem no final, iniciou um novo worker de callback de batch do Sidekiq, que é o que a gem implementou para nós, dispara isso como um job e então isso roda só essa única vez. Isso é legal, porque agora temos a capacidade de ir de uma única coisa rodando para várias e depois de volta para uma única coisa. E isso é muito legal, porque nos permite fazer isso de forma distribuída pelo nosso cluster Sidekiq também. É muito comum fazer isso com threading, onde você tem só uma máquina, sobe um monte de threads, faz algum trabalho paralelo e depois junta e espera até que essas threads terminem, e então faz as coisas em serial de novo.11:43 Mas com o Sidekiq, podemos fazer isso de forma distribuída pelos nossos servidores workers do Sidekiq. Então isso é muito legal e nos permite fazer muito mais dessa forma, de uma maneira bem melhor, porque isso agora pode ser escalado em várias máquinas, o que é fantástico. Então o Sidekiq Pro é onde você consegue isso, ou você usa a gem. Eu definitivamente recomendaria o Sidekiq Pro. Vai ter um suporte melhor.12:08 Provavelmente vai implementar tudo isso de forma mais eficiente ou seja lá o que for. E com certeza vai melhorar conforme o tempo passa. Então esse recurso é definitivamente meio que um requisito conforme você vai avançando na construção de background jobs mais avançados. Você provavelmente vai precisar disso para certas situações, porque você tem um workflow que precisa que seu código execute. E isso vai ajudar você a construir esses workflows.12:29 Por exemplo, seu callback Created poderia na verdade iniciar outro batch e disparar mais um. Então isso é bem interessante. Você pode ter essas coisas começando a se encadear. E é isso que eu faço no Hatchbox. Então é bem legal ver como tudo isso funciona e as coisas complexas que você pode fazer.12:49 Então isso é muito legal. E é claro que é um recurso complexo, necessário para muitas aplicações. Então espero que vocês tenham gostado deste episódio. Se vocês quiserem ver mais sobre background workers avançados ou coisas do Sidekiq, me avisem nos comentários abaixo. Agora a gente se fala no próximo episódio.13:05 Até mais.

Sobre este tutorial

Este tutorial resume um screencast do GoRails sobre como construir background workers avançados com batches do Sidekiq, de Chris Oliver. O screencast é a obra original. O GoRails o publica, junto com o restante da série, em gorails.com.