Este artigo contém partes (traduzidas) do artigo original de Brent Coiler.
Estou trabalhando em um projeto onde preciso que uma determinada tarefa seja realizada a cada determinado tempo, que não pode ser um resultado de uma requisição de um usuário, por isso deve ser feito fora das requisições padrões, ou seja em background.
Geralmente quando falamos nesse tipo de processo, pensamos em BackgrounDrb ou Starling/Workling. Estas ferramentas realmente são muito boas no que fazem, mas eu preciso de algo mais simples.
Eu não preciso de filas de tarejas, ou nada do tipo. I preciso apenas uma ou mais tarefas para gerenciar. I apenas quero algo que eu diga, “Um dia, faça [tarefa]“, e isso é tudo.
Então comecei a procurar mas não demorei muito pra achar, ontem falei sobre o novo Ruby Inside Brasil e nele encontrei a resposta pra o que precisava no artigo sobre o Rufus Scheduler.
E éra justamente esse carinha que eu estava procurando, simples, não precisa de banco de dados nem um processo separadado para ele. Apenas uma tarefa que é chamada por fora do nosso código Ruby/Rails.
Então vamos lá para a configuração…
Primeiramente instale a gem:
sudo gem install rufus-scheduler
Então eu criei um arquivo chamado task_scheduler.rb na pasta config/initializers. Dentro deste arquivo é onde acontece a mágica. É onde vai tudo, Está preparado? Lá vai…
scheduler = Rufus::Scheduler.start_new
scheduler.every("1m") do
DailyDigest.send_digest!
end
Sim, é só isso. Verdade.
Eu estava desconfiado até eu iniciar o servidor/aplicação e ver que ele estava enviando os e-mails. No estado atual ele estava enviando o e-mail a cada minuto, o que não é bem o que quero. Felizmente o Rufus Scheduler dispõe de várias formas de agendar tarefas, veja mais detalhes aqui. Então quando estava pronto eu mudei o código pra algo mais no estilo de um cron-job.
scheduler = Rufus::Scheduler.start_new
# Envia o email todo dia ao meio-dia
scheduler.cron("0 12 * * *") do
DailyDigest.new.send_digest!
end
Também é possível usar scheduler.in ou scheduler.at para uma tarefa de uma única vez, para ser rodada no futuro. Veja mais detalhes aqui
Então agora você já sabe como fazer. Agendamento de tarefas super simples no Rails. Não tinha como ser mais fácil
[UPDATE]
Em resposta a dúvida do nosso amigo Hamilton, para parar uma tarefa já iniciada, fazemos o seguinte:
job = scheduler.in '2d', :tags => 'admin' do
run_backlog_cleaning()
end
# depois ...
job.unschedule
# ou
scheduler.unschedule(job.job_id)