Então, digamos que eu quero enviar um monte de e-mails ou recriar o mapa do site ou o que quer que seja a cada 4 horas, como eu faria isso em Phoenix ou apenas com o Elixir?
Então, digamos que eu quero enviar um monte de e-mails ou recriar o mapa do site ou o que quer que seja a cada 4 horas, como eu faria isso em Phoenix ou apenas com o Elixir?
Respostas:
Existe uma alternativa simples que não requer nenhuma dependência externa:
defmodule MyApp.Periodically do
use GenServer
def start_link do
GenServer.start_link(__MODULE__, %{})
end
def init(state) do
schedule_work() # Schedule work to be performed at some point
{:ok, state}
end
def handle_info(:work, state) do
# Do the work you desire here
schedule_work() # Reschedule once more
{:noreply, state}
end
defp schedule_work() do
Process.send_after(self(), :work, 2 * 60 * 60 * 1000) # In 2 hours
end
end
Agora na sua árvore de supervisão:
worker(MyApp.Periodically, [])
Process.send_after
para sua própria função, de modo que a função possa ser chamada de ambos init
e handle_info
?
:timer.send_interval
está bom, mas tenha em mente que os intervalos serão constantes. Imagine que você quer fazer algo a cada minuto e, no futuro, o trabalho em si leva mais de um minuto. Nesses casos, você estaria trabalhando o tempo todo e sua fila de mensagens aumentaria sem limites. A solução acima sempre aguardará o período especificado após o término do trabalho.
O Quantum permite criar, localizar e excluir trabalhos em tempo de execução.
Além disso, você pode passar argumentos para a função task ao criar um cronjob e até modificar o fuso horário se não estiver satisfeito com o UTC.
Se seu aplicativo estiver sendo executado como várias instâncias isoladas (por exemplo, Heroku), existem processadores de tarefas suportados pelo PostgreSQL ou Redis, que também suportam o agendamento de tarefas:
Oban: https://github.com/sorentwo/oban
Exq: https://github.com/akira/exq
Você pode usar erlcron para isso. Você usa como
job = {{:weekly, :thu, {2, :am}},
{:io, :fwrite, ["It's 2 Thursday morning~n"]}}
:erlcron.cron(job)
A job
é uma tupla de 2 elementos. O primeiro elemento é uma tupla que representa a programação do trabalho e o segundo elemento é a função ou um MFA (Módulo, Função, Arity). No exemplo acima, executamos a :io.fwrite("It's 2 Thursday morning")
cada 2 da manhã de quinta-feira.
Espero que ajude!
Eu usei a biblioteca Quantum Quantum- Elixir .
Siga as instruções abaixo.
#your_app/mix.exs
defp deps do
[{:quantum, ">= 1.9.1"},
#rest code
end
#your_app/mix.exs
def application do
[mod: {AppName, []},
applications: [:quantum,
#rest code
]]
end
#your_app/config/dev.exs
config :quantum, :your_app, cron: [
# Every minute
"* * * * *": fn -> IO.puts("Hello QUANTUM!") end
]
Tudo pronto. Inicie o servidor executando o comando abaixo.
iex -S mix phoenix.server
Acho :timer.send_interval/2
um pouco mais ergonômico para usar com a GenServer
que Process.send_after/4
(usado na resposta aceita ).
Em vez de ter que reagendar sua notificação cada vez que você a manipula, :timer.send_interval/2
configure um intervalo no qual você recebe uma mensagem sem parar - não é necessário continuar ligando schedule_work()
como a resposta aceita.
defmodule CountingServer do
use GenServer
def init(_) do
:timer.send_interval(1000, :update)
{:ok, 1}
end
def handle_info(:update, count) do
IO.puts(count)
{:noreply, count + 1}
end
end
A cada 1000 ms (ou seja, uma vez por segundo), IntervalServer.handle_info/2
será chamado, imprima a corrente count
e atualize o estado do GenServer ( count + 1
), fornecendo uma saída como:
1
2
3
4
[etc.]
Além de usar Process.send_after
, você também pode usar : timer.apply_interval .
O Quantum é ótimo, usamos no trabalho como uma substituição do cron com um front-end da Phoenix e também adicionamos trabalhos em tempo real, o que é muito interessante.