Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Which OTP behavior should I use for an "endless" repetition of tasks?

Tags:

I want to repeatedly run the same sequence of operations over and over again next to a Phoenix application (without crashing the whole web-app if something brakes in the worker of course) and don't really know wether I should use a GenServer, Elixir's Tasks, an Agent or something completely different I haven't thought about so far.

When I start my Phoenix app a worker should start as well, that periodically pulls some values of a serial-connection, broadcasts them through a Phoenix channel, collects them until @save_interval is reached and then calculates the median, broadcasts that median via a different channel and writes it to an InfluxDB. Right now I have something (kind of working) like this:

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 

I'm only starting to figure all that OTP stuff out and hope someone of you could help me stumble into the right direction here.

like image 671
optikfluffel Avatar asked Jun 01 '15 08:06

optikfluffel


1 Answers

You should use a GenServer that sends itself messages after x seconds (60 seconds in the example below):

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 
like image 98
José Valim Avatar answered Dec 09 '22 17:12

José Valim