Wie machst du selektives Empfangen in gen_servers?

7

Ich habe die meisten meiner Apps auf OTP-Verhalten portiert, aber ich stecke fest. Ich kann nicht herausfinden, wie man mit einem gen_server selektiv empfängt. Wenn keine der Callback-Funktionsklauseln mit einer Nachricht übereinstimmt, wird die Nachricht nicht zurück in das Postfach geschrieben, und es wird ein Fehler ausgegeben!

Nun, überall, wo ich hingehe, loben die Leute selektiv. Überall, wo ich hingehe, loben die Leute OTP. Kann es wirklich wahr sein, dass du beides nicht gleichzeitig haben kannst? Scheint das nicht wie ein großer, korrigierbarer Mangel?

Wie gehen Erlang Programmierer damit um?

BEARBEITEN (reagiert auf den Kommentar von zed):

Hier ist ein Beispiel, in dem ich eine Liste von Ganzzahlen sehen möchte, die in sortierter Reihenfolge gedruckt werden:

%Vor%

Natürlich gibt es in meiner echten App Timer-Verzögerungen und die Nachrichten, die in der Reihenfolge verarbeitet werden müssen, sind mit anderen Nachrichten verschachtelt. Insbesondere sende ich HTTP-Anfragen ab, manchmal auf einmal, manchmal einzeln nacheinander mit einem Intervall dazwischen. In jedem Fall muss ich sie in der Reihenfolge sammeln.

    
mwt 17.08.2009, 21:02
quelle

5 Antworten

4

Gen_server ist wahrscheinlich nicht die beste Wahl dafür. Sie können alle Nachrichten in eine Pufferliste aufnehmen und den selektiven Empfang selbst implementieren:

%Vor%     
Zed 17.08.2009, 21:33
quelle
7
Mit

"plain_fsm" können Sie selektiv empfangen, während Sie weiterhin OTP-konform sind.

Ссылка

    
goertzenator 25.10.2010 15:36
quelle
4

Nein, gen_server ist nicht dafür ausgelegt, selektiv empfangen zu können. Jede Anfrage wird so bearbeitet, wie sie ankommt. Dies ist ein schwieriges Problem, da Erlang verlangt, dass alle Muster zum Zeitpunkt der Kompilierung bekannt sind. Es gibt kein "Musterobjekt".

Ich stimme zu, dass gen_fsm wahrscheinlich auch nicht für Sie ist, da es nicht mehrere Nachrichten in beliebiger Reihenfolge ankommen lässt, bevor Sie eine Explosion in der Anzahl der Zustände bekommen. Dies war einer der Gründe, warum wir selektives Empfangen hinzugefügt haben, es erlaubt Ihnen, uninteressante Nachrichten sicher zu ignorieren und sie für später zu verlassen.

An welchem ​​OTP interessiert Sie besonders?

    
rvirding 19.08.2009 02:32
quelle
3

Vielleicht möchten Sie wirklich gen_fsm verwenden. Dieses Verhalten wird normalerweise als Front-End für Protokolle gewählt, bei denen das Protokoll bestimmte Zustände hat und Anforderungen unterschiedlich behandeln muss, je nachdem, in welchem ​​Zustand es sich gerade befindet.

Aber zurück zu gen_server, verwenden wir gen_server für seine Funktionen. Er abonniert Systemereignisse für das Laden von Code und gibt Ihnen den Rückruf code_change. Es verursacht sasl-Berichte über Abstürze. Sie erhalten eine gut bekannte Struktur, die die Codepflege unterstützt. Am wichtigsten ist, dass es ein gut gestaltetes Protokoll für synchrone Anrufe implementiert.

Es ist schwer zu sagen, ob OTP-Verhalten in diesem Fall für Sie geeignet ist.

Angesichts des Kommentars klingt es wie ein gen_server ist falsch für Sie. Wenn ich das Verhalten von gen_server verwende, denke ich daran, dass es sich um einen Chef in einer Firma handelt. Jeder möchte mit dem Chef sprechen, deshalb liegt es im Interesse des Unternehmens, den Chef in die Lage zu versetzen, Aufträge schnell und effizient zu delegieren, damit er nicht warten lässt, anstatt zu arbeiten.

Der gen_server kann über den Parameter 'From' delegieren. Geben Sie dazu {no_reply, State} zurück und übergeben Sie den Parameter Von an den Delegaten. Der Delegat verwendet gen_server:reply/2 , um den ursprünglichen Aufruf zu beantworten.

Diese Methode der Verwendung eines gen_server könnte möglicherweise für Sie sein. Starten Sie einen "einfachen" Prozess, den Sie mit receive-end verwenden, um selektiv zu empfangen. Wenn dies ein wirklich unabhängiger Job ist, kann der gen_server ihn ignorieren (fire and forget). Wenn es wissen will, ob es fertig ist, kann man gen_server:cast/2 eine Nachricht von dem gestarteten "normalen" Prozess zurückgeben.

Wenn Sie den gen_server während des selektiven Empfangens blockieren wollen, dann könnte es eine Idee sein, einen Prozess ebenfalls zu starten und zu warten, bis er stirbt, bevor er zurückkehrt. Selektiver Empfang ist eine O (n) lineare Suche nach den Nachrichten in der Reihenfolge, in der sie angekommen sind. Jeder selektive Empfang scannt also alle Nachrichten in der Warteschlange, die für einen populären gen_server hoch sein könnten.

Kein Unternehmen soll nur Chefs haben, die dort arbeiten. Keine erlang-Anwendung soll nur gen_servers haben.

    
Christian 17.08.2009 22:22
quelle
2

Nur weil Sie gen_server nicht für eines Ihrer Module verwenden können, bedeutet das nicht, dass Sie OTP nicht verwenden. Alle Callback-Module implementieren den Empfangsblock für Sie, der Sie daran hindert, selektiv zu empfangen. Es gibt keinen Grund, warum Sie Ihren eigenen Dienst nicht implementieren können, der selektiv empfängt. Und das bedeutet nicht, dass du es nicht auf OTP-Art gemacht hast.

Sie können Ihren Service weiterhin von einem Supervisor mit allen Vorteilen verwalten lassen.

    
Jeremy Wall 19.08.2009 02:27
quelle

Tags und Links