ElixirまたはPhoenixフレームワークでコードを数時間ごとに実行するようにスケジュールするにはどうすればよいですか?


194

それでは、大量のメールを送信したり、サイトマップを4時間ごとに再作成したりしたいとしましょう。フェニックスで、またはElixirだけでどうすればよいでしょうか。

回答:


386

外部依存関係を必要としない簡単な代替手段があります:

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, [])

167
この言語を愛さないのは不可能です:)
NoDisplayName '19

3
このファイルはどこに置くべきですか?フェニックスプロジェクトのlib /ディレクトリの下?テストはどこに行って、定期的にテストするのですか?
EugZol 2015年

9
libでは、実行時間が長いためです。「test / my_app / periodically_test.exs」など、意味のあるものであれば何でもテストを実行できます。
ホセ・Valim

2
移動しないように、任意の特定の理由Process.send_afterの機能が両方から呼び出すことができるように、独自の機能へinithandle_info
Ryan Bigg 2016年

24
@CodyPoll :timer.send_intervalは問題ありませんが、間隔は一定であることを覚えておいてください。ですから、毎分何かを実行したいとし、将来的には、作業自体が1分以上かかると想像してください。そのような場合、あなたはいつも働いていて、メッセージキューは無制限に大きくなります。上記のソリューションは、作業が完了した、常に指定された期間待機します。
ホセ・Valim

32

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


1
それを必要としない単純なタスクの多くにとってはやり過ぎになると思いますが、とにかく答えてくれてありがとう。
NoDisplayName

利用可能なライブラリのリストを用意しておくことは私にとって役に立ちました。
sheldonkreger 2016

24

そのために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時に実行されます。

お役に立てば幸いです。


うん、何もないよりはましだ、ありがとう。私はしばらくの間、質問に答えずに残します。おそらく他の提案があるでしょう
NoDisplayName '19

4
どういたしまして!ありますgithub.com/c-rack/quantum-elixirご希望の場合は、エリキシルlibにある
Gjaldon

6

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 

これはcronjobsのようなものです
DarckBlezzer

1

私は(承認された回答で使用されている)よりも:timer.send_interval/2人間工学的に少し使いやすいと思います。GenServerProcess.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.]


0

Quantumは素晴らしいです。私たちは仕事でそれをphoenixフロントエンドでのcronの置き換えとして使用し、ジョブをリアルタイムで追加することもできます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.