สมมุติว่าฉันต้องการส่งอีเมลจำนวนมากหรือสร้างแผนผังไซต์ขึ้นใหม่หรืออะไรก็ตามทุกๆ 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
ดี แต่โปรดจำไว้ว่าช่วงเวลาจะคงที่ ลองจินตนาการว่าคุณต้องการทำบางสิ่งบางอย่างทุกนาทีและในอนาคตงานเองใช้เวลามากกว่าหนึ่งนาที ในกรณีเช่นนี้คุณจะทำงานตลอดเวลาและคิวข้อความของคุณจะขยายตัวไม่ จำกัด การแก้ปัญหาข้างต้นมักจะรอเวลาที่กำหนดหลังจากงานเสร็จสิ้น
Quantumให้คุณสร้างค้นหาและลบงานที่รันไทม์
นอกจากนี้คุณสามารถส่งผ่านข้อโต้แย้งไปยังฟังก์ชั่นงานเมื่อสร้าง cronjob และแม้แต่ปรับเปลี่ยนเขตเวลาหากคุณไม่พอใจกับ UTC
หากแอปของคุณทำงานเป็นอินสแตนซ์ที่แยกได้หลายรายการ (เช่น Heroku) มีตัวประมวลผลงานที่รองรับโดย PostgreSQL หรือ Redis ซึ่งรองรับการกำหนดเวลางาน:
โอบัน: https://github.com/sorentwo/oban
Exq: https://github.com/akira/exq
คุณสามารถใช้erlcronเพื่อสิ่งนั้นได้ คุณใช้มันเหมือน
job = {{:weekly, :thu, {2, :am}},
{:io, :fwrite, ["It's 2 Thursday morning~n"]}}
:erlcron.cron(job)
A job
คือ tuple 2 องค์ประกอบ องค์ประกอบแรกคือ tuple ที่แสดงกำหนดการสำหรับงานและองค์ประกอบที่สองคือฟังก์ชันหรือ MFA (โมดูล, ฟังก์ชัน, Arity) ในตัวอย่างข้างต้นเราเรียกใช้:io.fwrite("It's 2 Thursday morning")
ทุก ๆ วันจันทร์ถึงวันพฤหัสบดี
หวังว่าจะช่วย!
ผมใช้ห้องสมุดควอนตัมQuantum- ยาอายุวัฒนะ
ทำตามคำแนะนำด้านล่าง
#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
ทุกๆ 1,000 มิลลิวินาที (เช่นหนึ่งครั้งต่อวินาที) IntervalServer.handle_info/2
จะถูกเรียกพิมพ์ปัจจุบันcount
และอัปเดตสถานะของ GenServer ( count + 1
) เพื่อให้ผลลัพธ์เช่น:
1
2
3
4
[etc.]
นอกจากนี้การใช้งานProcess.send_after
นอกจากนี้คุณยังสามารถใช้: timer.apply_interval
Quantumนั้นยอดเยี่ยมเราใช้มันในที่ทำงานเพื่อทดแทน cron ด้วย front-end ของฟีนิกซ์และเรายังเพิ่มงานในแบบเรียลไทม์ซึ่งเป็นระเบียบมาก