Допустим, я хочу отправлять кучу электронных писем или воссоздавать карту сайта или что-то еще каждые 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
Пример: https://github.com/akira/exq
Вы можете использовать erlcron для этого. Вы используете это как
job = {{:weekly, :thu, {2, :am}},
{:io, :fwrite, ["It's 2 Thursday morning~n"]}}
:erlcron.cron(job)
A job
- это двухэлементный кортеж. Первый элемент - это кортеж, который представляет расписание для задания, а второй элемент - это функция или 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 мс (т. Е. Раз в секунду) IntervalServer.handle_info/2
будут вызываться, распечатывать текущее значение count
и обновлять состояние GenServer ( count + 1
), давая вам вывод, подобный следующему:
1
2
3
4
[etc.]
Помимо использования Process.send_after
, вы также можете использовать : timer.apply_interval .
Quantum - это здорово, мы используем его на работе как замену cron на front-end феникса, а также добавляем задания в реальном времени, что очень удобно.