Soll ich einen Befehl oder ein Ereignis verwenden?

14

Der Unterschied zwischen einem Befehl und einem Ereignis in der Buskommunikation erscheint mir etwas vage. Ich weiß, dass Befehle nur einmal ausgeführt werden sollten, während ein Ereignis mehrmals behandelt werden kann, aber ich bin mir immer noch nicht sicher, wann ich einen Befehl oder ein Ereignis verwenden soll.

Schauen wir uns ein Beispiel an:

Wenn sich ein neuer Benutzer bei einer Webanwendung registriert, sollten wir ihm ein Konto erstellen und eine Bestätigungs-E-Mail senden.

Erstellen des Kontos - Dies scheint der richtige Ort zu sein, um ein KontoCreateUserCommand an den Bus zu senden und eine spezialisierte Komponente damit umgehen zu lassen.

Oder sollte dies nicht einmal mit einer asynchronen Buskommunikation implementiert werden? Wir möchten, dass sich der Benutzer sofort bei der Anwendung anmelden kann. Mit dem Bus haben wir keine Garantie, wann der Befehl ausgeführt wird.

E-Mail senden - Nachdem die Komponente das Konto erstellt hat, sehe ich zwei Möglichkeiten

  1. Senden Sie einen weiteren Befehl an den Bus SendConfirmationEmailCommand
  2. Veröffentlichen Sie eine Veranstaltung UserAccountCreatedEvent

Und dann lassen Sie die E-Mail-Absender-Komponente es greifen und zu seinem Job.

Einerseits möchte ich, dass die Bestätigungs-E-Mail nur einmal gesendet wird (verwenden Sie einen Befehl), andererseits glaube ich, dass es mehrere Komponenten geben kann, die an neu registrierten Benutzern interessiert sind. Ein Logger oder vielleicht ein SMS-Absender.

Wie würden Sie es implementieren?

Andrzej Gis
quelle

Antworten:

16

Im Prinzip beschreibt ein Befehl eine Anforderung, die ausgeführt werden soll, während ein Ereignis etwas beschreibt, was passiert ist:

  • Für einen Befehl muss eine Aktion von einem Prozessor ausgeführt werden, und diese Aktion sollte von diesem Prozessor nur einmal ausgeführt werden.

  • Ein Ereignis ist die Benachrichtigung über eine bereits ausgeführte Aktion oder ein externes Ereignis. Möglicherweise sind mehrere Prozessoren / Agenten daran interessiert, Informationen über das Ereignis zu erhalten. Einige von ihnen können in ihrem Verantwortungsbereich weitere Befehle oder Aktionen erteilen, die für diese Benachrichtigung erforderlich sind.

In Ihrem Szenario verstehe ich Folgendes:

  • CreateUserCommand ist ein Befehl
  • UserAccountCreatedEventist ein Ereignis, das ausgegeben werden soll, wenn CreateUserCommandes vom Kontoverwaltungsdienst erfolgreich abgeschlossen wurde

Jetzt gibt es zwei Möglichkeiten:

  1. Der Kontoverwaltungsdienst gibt sich selbst SendConfirmationEmailCommandauf dem Bus aus, da er erwartet, dass dieser Befehl von einem spezialisierteren Dienst ausgeführt wird.
  2. Der Kontoverwaltungsdienst sendet lediglich die Ereignisbenachrichtigung nach Abschluss und überlässt einem anderen Dienst (z. B. Kommunikationsdienst, Abonnementdienst usw.) die Entscheidung, ob und ob eine E-Mail an / sms / etc ... gesendet werden soll oder nicht erforderlich, um einen SendConfirmationEmailCommandBefehl auszugeben, der von einem Gateway ausgeführt werden soll.

Wenn Sie sich für einen Servicebus-Ansatz entschieden haben, ist es sinnvoll, die Flexibilität zu nutzen, die dies ermöglicht, dh Option 2 zu bevorzugen.

Christophe
quelle
Danke, das klärt die Dinge auf. Zwei weitere Fragen zu Option 2: 1. Woher weiß der Kontoverwaltungsdienst, wie der Befehl ausgeführt wurde? Ich glaube, es geht darum, die Ereignisse zu hören, die von spezialisierten Diensten nach Abschluss ihrer Aufgaben veröffentlicht werden - was ist dann der eigentliche Zweck des Kontoverwaltungsdienstes? Ereignisse erneut veröffentlichen? Es scheint überflüssig. 2. Ich habe auch nicht verstanden, wer den SendConfirmationEmailCommand ausgeben soll. Account Management Service oder der "andere Service"?
Andrzej Gis
1) Ich ging davon aus, dass der Kontoverwaltungsdienst den Job selbst ausgeführt und das Ereignis gesendet hat, wenn es erfolgreich beendet wurde (dh keine Fehler aufgetreten sind). Aber Sie haben Recht: Es ist möglich, dass der Kontoverwaltungsdienst selbst Befehle an einen Persistenz- / Datenbankdienst sendet und das Ereignis zum Abschluss des Auftrags überwachen muss (z. B. eine asynchrone Antwort).
Christophe
@gisek 2) In einem Servicebus würde ich mir vorstellen, dass Sie sehr spezialisierte Services haben, die jeweils eine begrenzte Verantwortung haben. In diesem Fall führt die Kontoverwaltung nur die Erstellung durch und benachrichtigt jeden Interessierten darüber. Ein anderer Dienst würde dann überwachen, um zu reagieren. Sie könnten beispielsweise einen Kommunikationsmanager haben, der für die Anwendung von Geschäftsregeln zuständig ist, um zu entscheiden, wann und wie Ereignisse an Benutzer kommuniziert werden. Wenn Sie 1) +2) im selben Dienst ausführen würden, würden Sie kaum einen Dienstbus benötigen.
Christophe