Câu trả lời:
Có một cách thay thế đơn giản không yêu cầu bất kỳ sự phụ thuộc bên ngoài nào:
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
Bây giờ trong cây giám sát của bạn:
worker(MyApp.Periodically, [])
Process.send_after
vào chức năng riêng của mình để chức năng có thể được gọi từ cả hai init
và handle_info
?
:timer.send_interval
vẫn ổn nhưng hãy nhớ rằng khoảng thời gian sẽ không đổi. Vì vậy, hãy tưởng tượng bạn muốn làm một cái gì đó mỗi phút và, trong tương lai, bản thân công việc mất hơn một phút. Trong những trường hợp như vậy, bạn sẽ làm việc mọi lúc và hàng đợi tin nhắn của bạn sẽ không bị ràng buộc. Giải pháp trên sẽ luôn chờ khoảng thời gian nhất định sau khi hoàn thành công việc.
Lượng tử cho phép bạn tạo, tìm và xóa các công việc trong thời gian chạy.
Hơn nữa, bạn có thể chuyển các đối số cho hàm tác vụ khi tạo cronjob và thậm chí sửa đổi múi giờ nếu bạn không hài lòng với UTC.
Nếu ứng dụng của bạn đang chạy dưới dạng nhiều phiên bản riêng biệt (ví dụ Heroku), có bộ xử lý công việc được PostgreQuery hoặc Redis hỗ trợ, cũng hỗ trợ lập lịch tác vụ:
Oban: https://github.com/sorentwo/oban
Ví dụ: https://github.com/akira/exq
Bạn có thể sử dụng erlcron cho điều đó. Bạn sử dụng nó như thế nào
job = {{:weekly, :thu, {2, :am}},
{:io, :fwrite, ["It's 2 Thursday morning~n"]}}
:erlcron.cron(job)
A job
là một tuple 2 phần tử. Phần tử đầu tiên là một tuple đại diện cho lịch trình cho công việc và phần tử thứ hai là chức năng hoặc MFA (Mô-đun, Chức năng, Arity). Trong ví dụ trên, chúng tôi chạy :io.fwrite("It's 2 Thursday morning")
mỗi 2 giờ sáng thứ Năm.
Mong rằng sẽ giúp!
Tôi đã sử dụng thư viện lượng tử Quantum- Elixir .
Thực hiện theo các hướng dẫn dưới đây.
#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
]
Tất cả các thiết lập. Khởi động máy chủ bằng cách chạy bên dưới lệnh.
iex -S mix phoenix.server
Tôi thấy :timer.send_interval/2
hơi tiện dụng hơn khi sử dụng với GenServer
hơn Process.send_after/4
(được sử dụng trong câu trả lời được chấp nhận ).
Thay vì phải sắp xếp lại thông báo của bạn mỗi khi bạn xử lý nó, hãy :timer.send_interval/2
thiết lập một khoảng thời gian mà bạn nhận được một tin nhắn vô tận. Không cần phải gọi schedule_work()
như sử dụng câu trả lời được chấp nhận.
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
Cứ sau 1000 ms (tức là một lần một giây), IntervalServer.handle_info/2
sẽ được gọi, in hiện tại count
và cập nhật trạng thái của GenServer ( count + 1
), cung cấp cho bạn đầu ra như:
1
2
3
4
[etc.]
Ngoài việc sử dụng Process.send_after
, bạn cũng có thể sử dụng : timer.apply_interval .
Lượng tử là tuyệt vời, chúng tôi sử dụng nó trong công việc như là một thay thế cron với mặt trước phượng hoàng và chúng tôi cũng thêm các công việc trong thời gian thực rất gọn gàng.