それでは、大量のメールを送信したり、サイトマップを4時間ごとに再作成したりしたいとしましょう。フェニックスで、またはElixirだけでどうすればよいでしょうか。
それでは、大量のメールを送信したり、サイトマップを4時間ごとに再作成したりしたいとしましょう。フェニックスで、またはElixirだけでどうすればよいでしょうか。
回答:
外部依存関係を必要としない簡単な代替手段があります:
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
今あなたの監督ツリーで:
worker(MyApp.Periodically, [])
Process.send_after
の機能が両方から呼び出すことができるように、独自の機能へinit
とhandle_info
?
:timer.send_interval
は問題ありませんが、間隔は一定であることを覚えておいてください。ですから、毎分何かを実行したいとし、将来的には、作業自体が1分以上かかると想像してください。そのような場合、あなたはいつも働いていて、メッセージキューは無制限に大きくなります。上記のソリューションは、作業が完了した後、常に指定された期間待機します。
Quantumでは、実行時にジョブを作成、検索、削除できます。
さらに、cronjobの作成時にタスク関数に引数を渡し、UTCに満足できない場合はタイムゾーンを変更することもできます。
アプリが複数の分離されたインスタンス(Herokuなど)として実行されている場合、PostgreSQLまたはRedisによってサポートされるジョブプロセッサがあり、タスクスケジューリングもサポートしています。
オーバン:https : //github.com/sorentwo/oban
例:https : //github.com/akira/exq
Toniq:https : //github.com/joakimk/toniq
Verk:https : //github.com/edgurgel/verk
そのためにerlcronを使用できます。あなたはそれを好きです
job = {{:weekly, :thu, {2, :am}},
{:io, :fwrite, ["It's 2 Thursday morning~n"]}}
:erlcron.cron(job)
A job
は2要素のタプルです。最初の要素はジョブのスケジュールを表すタプルで、2番目の要素は関数またはMFA(Module、Function、Arity)です。上記の例では、:io.fwrite("It's 2 Thursday morning")
毎週木曜日の午前2時に実行されます。
お役に立てば幸いです。
QuantumライブラリQuantum- Elixirを使用しました。
以下の指示に従ってください。
#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
]
準備完了。以下のコマンドを実行してサーバーを起動します。
iex -S mix phoenix.server
私は(承認された回答で使用されている)よりも:timer.send_interval/2
人間工学的に少し使いやすいと思います。GenServer
Process.send_after/4
通知を処理するたびにスケジュールを変更する代わりに:timer.send_interval/2
、メッセージを際限なく受信する間隔を設定しschedule_work()
ます。承認された回答のように電話をかけ続ける必要はありません。
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
1000ミリ秒ごと(つまり、1秒に1回)にIntervalServer.handle_info/2
呼び出され、current を出力しcount
、GenServerの状態(count + 1
)を更新して、次のような出力を提供します。
1
2
3
4
[etc.]
を使用する以外にProcess.send_after
、:timer.apply_intervalも使用できます。