У меня есть рабочий процесс, который включает в себя пробуждение каждые 30 секунд или около того и опрос базы данных для обновлений, принятие мер по этому вопросу, а затем возврат к сну. Отказ от того, что опрос базы данных не масштабируется и другие подобные проблемы, каков наилучший способ структурирования этого рабочего процесса с помощью диспетчеров, рабочих, задач и т.д.?
Я выложу несколько идей, которые у меня были, и мои мысли за/против. Пожалуйста, помогите мне разобраться в самом подходе Elixir-y. (Я все еще очень новичок в Elixir, кстати.)
1. Бесконечный вызов через функцию вызова
Просто поставьте простой рекурсивный цикл, например:
def do_work() do
# Check database
# Do something with result
# Sleep for a while
do_work()
end
Я видел что-то подобное, следуя инструкциям по созданию веб-искателя.
Одна из проблем, которые я имею здесь, - бесконечная глубина стека из-за рекурсии. Разве это не приведет к переполнению стека, так как мы рекурсируем в конце каждого цикла? Эта структура используется в стандартном руководстве Elixir для задач, поэтому я, вероятно, ошибаюсь в проблеме.
Обновление. Как упоминалось в ответах, рекурсия хвоста в Elixir означает, что переполнение стека здесь не проблема, Циклы, которые называют себя в конце, являются принятым способом бесконечного цикла.
2. Используйте задачу, перезагрузите каждое время
Основная идея здесь - использовать задачу, которая запускается один раз и затем выходит, но сопрягайте ее с Supervisor с стратегией перезапуска one-to-one
, поэтому она запускается каждый раз после ее завершения. Задача проверяет базу данных, спит, а затем завершает работу. Супервизор видит выход и запускает новый.
Это дает возможность жить внутри Супервизора, но это похоже на злоупотребление Супервизора. Он используется для циклирования в дополнение к захвату ошибок и перезапуску.
(Примечание. Возможно, что-то еще можно сделать с Task.Supervisor, в отличие от обычного супервизора, и я просто не понимаю его.)
3. Задача + Бесконечная петля рекурсии
В принципе, объедините 1 и 2, так что это задача, которая использует бесконечный цикл рекурсии. Теперь он управляется Супервизором и перезагружается, если он разбился, но не перезапускается снова и снова как нормальная часть рабочего процесса. В настоящее время это мой любимый подход.
4. Другое?
Я беспокоюсь, что есть некоторые фундаментальные структуры OTP, которые мне не хватает. Например, я знаком с Agent и GenServer, но я недавно наткнулся на Task. Может быть, есть какой-то Looper для именно этого случая или какой-то прецедент Task.Supervisor, который его охватывает.