Nehmen wir also an, ich möchte alle 4 Stunden ein paar E-Mails senden oder eine Sitemap oder was auch immer neu erstellen. Wie würde ich das in Phoenix oder nur mit Elixir machen?
Nehmen wir also an, ich möchte alle 4 Stunden ein paar E-Mails senden oder eine Sitemap oder was auch immer neu erstellen. Wie würde ich das in Phoenix oder nur mit Elixir machen?
Antworten:
Es gibt eine einfache Alternative, die keine externen Abhängigkeiten erfordert:
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
Jetzt in Ihrem Überwachungsbaum:
worker(MyApp.Periodically, [])
Process.send_after
in eine eigene Funktion zu wechseln, damit die Funktion von beiden init
und aufgerufen werden kann handle_info
?
:timer.send_interval
ist in Ordnung, aber denken Sie daran, dass die Intervalle konstant bleiben. Stellen Sie sich vor, Sie möchten jede Minute etwas tun, und in Zukunft dauert die Arbeit selbst mehr als eine Minute. In solchen Fällen würden Sie die ganze Zeit arbeiten und Ihre Nachrichtenwarteschlange würde unbegrenzt wachsen. Die obige Lösung wartet immer die angegebene Zeit, nachdem die Arbeit erledigt ist.
Mit Quantum können Sie Jobs zur Laufzeit erstellen, suchen und löschen.
Darüber hinaus können Sie beim Erstellen eines Cronjobs Argumente an die Taskfunktion übergeben und sogar die Zeitzone ändern, wenn Sie mit UTC nicht zufrieden sind.
Wenn Ihre App als mehrere isolierte Instanzen ausgeführt wird (z. B. Heroku), gibt es Jobprozessoren, die von PostgreSQL oder Redis unterstützt werden und die auch die Aufgabenplanung unterstützen:
Oban: https://github.com/sorentwo/oban
Beispiel: https://github.com/akira/exq
Sie können dafür Erlcron verwenden . Du benutzt es gerne
job = {{:weekly, :thu, {2, :am}},
{:io, :fwrite, ["It's 2 Thursday morning~n"]}}
:erlcron.cron(job)
A job
ist ein 2-Element-Tupel. Das erste Element ist ein Tupel, das den Zeitplan für den Job darstellt, und das zweite Element ist die Funktion oder ein MFA (Modul, Funktion, Arität). Im obigen Beispiel laufen wir :io.fwrite("It's 2 Thursday morning")
jeden Donnerstag um 2 Uhr morgens.
Hoffentlich hilft das!
Ich habe die Quantenbibliothek Quantum-Elixir verwendet .
Befolgen Sie die nachstehenden Anweisungen.
#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
]
Alles bereit. Starten Sie den Server, indem Sie den folgenden Befehl ausführen.
iex -S mix phoenix.server
Ich finde es :timer.send_interval/2
etwas ergonomischer, mit einem zu arbeiten GenServer
als Process.send_after/4
(in der akzeptierten Antwort verwendet ).
Anstatt Ihre Benachrichtigung jedes Mal neu planen zu müssen, legen Sie :timer.send_interval/2
ein Intervall fest, in dem Sie endlos eine Nachricht erhalten - Sie müssen nicht weiter anrufen, schedule_work()
wie es die akzeptierte Antwort verwendet.
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
Alle 1000 ms (dh einmal pro Sekunde) IntervalServer.handle_info/2
wird aufgerufen, der aktuelle count
Wert gedruckt und der Status des GenServers aktualisiert ( count + 1
), sodass Sie folgende Ausgaben erhalten:
1
2
3
4
[etc.]
Neben der Verwendung Process.send_after
können Sie auch Folgendes verwenden : timer.apply_interval .
Quantum ist großartig, wir verwenden es bei der Arbeit als Cron-Ersatz mit einem Phoenix-Frontend und wir fügen auch Jobs in Echtzeit hinzu, was sehr ordentlich ist.