2015-06-01 2 views
19

Я хочу повторно запускать одну и ту же последовательность операций снова и снова рядом с приложением Phoenix (без сбоев в работе всего веб-приложения, если что-то тормозит в рабочем месте, конечно) и не знаю, как я должен использовать GenServer , Задачи Эликсира, Агент или что-то совершенно другое, о котором я до сих пор не думал.Какое поведение OTP следует использовать для «бесконечного» повторения задач?

Когда я запускаю приложение Phoenix, рабочий должен также запускать, что периодически вытягивает некоторые значения последовательного соединения, транслирует их по каналу Phoenix, собирает их до тех пор, пока не будет достигнут @save_interval, а затем вычислит медиану, через другой канал и записывает его в InfluxDB. Сейчас у меня есть что-то (вид работы), как это:

def do_your_thing(serial_pid) do 
    Stream.interval(@interval_live) 
    |> get_new_values_from_serial(serial_pid) 
    |> broadcast!("live-channel:#{@name}") 
    |> Enum.take(div(@interval_save, @interval_live)) 
    |> calculate_medians() 
    |> broadcast!("update-channel:#{@name}") 
    |> write_to_database() 

    do_your_thing(serial_pid) # repeat 
end 

Я только начинаю понять все, что OTP вещи, и надеюсь, что кто-то из вас может помочь мне наткнуться в правильном направлении здесь.

ответ

31

Вы должны использовать GenServer, который рассылает себя сообщения после х секунд (60 секунд в примере ниже):

defmodule MyApp.Worker do 
    use GenServer 

    def start_link() do 
    GenServer.start_link(__MODULE__, []) 
    end 

    def init([]) do 
    schedule_work() 
    {:ok, []} 
    end 

    def handle_info(:work, state) do 
    state = do_work(state) 
    schedule_work() 
    {:noreply, state} 
    end 

    defp do_work(state) do 
    # Do your work here and return state 
    end 

    defp schedule_work do 
    Process.send_after(self(), :work, 60_000) 
    end 
end 
+2

Почему не задача, которая делает свои вещи периодически в бесконечном цикле (возможно питание от потока. интервал или поток.) Если это всего лишь периодическое нажатие, которое направляет выталкиваемые данные дальше в систему, на самом деле это не обязательно должен быть GenServer. Задача по-прежнему совместима с OTP, и для меня это кажется более простым для работы. – sasajuric

+4

Причина в том, что Task не может получать системные сообщения. Мы хотим, чтобы Stream и друзья знали об этом, но он не в 1.0 и, возможно, будет только в версии 1.3. –

+1

Также вы можете захотеть, чтобы ваши наблюдатели могли перезапустить рабочего, выполняющего периодическую работу, а не просто позволить бесконечному потоку сбой текущего процесса, если что-то пойдет не так. – Letseatlunch

Смежные вопросы