Ich weiß, dass es ziemlich unmöglich ist, dass ein GenServer-Prozess sich selbst aufruft, weil Sie im Wesentlichen einen Deadlock haben. Aber ich bin neugierig, ob es einen bevorzugten Weg gibt, so etwas zu tun.Ordnungsgemäße Methode zum Strukturieren von GenServer-Aufrufe an self
Angenommen, das folgende Szenario: Ich habe eine Warteschlange, aus der ich Sachen herauspoppe. Wenn die Warteschlange jemals leer ist, möchte ich sie wieder auffüllen. Ich könnte es so strukturieren:
def handle_call(:refill_queue, state) do
new_state = put_some_stuff_in_queue(state)
{:reply, new_state}
end
def handle_call(:pop, state) do
if is_empty_queue(state) do
GenServer.call(self, :refill_queue)
end
val,new_state = pop_something(state)
{:reply, val, new_state}
end
Das große Problem hier ist, dass dies Deadlock wird, wenn wir versuchen, die Warteschlange aufzufüllen. Eine Lösung, die ich in der Vergangenheit verwendet habe, ist die Verwendung von cast
mehr, damit es nicht blockiert. Wie so (call
für Nachfüllung cast
ändern)
def handle_cast(:refill_queue, state) do
Aber in diesem Fall, ich denke, es wird nicht funktionieren, da die Asynchron-Guss die Warteschlange zum Nachfüllen im pop
Fall zurückkehren könnte, bevor sie tatsächlich die Warteschlange Bedeutung Füllung Ich werde versuchen, eine leere Warteschlange zu löschen. Die Kernfrage ist: Wie ist der beste Weg, damit umzugehen? Ich nehme an, die Antwort ist nur put_some_stuff_in_queue
direkt innerhalb der pop
Anruf anrufen, aber ich wollte überprüfen. Mit anderen Worten, es scheint, als ob das Richtige zu tun ist, machen handle_call
und handle_cast
so einfach wie möglich und im Grunde nur Wrapper zu anderen Funktionen, wo die eigentliche Arbeit passiert. Dann erstellen Sie so viele handle_*
Funktionen, wie Sie alle möglichen Fälle abdecken müssen, mit denen Sie beschäftigen werden, anstatt handle_call(:foo)
wiederum handle_call(:bar)
anrufen.
Ich würde 'refill_queue' eine Plain-Funktion machen und sie von' handle_call (: pop) 'aufrufen, wenn sie synchron sein muss. Andernfalls haben Sie mehrere Möglichkeiten, async zu bearbeiten (senden Sie eine andere Nachricht an self, haben Sie einen anderen Prozess, der das Nachfüllen erledigt, etc.) –
Sie sollten sich die [GenStage] (http://elixir-lang.org/blog) anschauen/2016/07/14/annouting-genstage /), klingt, als ob es die Funktionalität bietet, nach der Sie suchen. – mudasobwa