Entonces, digamos que quiero enviar un montón de correos electrónicos o recrear el mapa del sitio o lo que sea cada 4 horas, ¿cómo haría eso en Phoenix o simplemente con Elixir?
Entonces, digamos que quiero enviar un montón de correos electrónicos o recrear el mapa del sitio o lo que sea cada 4 horas, ¿cómo haría eso en Phoenix o simplemente con Elixir?
Respuestas:
Existe una alternativa simple que no requiere dependencias externas:
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
Ahora en su árbol de supervisión:
worker(MyApp.Periodically, [])
Process.send_after
a su propia función para que la función pueda llamarse desde ambos init
y handle_info
?
:timer.send_interval
está bien, pero tenga en cuenta que los intervalos serán constantes. Imagine que quiere hacer algo cada minuto y, en el futuro, el trabajo en sí mismo lleva más de un minuto. En tales casos, estaría trabajando todo el tiempo y su cola de mensajes crecería sin límites. La solución anterior siempre esperará el período dado después de que se realice el trabajo.
Quantum le permite crear, encontrar y eliminar trabajos en tiempo de ejecución.
Además, puede pasar argumentos a la función de tarea al crear un cronjob e incluso modificar la zona horaria si no está satisfecho con UTC.
Si su aplicación se ejecuta como varias instancias aisladas (por ejemplo, Heroku), hay procesadores de trabajo respaldados por PostgreSQL o Redis, que también admiten la programación de tareas:
Oban: https://github.com/sorentwo/oban
Exq: https://github.com/akira/exq
Puedes usar erlcron para eso. Lo usas como
job = {{:weekly, :thu, {2, :am}},
{:io, :fwrite, ["It's 2 Thursday morning~n"]}}
:erlcron.cron(job)
A job
es una tupla de 2 elementos. El primer elemento es una tupla que representa la programación del trabajo y el segundo elemento es la función o un MFA (Módulo, Función, Aridad). En el ejemplo anterior, corremos :io.fwrite("It's 2 Thursday morning")
cada 2am del jueves.
¡Espero que ayude!
Usé la biblioteca Quantum Quantum -Elixir .
Siga las instrucciones a continuación.
#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
]
Todo listo. Inicie el servidor ejecutando el siguiente comando.
iex -S mix phoenix.server
Encuentro un :timer.send_interval/2
poco más ergonómico para usar con un GenServer
que Process.send_after/4
(usado en la respuesta aceptada ).
En lugar de tener que reprogramar su notificación cada vez que la maneja, :timer.send_interval/2
establece un intervalo en el que recibe un mensaje sin cesar, sin necesidad de seguir llamando schedule_work()
como lo usa la respuesta aceptada.
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
Cada 1000 ms (es decir, una vez por segundo), IntervalServer.handle_info/2
se llamará, imprimirá el actual count
y actualizará el estado del GenServer ( count + 1
), dándole un resultado como:
1
2
3
4
[etc.]
Además de usar Process.send_after
, también puedes usar : timer.apply_interval .
Quantum es genial, lo usamos en el trabajo como un reemplazo de cron con un front-end de Phoenix y también agregamos trabajos en tiempo real cual es muy bueno.