So implementieren Sie einen Prozessmanager im Event-Sourcing

14

Ich arbeite an einer kleinen Beispielanwendung, um die Konzepte von CQRS und Event-Sourcing zu erlernen. Ich habe ein BasketAggregat und ein ProductAggregat, die unabhängig voneinander arbeiten sollten.

Hier ist ein Pseudocode zur Veranschaulichung der Implementierung

Basket { BasketId; OrderLines; Address; }

// basket events
BasketCreated { BasketId; }
ItemAdded { BasketId; ProductId; Quantity }
AddItemSucceeded { BasketId; ProductId; Quantity }
AddItemRevoked { BasketId; ProductId; Quantity }
ItemRemoved { BasketId; ProductId; Quantity }
CheckedOut { BasketId; Address }

Product { ProductId; Name; Price; }

// product events
ProductReserved { ProductId; Quantity }
ProductReservationFailed { ProductId; Quantity }
ProductReservationCancelled { ProductId; Quantity; }

Befehle sind den Ereignissen ziemlich ähnlich und verwenden den imperativen Namen und nicht die Vergangenheitsform.

Im Moment funktionieren diese unabhängig voneinander einwandfrei. Ich gebe einen Befehl aus AddItemund es wird ein ItemAddedEreignis auf dem BasketAggregat erstellt, das das tut, was es mit dem Status des 'Basket' zu tun hat. In ähnlicher Weise funktionieren der Befehl und die Ereignisse für das Produkt einwandfrei.

Ich möchte dies jetzt zu einem Prozess kombinieren, der ungefähr so ​​ablaufen würde (in Bezug auf Befehle und Ereignisse, die passieren):

Der Prozessmanager würde Folgendes tun:

on BasketCreated: CreateShoppingProcess
on ItemAdded: ReserveProduct
on ProductReserved: SucceedAddingItem // does nothing, but needs to be there so that the basket knows it can check out
on ProductReservationFailed: RevokeAddItem
on RemoveItem: CancelProductReservation
on Checkout: CreateOrder // create an order and so on...

Die Fragen, auf die ich keine endgültigen Antworten finden konnte, sind:

  1. Muss ich den Prozessmanager beibehalten? Es scheint so, als ob ich es tue, aber ich bin mir nicht sicher
  2. In diesem Fall muss ich die Ereignisse für den Prozessmanager speichern. Die Ereignisse, die abgehört werden, sind jedoch an die Aggregate gebunden. Füge ich diesen die Prozess-ID hinzu? Habe ich separate Ereignisse nur für den Prozessmanager? Wie man das macht und so trocken wie möglich hält
  3. Woher weiß ich, für welchen Warenkorb die ProductReservedVeranstaltungen sind? Ist es in Ordnung, eine BasketIdzu haben, oder sind das undichte Informationen?
  4. Wie halte ich eine Beziehung zwischen Ereignissen, woher weiß ich, ItemAddedwelches ProductReservedEreignis welches hervorgebracht hat ? Gebe ich ein EventId? Das scheint seltsam ...
  5. Sollte ich das Basketals Prozessmanager anstelle eines einfachen Aggregats implementieren ?

Nach einigen weiteren Nachforschungen bin ich zu folgendem gekommen: Eine Saga ist etwas, das seine eigenen Ereignisse beibehält und Ereignisse von außen abhört. Grundsätzlich ist es ein Aggregat, das auch auf Ereignisse außerhalb seiner eigenen kleinen Welt reagieren kann.

Ein Prozessmanager arbeitet mit den Ereignissen von außen und sendet Befehle aus. Der Verlauf kann anhand der Ereignisse auf den Aggregaten wiederhergestellt werden, die einen gemeinsamen Bezeichner wie eine Korrelations-ID haben.

Ivan Pintar
quelle
Anscheinend versuchen Sie, in Ihrem System einen formalen Prozess zu codieren, der einen vorhandenen informellen Anwendungsfall aus einer Reihe von Befehlen umschreibt. Dabei scheinen Sie neben den vorhandenen eine Reihe von redundanten Befehlen und Ereignissen zu erstellen. Ist das deine Absicht? Was ist das geschäftliche Bedürfnis hinter der Formalisierung von Dingen als Code-Prozess? Was in Ihrer Domäne erfordert, dass Sie diesen Prozess und den Grund dafür als vollwertiges Konzept identifizieren?
Guillaume31
Dies ist ein komplett ausgedachtes Projekt, bei dem der Zweck darin besteht, zu lernen, wie zwei relativ unabhängige Aggregate zusammenarbeiten. Es gibt also wirklich keinen "Geschäftsbedarf". Ich versuche, Redundanzen bei diesen Befehlen und Ereignissen so weit wie möglich zu vermeiden. Daher die Verwechslung mit dem Prozessmanager, denn es sieht so aus, als sollte sich nichts wiederholen, was die Aggregate bereits verarbeiten. Ich muss jedoch irgendwie eine Verbindung zwischen diesen beiden Aggregaten aufrechterhalten. Es scheint, dass die Verwendung von Kausalität und Korrelation hilfreich sein könnte, aber ich muss es ausprobieren.
Ivan Pintar

Antworten:

14

Lesen Sie, was Rinat Abdullin über die Entwicklung von Geschäftsprozessen geschrieben hat . Beachten Sie insbesondere seine Empfehlung für die Entwicklung eines Geschäftsprozesses in einer sich schnell ändernden Umgebung - ein Prozessmanager ist "nur" ein automatisierter Ersatz für einen Menschen, der auf einen Bildschirm starrt.

Mein eigenes mentales Modell eines Prozessmanagers ist, dass es sich um eine ereignisgesteuerte Projektion handelt, die Sie nach einer Liste ausstehender Befehle abfragen können.

Muss ich den Prozessmanager beibehalten? Es scheint so, als ob ich es tue, aber ich bin mir nicht sicher

Es ist ein Lesemodell. Sie können den Prozessmanager jedes Mal, wenn Sie ihn benötigen, aus dem Verlauf der Ereignisse neu erstellen. oder Sie können es wie einen Schnappschuss behandeln, den Sie aktualisieren.

In diesem Fall muss ich die Ereignisse für den Prozessmanager speichern.

Nein - der Prozessmanager ist ein Manager . Es macht nichts Nützliches für sich allein; Stattdessen werden die Aggregate angewiesen, ihre Arbeit zu erledigen (dh Änderungen am Buch der Aufzeichnungen vorzunehmen).

Woher weiß ich, für welchen Warenkorb die ProductReserved-Ereignisse bestimmt sind? Ist es in Ordnung, eine BasketId auf diesen zu haben, oder ist das undichte Informationen

Sicher. Hinweis: In den meisten "echten" Einkaufsdomains würden Sie nicht darauf bestehen, Inventar zu reservieren, bevor Sie eine Bestellung bearbeiten. es fügt dem Geschäft unnötige Konkurrenz hinzu. Es ist wahrscheinlicher, dass Ihr Unternehmen die Bestellung annehmen möchte, und sich dann in dem seltenen Fall entschuldigen möchte, dass die Bestellung nicht in der erforderlichen Zeit ausgeführt werden kann.

Wie halte ich eine Beziehung zwischen Ereignissen, woher weiß ich, welches ItemAdded-Ereignis welches ProductReserved-Ereignis erzeugt hat?

Nachrichten haben Metadaten - insbesondere können Sie einen causationIdentifier (damit Sie identifizieren können, welche Befehle welche Ereignisse erzeugt haben) und einen correlationIdentifier einschließen , um die Konversation im Allgemeinen zu verfolgen.

Beispielsweise schreibt der Prozessmanager eine eigene ID als correlationId in den Befehl. Die von einer Kopie erzeugten Ereignisse enthalten die Korrelations-ID des Befehls, und Ihr Prozessmanager abonniert alle Ereignisse mit einer eigenen Korrelations-ID.

Sollte ich den Basket als Prozessmanager anstelle eines einfachen Aggregats implementieren?

Meine Empfehlung lautet nein. Aber Udi Dahan hat eine andere Meinung, die Sie überprüfen sollten; Dies bedeutet, dass CQRS nur Sinn macht, wenn Ihre Aggregate Sagen sind. Udi verwendete Saga an der Stelle, an der der Prozessmanager die vorherrschende Schreibweise geworden ist.

sollten Prozessmanager Aggregate abrufen?

Nicht wirklich? Prozessmanager befassen sich hauptsächlich mit der Orchestrierung und nicht mit dem Domänenstatus. Eine Instanz eines Prozesses hat einen "Zustand" in Form eines Verlaufs aller Ereignisse, die sie beobachtet haben. Die richtige Vorgehensweise bei Ereignis Z hängt davon ab, ob wir Ereignisse X und Y gesehen haben oder nicht Sie müssen möglicherweise in der Lage sein, eine Darstellung dieses Zustands zu speichern und zu laden.

(Ich sage „nicht wirklich“ , weil Aggregat vage genug definiert ist , dass es nicht ganz falsch ist , dass die Liste der beobachteten Ereignisse Anspruch ist ein „Aggregat“ Die Unterschiede mehr semantische sind als Implementierung -. Wir laden Prozesszustand und dann entscheiden , welche Nachrichten zu sende es an die Teile des Systems, die für den Domain-Status verantwortlich sind.

Der PM muss also nicht eine Art von Statusverwaltung über eine andere anwenden, da er nur für die Ausführung von Live-Aufgaben verantwortlich ist und niemals für Wiederholungen.

Nicht ganz - das Staatsmanagement ist kein Macher, es ist ein Wächter-Verfolger. In Situationen, in denen der Prozessmanager keine Signale senden sollte, geben Sie ihm träge Verbindungen zur Welt. Mit anderen Worten, dispatch(command)ist ein No-Op.

VoiceOfUnreason
quelle
1
Sie sagen: Sie können den Prozessmanager jedes Mal, wenn Sie ihn benötigen, aus dem Verlauf der Ereignisse neu erstellen. Um ihn jedoch neu zu erstellen, müssen Sie Ereignisse dafür speichern. Oder sollte ich es aus den Ereignissen in den Aggregaten neu erstellen? Der Teil, mit dem ich zu kämpfen habe, ist: Bei Aggregaten haben die Ereignisse die Aggregat-ID, und es ist einfach, sie neu zu erstellen, indem alle Ereignisse mit dieser Aggregat-ID gefunden werden. Aber wie würde ich das für den Prozessmanager tun? Sollte ich das für den Prozessmanager tun? Oder sollte der Prozessmanager die Aggregate nachschlagen, wenn er aufgrund eines eingetretenen Ereignisses eine Entscheidung treffen muss?
Ivan Pintar
Was mir gefehlt hat, war der Begriff der Kausalität und Korrelation beim Event-Sourcing. Nachdem ich das untersucht hatte, ergab Ihre Antwort auf die vierte Frage endlich Sinn.
Ivan Pintar
1
Ich würde mich über eine Antwort auf @IvanPintars ersten Kommentar freuen. sollten Prozessmanager Aggregate abrufen? Sollten sie ihre eigenen auf den Ereignissen aufbauen, die sie verarbeiten? In diesem Fall müssten Event-Handler nebenwirkungsfrei sein, oder?
Jeff
@ Jeff In einem Beispiel hatte der Prozessmanager einen eigenen Speicher, der mit jedem verarbeiteten Ereignis aktualisiert wurde, eine Art Lesemodell. Dies war einfach zu tun und es war einfach zu verfolgen, was es bereits verarbeitet hat. In einem anderen Beispiel hat der Prozessmanager eigene Ereignisse erstellt und gespeichert, die aus den aggregierten Ereignissen aufgebaut sind. Ähnlich wie oben, aber der Staat war ereignisgesteuert. Abhängig von der Komplexität des Status, den der Prozessmanager beibehält, ist es möglicherweise einfacher, den einen oder anderen Status zu verwenden. Ich fand den ersten Ansatz einfacher.
Ivan Pintar
Interessant, also ist es mehr oder weniger Sache des Entwicklers, solange der Prozessmanager auf Ereignisse reagiert und am Ende Befehle sendet?
Jeff
2

Was Sie suchen, hat ein Muster namens "Saga", das im Wesentlichen ein Prozessmanager ist.

Saga-Befehle eignen sich auch für Prozesse mit langer Laufzeit, da sie den Status zwischen korrelierten Befehlen aufrechterhalten können.

Hier ist ein großartiger Artikel über Sagas

Bishoy
quelle