Alors disons que je veux envoyer un tas d'e-mails ou recréer un plan du site ou quoi que ce soit toutes les 4 heures, comment ferais-je à Phoenix ou tout simplement avec Elixir?
Alors disons que je veux envoyer un tas d'e-mails ou recréer un plan du site ou quoi que ce soit toutes les 4 heures, comment ferais-je à Phoenix ou tout simplement avec Elixir?
Réponses:
Il existe une alternative simple qui ne nécessite aucune dépendance externe:
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
Maintenant dans votre arbre de supervision:
worker(MyApp.Periodically, [])
Process.send_after
à sa propre fonction pour que la fonction puisse être appelée à partir des deux init
et handle_info
?
:timer.send_interval
va bien, mais gardez à l'esprit que les intervalles seront constants. Imaginez donc que vous voulez faire quelque chose à chaque minute et, à l'avenir, le travail lui-même prendra plus d'une minute. Dans de tels cas, vous travailleriez tout le temps et votre file d'attente de messages augmenterait sans limite. La solution ci-dessus attendra toujours la période donnée une fois le travail terminé.
Quantum vous permet de créer, rechercher et supprimer des travaux lors de l'exécution.
De plus, vous pouvez passer des arguments à la fonction de tâche lors de la création d'un cronjob et même modifier le fuseau horaire si vous n'êtes pas satisfait de l'UTC.
Si votre application s'exécute en tant que plusieurs instances isolées (par exemple Heroku), il existe des processeurs de travaux soutenus par PostgreSQL ou Redis, qui prennent également en charge la planification des tâches:
Oban: https://github.com/sorentwo/oban
Exq: https://github.com/akira/exq
Vous pouvez utiliser erlcron pour cela. Vous l'utilisez comme
job = {{:weekly, :thu, {2, :am}},
{:io, :fwrite, ["It's 2 Thursday morning~n"]}}
:erlcron.cron(job)
A job
est un tuple à 2 éléments. Le premier élément est un tuple qui représente la planification du travail et le deuxième élément est la fonction ou un MFA (Module, Function, Arity). Dans l'exemple ci-dessus, nous courons :io.fwrite("It's 2 Thursday morning")
tous les 2h du jeudi.
J'espère que cela pourra aider!
J'ai utilisé la bibliothèque Quantum Quantum- Elixir .
Suivez les instructions ci-dessous.
#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
]
Tout est prêt. Démarrez le serveur en exécutant la commande ci-dessous.
iex -S mix phoenix.server
Je trouve un :timer.send_interval/2
peu plus ergonomique à utiliser avec un GenServer
que Process.send_after/4
(utilisé dans la réponse acceptée ).
Au lieu d'avoir à replanifier votre notification chaque fois que vous la manipulez, :timer.send_interval/2
configurez un intervalle pendant lequel vous recevez un message à l'infini - pas besoin de continuer à appeler schedule_work()
comme la réponse acceptée l'utilise.
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
Toutes les 1000 ms (c.-à-d., Une fois par seconde), IntervalServer.handle_info/2
sera appelé, imprimera le courant count
et mettra à jour l'état ( count + 1
) du GenServer , vous donnant une sortie comme:
1
2
3
4
[etc.]
Outre l'utilisation Process.send_after
, vous pouvez également utiliser : timer.apply_interval .