Qual a verdade do Sidekiq?
Normalmente, quando falamos sobre a arquitetura padrão (MVC, RAILS + HEROKU)
temos uma longa caminhada de tráfego. Durante toda essa caminhada (request até response)
bloqueamos nossa UX de retornar absolutamente qualquer coisa
O processo padrão do heroku que lida com essas requisições também é bloqueado. Se a aplicação
demorar mais de 30 segundos, ela encerra a conexão te retornando um TIMED OUT.
O Heroku faz isso, pois o que você verdadeiramente paga no Heroku
são os números de processamentos de aplicações (conhecidos como Dynos).
Existem DOIS TIPOS de Dynos:
- Web Dyno
- Worker Dyno
Em alto nível, um Dyno é um processo que roda na sua aplicação Rails.
Um Web Dyno, é um subtópico especialmente feito para lidar com tráfego web.
O Heroku coloca todos os Web Dynos atrás de algo que chamamos de "Routing Mash"
|----------------------------------------------------------------------------|
| Request -> HTTP Reverse Proxy -> HTTP Cache -> Routing Mash -> Dyno Grid |
|----------------------------------------------------------------------------|
No caso, ao invés de demorar 30 segundos, podemos adicionar o request dentro de uma lista
e retornar imediatamente pro usuário uma mensagem do tipo "Adicionamos sua requisição na nossa lista"
Basicamente, é um key value sem precisar modelar os dados com um banco sequencial (Redis)
Então, no caso, ao invés de chamar o model.rb para gerar o report, colocamos
uma mensagem na fila e ele retornará imediatamente ao usuário. Enquanto isso,
nossa fila também se comunica com um worker.
Um worker é um objeto em Ruby que está num processo diferente do que está no mesmo
deploy do Web Request.
Pelo fato do serviço estar separado da Web, ele não está registrado nas regras de 30 segundos
ou seja, quando o Worker finalizar o processo, podemos tomar alguma decisão com os dados.
Como, por exemplo, mandar um email pro usuário ou subir no Bucket.
Normalmente, adicionamos os dados no cache, para que o usuário veja na Web sem precisar recalcular.
Comumente, sempre usamos o Redis com o Sidekiq.
Redis -> Banco de Dados
Sidekiq -> Lib para manusear os processos e aplicações Rails
Ps: O Sidekiq vem com sua própria UI, que é feita em Sinatra, logo você precisa importar o Sinatra.
Exemplos:
#routes.rb
require 'sidekiq/web'
mount Sidekiq::Web => "/sidekiq"
$ mkdir workers
$ cd workers && touch report_worker.rb
#report_worker.rb
class ReportWorker
include Sidekiq::worker
sidekiq_options retry:false
def perform(start_date, end_date)
puts("#{start_date} até #{end_date}")
end
end
No caso acima, usamos o retry: false pois, por padrão, se o worker falhar, ele
tentará executar o processo até dar certo.
Todo Sidekiq Worker tem um método chamado "Perform". Ele que é chamado
quando algo da fila é processado.
Você também pode colocar parâmetros na fila!
#controller.rb
def report
ReportWorker.perform_async("01-01-2020", "01-01-2021")
render text: "Request Comum"
end
E por último, para sabermos pelo menos como funciona a execução do Sidekiq,
para rodarmos ele no terminal, usamos:
$ sidekiq -c 1
Ele roda todos os processos com uma Thresh (padrão), Mas você pode aumentar
esse número.
Por padrão, ele sabe que a fila está no Redis, pois ele lê a porta 6379 (Porta padrão do Redis)
Tá Diego, mas como eu posso dar deploy disso na núvem?
Eu te respondo, meu caro:
Na sua aplicação Rails, faça o seguinte:
#procfile
reportworker: bundle sidekiq -c 1
Assim, ele irá executar o mesmo comando que fizemos no nosso terminal local.