perform_later e deliver_later funcionam como antes.
O que este tutorial aborda
- Adicionar o Solid Queue e suas tabelas a uma aplicação existente.
- Apontar o Active Job para ele, um ambiente por vez.
- Executar o Solid Queue com seu próprio comando ou com o plugin do Puma.
- Ler as tabelas que ele cria, e controlar a ordem em que os jobs são executados.
Requisitos
O Rails 8 gera novas aplicações com o Solid Queue já configurado. Se você executou
rails new no Rails 8, a etapa de instalação já está feita. Você pode seguir direto para a execução do worker.Instalar o Solid Queue
Adicione a gem, instale suas migrations, e migre:Apontar o Active Job para o Solid Queue
Defina o adapter de fila por ambiente, emconfig/environments/development.rb e novamente em config/environments/production.rb:
config/environments/test.rb no adapter :test, a menos que você tenha um motivo para não fazer isso. Testes que verificam jobs enfileirados são mais fáceis de escrever com o adapter de teste.
Definir o adapter apenas faz o Rails gravar jobs no banco de dados. Nada os executa até que o processo worker esteja em execução, então enfileirar sem que nada aconteça é esperado nesse estágio, e não uma configuração incorreta.
Executar o worker
Como processo próprio
Procfile e gerencia vários processos.
Dentro do Puma
Se você preferir não gerenciar um segundo processo, o Solid Queue traz um plugin para o Puma. Adicione-o aconfig/puma.rb:
bin/rails server te dá os dois. Por padrão, o Solid Queue faz fork de processos separados de worker e dispatcher. A integração com o Puma do AppSignal reporta a capacidade do servidor web, não a dos jobs. Use a integração com o Active Job para monitorar a performance dos jobs.
O que o Solid Queue armazena
Cada parte do estado do Solid Queue é uma tabela do Active Record. Você pode consultá-la a partir da console do Rails em vez de ter que consultar um serviço separado.
Poder ler e corrigir a linha de um job é uma diferença real em relação às filas baseadas em Redis. Nelas, editar um job diretamente é desencorajado. Recorra a isso para corrigir um erro, não como parte rotineira da execução dos jobs.
Ordem e prioridade das filas
Dois mecanismos decidem o que executa a seguir, e eles se combinam. Ordem das filas. Um worker configurado com uma lista de filas as esvazia na ordem dada. Um worker que escutareal_time e depois background esvazia real_time primeiro, sempre.
Prioridade. Os jobs também têm uma prioridade inteira. O menor valor vence, e a contagem começa em zero, então uma prioridade 0 supera uma prioridade 1.
Monitore o Solid Queue com o AppSignal
O AppSignal instrumenta o Solid Queue através da sua integração com o Solid Queue e, para tudo que é enfileirado através do Active Job, através da sua integração com o Active Job. Os jobs são reportados no namespacebackground, separado das requisições web. Um job lento não distorce seus percentis de requisição.
Duas coisas vale a pena configurar assim que o Solid Queue estiver em execução:
- Erros de jobs que falharam. Uma linha em
solid_queue_failed_executionsindica que um job lançou uma exceção. O rastreamento de erros do AppSignal informa o que ele lançou, com que frequência, e com quais argumentos. - Duração dos jobs e queue time. Cada job recebe um trace de performance, dividido nos eventos que executou. A integração com o Active Job reporta quanto tempo os jobs esperam antes de executar. Um queue time crescente pode significar que os jobs estão chegando mais rápido do que os workers conseguem processá-los.
Transcrição
Transcrito do vídeo e levemente editado. As legendas automáticas entenderam errado vários nomes de produtos e de APIs, e esses foram corrigidos.Ler a transcrição
Ler a transcrição
0:02 Olá, pessoal, nesta aula vamos falar sobre como usar o Solid Queue nas suas aplicações Rails. Se você vem de outro backend do Active Job, talvez o Sidekiq: o Sidekiq precisa do Redis para que os jobs sejam enviados. Então sua aplicação Rails envia uma mensagem para o Redis, o Redis é monitorado pelo Sidekiq, que dispara os jobs. O Good Job é outra ferramenta parecida, mas usa seu banco de dados Postgres, e o Solid Queue é bem parecido com isso, usando o banco de dados da sua aplicação Rails. Então você executa uma migration, adiciona algumas tabelas, e um processo vai executar e monitorar seu banco de dados por jobs.0:41 O que é legal nisso é que você não precisa de um serviço extra como o Redis. Se você não estivesse usando ele para mais nada, teria que adicionar o Redis para usar o Sidekiq, e essa é uma forma de simplesmente usar o banco de dados que você já tem. Então vamos configurar um exemplo. Vou iniciar uma aplicação Rails novinha, e vou mostrar aqui, só para referência, que estamos no Rails 7.1, e podemos executar
rails new, e vamos chamar nossa aplicação de Solid Queue Example. Voltamos em um instante, quando isso for criado, e vamos adicionar o Solid Queue e enfileirar alguns jobs. Muito bem, vamos entrar no nosso Solid Queue Example, e vamos fazer bundle add solid_queue para adicionar isso ao nosso Gemfile.1:30 E então o próximo passo é instalar as migrations, e depois db:migrate. Isso pode mudar no futuro, provavelmente vai existir um script de instalação que fará isso diretamente, porque outra coisa que atualmente é necessária é um arquivo de configuração. Então vamos executar isso para instalar as migrations, e depois podemos fazer rails db:migrate para adicionar isso ao nosso banco de dados. Estou usando SQLite neste exemplo, mas você pode usar Postgres ou MySQL, e suporte para MS SQL e outros provavelmente será adicionado em breve, e vai haver outras melhorias aqui também. Mas aqui você pode ver que isso cria uma, duas, três, quatro, cinco, seis, sete, oito, nove tabelas para gerenciar seu job.2:14 Então você vai poder olhar essas tabelas mais tarde e ver o que estão fazendo enquanto enfileiramos jobs e outras coisas, mas vamos testar o comando primeiro. E vou mostrar que agora ele vai quebrar e dizer que não encontramos um arquivo de configuração. Então podemos criar config/solid_queue.yml, e agora nosso processo do Solid Queue pode ser executado. Vai funcionar sem problemas. Por padrão, ele vai iniciar um dispatcher e um worker que escutam todas as filas.2:50 E o dispatcher é basicamente o supervisor que mantém todos os workers e acompanha os processos e tudo mais. E os workers vão de fato fazer o processamento do job. Então isso vai escutar todas as filas por padrão e ter um thread pool de tamanho cinco, e configurar um processo para isso com a configuração padrão. E você sempre pode ajustar isso para seu caso de uso e dizer que precisa de 10 processos e que eles precisam tratar filas diferentes e tudo mais, mas vamos ficar com esses padrões por agora. Então agora podemos executar uma aplicação Rails e criar alguns jobs.3:26 Então podemos gerar um mailer, digamos um mailer, temos um user mailer e queremos notificar o usuário sobre, talvez, um recibo de pagamento. Também poderíamos simplesmente criar um job, como um job de importação que tem algo para fazer. E esses, vamos poder abrir a console do Rails. Na verdade, primeiro vamos entrar nos nossos config environments. Faremos isso já.3:57 Vamos entrar em config/environments, e você vai definir aqui uma linha de config: config.active_job.queue_adapter = :solid_queue. Essa vai ser a linha que faz a mágica de conectar o Active Job ao Solid Queue, e ela vai começar a enviar jobs para o banco de dados. Depois precisamos daquele processo separado para realmente executar os workers de jobs e o dispatcher, para que o trabalho seja feito. Porque se deixarmos apenas assim, o Rails vai enfileirar jobs e nada vai escutá-los, a menos que iniciemos esse outro processo. Você pode entrar no seu ambiente de teste e adicionar isso aqui, e adicionar em produção.4:43 Talvez no seu ambiente de teste você queira manter o adapter de teste, e isso é totalmente normal, fácil de trabalhar. Mas em produção, você vai fazer isso também. Certo, então vamos deixar test fora disso e usar o adapter de teste por agora, e vamos configurar o Solid Queue em development. Certo, agora podemos ir olhar nossa aplicação Rails. Vamos abrir a console do Rails e fazer UserMailer.receipt.deliver_later, o que vai enfileirar o job.5:18 Você vai ver que ele diz que foi tratado pelo Solid Queue, que enfileirou um job. A fila padrão tem um ID do Active Job e todas as outras informações do Action Mailer, e então enfileirou o job de envio de e-mail e nos devolveu, dizendo, aqui está. Também podemos configurar aquele job de importação e chamar perform_later nele. Ainda não fazemos nada com esses jobs, mas eles vão ser enfileirados, e podemos dar uma olhada no nosso banco de dados para ver o que tem lá. Como estamos usando SQLite, vamos ter, na pasta storage, nosso banco de dados development.sqlite.6:00 Então é isso que queremos abrir em uma ferramenta como o TablePlus, para poder explorar e ver o que está acontecendo aqui. A primeira tabela que temos é blocked_executions. Deixa eu redimensionar isso. Tabela blocked_executions, claimed_executions, failed_executions, e solid_queue_jobs é onde podemos ver nossos dois jobs que acabamos de adicionar. Então nada está sendo processado ainda, os jobs estão apenas ali, parados.6:29 Eles têm os argumentos que foram passados, prioridades que você pode usar para dizer que esse job é mais prioritário que outro, e também têm o ID do Active Job, quando foi agendado, e quando foi criado e atualizado, e também vai registrar quando terminou. Então essa é toda a informação do job. Temos solid_queue_pauses, então parece que vamos poder pausar um job e interromper sua execução no meio. Temos nossos processos, então se iniciarmos nossos workers do Solid Queue, isso vai aparecer aqui. Vamos ver o último heartbeat, e ele acompanha essas coisas.7:10 Também temos ready_executions e scheduled_executions. Então podemos ter jobs e essas executions, e quando criamos esses jobs, uma execution é configurada automaticamente para nós. Então poderíamos criar um job e depois agendá-lo para mais tarde. Ele também pode ser recorrente. Isso está configurado para tratar boa parte disso para nós.7:30 Não precisamos saber muito sobre como isso funciona internamente, mas queremos saber sobre essas prioridades e as filas, porque as filas também podem determinar como os jobs são tratados. E eu sei que isso também é mencionado aqui. Éh, éh, éh… Aqui está, ordem e prioridades das filas. Então, se você especificar uma lista de filas para um worker, elas serão consumidas na ordem dada, por exemplo, se você escolher real_time e depois background, os jobs de real_time sempre terão precedência sobre os outros.8:03 Mas você também pode dar prioridades inteiras ao job. Então você pode dizer que existe uma prioridade zero ou uma prioridade um. A prioridade zero será sempre mais importante, e elas começam em zero, meio que como um array. Então zero é o primeiro item, um é o próximo, e assim por diante.8:26 Então é isso, e é aí que vemos essa prioridade aqui nas nossas executions. E agora podemos executar nosso comando para iniciar o Solid Queue. Então teríamos o Rails rodando em um servidor, em um processo diferente, e estaríamos enfileirando jobs, o que poderia vir de rake tasks ou de qualquer outro lugar, assim como você usaria o Active Job normalmente. E vamos ver que ele está executando esses dois jobs e que eles terminaram. O job número dois foi mais rápido que o job número um, que era o e-mail, e ele pegou esses dois jobs e simplesmente imprime a saída típica que você veria normalmente, como nos seus logs do Sidekiq também.9:10 Então é basicamente isso. Não há muitas coisas interessantes para explorar. Vemos que esses processos agora estão visíveis aqui, então podemos consultar nosso banco de dados. Se quisermos ver em um dashboard quantos workers temos e o que estão fazendo, podemos simplesmente consultar o banco de dados em vez de ter que conversar com, sabe, outro processo no Linux ou algo assim. Temos todas essas informações disponíveis diretamente em models do Rails, o que é realmente muito bom.9:44 E também, uma das coisas desencorajadas no Sidekiq é, por exemplo, tentar excluir um job ou algo assim. Aqui vamos ter acesso fácil ao banco de dados. Então, com jobs, você provavelmente não quer ficar mexendo muito, mas se você já cometeu um erro e precisa editar os argumentos de um job ou mudar a prioridade ou algo assim, você tem acesso a isso no seu banco de dados, e poderia fazer isso se precisasse. Então essa é uma ferramenta bem interessante. O que é ótimo é que não precisamos de outro serviço em execução ou nada do tipo.10:20 Está ali, disponível para nós, no nosso banco de dados, e não requer, sabe, Redis ou outra coisa. Outra coisa interessante que eu queria destacar é que ele tem um plugin para o Puma. Então, nas suas aplicações Rails, se você não quiser executar isso como um processo separado, isso é um recurso interessante que podemos usar. Muitos de nós hoje têm Procfiles e usam bundling de CSS e JS ou algo assim, então acabamos tendo que executar vários processos.10:48 Se entrarmos no VS Code, podemos abrir config/puma.rb, e aqui, no final, ao lado de plugin :tmp_restart, que escuta o arquivo tmp restart ser tocado e reinicia o Rails, também podemos adicionar esse plugin. Quando o Puma inicia, ele também vai executar o Solid Queue, e quando o Puma é encerrado, ele também vai parar o Solid Queue. Então aqui você pode ver que, quando iniciamos nossa aplicação Rails com rails server, recebemos muitos logs dos processos do Solid Queue monitorando o banco de dados. Por padrão, ele verifica a cada 100 milissegundos, mais ou menos, algo como 0,1 segundo.11:30 Eu acho que esse era o padrão que eu vi no código antes. Então isso vai fazer várias consultas ao seu banco de dados, mas não com tanta frequência, porque seus bancos de dados são super performáticos, e ele só está de olho neles. Então, quando você enfileira um job, deve levar cerca de um décimo de segundo antes de ele começar a executar e ser detectado. Então isso vai ser muito rápido e performático, e vai simplesmente funcionar ao lado de tudo mais. E podemos fazer Ctrl+C, o Puma vai encerrar o Solid Queue e também vai encerrar a aplicação Rails, tudo em um único processo, o que eu achei super útil como recurso, se você não estiver usando um Procfile e já gerenciando processos separados.12:15 Isso é bom e já vem embutido. Isso sempre foi algo em que, se você faz deploy do Sidekiq, você realmente quer que ele esteja em execução e monitorado por outra coisa, e agora essa é uma boa forma de fazer isso. E eu acho que talvez até o Sidekiq consiga fazer isso hoje em dia também. Mas essa foi uma introdução rápida ao Solid Queue. Não há muitos recursos nele, porque é basicamente transparente por trás dos bastidores.12:39 Você precisa executar um processo, adicionar algumas tabelas ao seu banco de dados, e está tudo certo. É basicamente isso. Ele já usa o backend, ou interface, do Active Job com o qual você já está acostumado. Então realmente não há nada para você fazer. Eu recomendo bastante dar uma olhada nisso.12:57 Eu sei que isso vai ser algo grande no futuro. Provavelmente vai ser incorporado em muitas aplicações, porque é simples e fácil usar o serviço de banco de dados que você já tem. Então é isso por este episódio. Espero que você tenha gostado. Se você tiver perguntas sobre o Solid Queue ou qualquer coisa assim, nos conte nos comentários abaixo.13:14 Vamos dar uma olhada e tentar responder.