2015-06-01 3 views
19

Ich möchte wiederholt die gleiche Sequenz von Operationen immer wieder neben einer Phoenix-Anwendung ausführen (ohne die gesamte Web-App abzustürzen, wenn etwas im Arbeiter bremst) und nicht wirklich weiß, ob ich einen GenServer verwenden soll , Elixirs Aufgaben, ein Agent oder etwas ganz anderes, worüber ich bisher noch nicht nachgedacht habe.Welches OTP-Verhalten sollte ich für eine "endlose" Wiederholung von Aufgaben verwenden?

Wenn ich meine Phoenix-App starte, sollte auch ein Worker starten, der periodisch einige Werte einer seriellen Verbindung abruft, sie über einen Phoenix-Kanal sendet, sie sammelt und dann den Median berechnet, den Median ausstrahlt über einen anderen Kanal und schreibt es in eine InfluxDB. Im Moment habe ich etwas (eine Art Arbeits) wie folgt aus:

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 

Ich fange nur alles, was OTP Zeug, um herauszufinden, und hoffen, dass jemand von euch könnte mich in die richtige Richtung stolpern helfen hier.

Antwort

31

Sie sollten eine GenServer verwenden, die ihnen Nachrichten nach x Sekunden (60 Sekunden im Beispiel unten) sendet:

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

Warum nicht eine Aufgabe, die seine Sachen tut periodisch in einer Endlosschleife (möglicherweise durch Strom angetrieben. Intervall oder Stream.wiederholt)? Wenn dies nur ein periodischer Pull ist, der die gezogenen Daten weiter zum System weiterleitet, muss es nicht unbedingt ein GenServer sein, richtig. Die Aufgabe ist immer noch OTP-konform und für mich scheint es einfacher für den Job zu sein. – sasajuric

+4

Der Grund ist, dass Task keine Systemmeldungen empfangen kann. Wir wollen Stream und Freunde darauf aufmerksam machen, aber es ist nicht in 1.0 und wird möglicherweise nur in 1.3 sein. –

+1

Sie möchten auch, dass Ihre Supervisors in der Lage sind, den Mitarbeiter, der die periodische Arbeit erledigt, neu zu starten, anstatt den Infinite Stream den aktuellen Prozess abbrechen zu lassen, wenn etwas schief geht. – Letseatlunch

Verwandte Themen