Mir ist klar, dass die obige Frage wahrscheinlich ein paar Fragen aufwirft, aber lassen Sie mich versuchen zu erklären:
Ich versuche, mich auf ein paar verwandte Konzepte einzulassen, im Grunde das Saga-Muster ( http://www.rgoarchitects.com/Files/SOAPatterns/Saga.pdf ) in Kombination mit Event-Sourcing (Ein DDD-Konzept) : http://en.wikipedia.org/wiki/Domain-driven_design )
Ein guter Beitrag, der alles zusammenfasst: https://blog.jonathanoliver.com/cqrs-sagas-with-event-sourcing-part-ii-of-ii/
Ich komme gleich zu der Frage, aber ich denke, ich muss versuchen, zunächst zusammenzufassen, was ich davon verstehe (was möglicherweise falsch ist, korrigieren Sie dies bitte, wenn dies der Fall ist), da dies möglicherweise einen Einfluss darauf hat, warum ich es bin die Frage stellen, um mit zu beginnen:
- Das Saga-Muster ist eine Art Broker, der bei einer bestimmten Aktion (Endbenutzer, Automatisierter usw., im Wesentlichen alles, was Daten ändert) diese Aktion in Geschäftsaktivitäten aufteilt und jede dieser Aktivitäten als Nachrichten an einen Nachrichtenbus sendet, der Sendet es wiederum an die jeweiligen Aggregatwurzeln, um es zu pflegen.
- Diese aggregierten Wurzeln können völlig autonom arbeiten (nette Trennung von Bedenken, große Skalierbarkeit usw.)
- Eine Saga-Instanz selbst enthält keine Geschäftslogik, die in den aggregierten Wurzeln enthalten ist, an die sie Aktivitäten sendet. Die einzige 'Logik', die in der Saga enthalten ist, ist die 'Prozess'-Logik (oft als Statemachine implementiert), die basierend auf empfangenen Aktionen (sowie Folgeereignissen) festlegt, was zu tun ist (dh welche Aktivitäten gesendet werden sollen).
- Das Saga-Muster implementiert eine Art verteiltes Transaktionsmuster. Dh, wenn eine der aggregierten Wurzeln (die wiederum autonom arbeiten, ohne die Existenz der anderen zu kennen) ausfällt, muss möglicherweise die gesamte Aktion zurückgesetzt werden.
- Dies wird umgesetzt, indem alle aggregierten Wurzeln nach Abschluss ihres Aktivitätsberichts an die Saga zurückgeschickt werden. (Im Erfolgsfall ebenso wie im Fehlerfall)
- Für den Fall, dass alle aggregierten Wurzeln erfolgreich sind, bestimmt die interne Statemachine, ob die Saga als Nächstes etwas unternimmt (oder entscheidet, ob dies getan wird).
- Im Fehlerfall gibt die Saga an alle Aggregatwurzeln, die an der letzten Aktion teilgenommen haben, eine sogenannte Ausgleichsaktion aus, dh: eine Aktion, um die letzte Aktion rückgängig zu machen, die jede der Aggregatwurzeln ausgeführt hat.
- Wenn die Aktion "plus 1 Stimme" war, könnte dies einfach eine "Minus 1 Stimme" sein, aber es könnte komplizierter sein, als wenn ein Blogpost auf seine vorherige Version zurückgesetzt würde.
- Event-Sourcing (siehe den Blogpost, in dem beide kombiniert werden) zielt darauf ab, die Ergebnisse der einzelnen Aktivitäten, die jeder der zusammengefassten Roots durchführt, in einem zentralen Event-Speicher zu speichern (die Änderungen werden in diesem Kontext als "Ereignisse" bezeichnet).
- Dieser Ereignisspeicher ist die "einzelne Version der Wahrheit" und kann verwendet werden, um den Status aller Entitäten abzuspielen, indem einfach die gespeicherten Ereignisse wiederholt werden (im Wesentlichen wie ein Ereignisprotokoll).
- Die Kombination der beiden Möglichkeiten (dh das Auslagern der Änderungen mithilfe von Event-Sourcing durch aggregierte Roots, bevor sie an die Saga zurückgemeldet werden) bietet viele nette Möglichkeiten, von denen eine meine Frage betrifft ...
Ich hatte das Gefühl, ich musste das von meiner Schulter nehmen, da es eine Menge ist, die ich auf einmal begreifen kann. In Anbetracht dieses Kontexts / dieser Einstellung (bitte korrigieren, falls falsch)
Die Frage: Wenn ein aggregierter Stamm eine Kompensationsaktion erhält und dieser aggregierte Stamm seine Zustandsänderungen mithilfe von Ereignisquellen ausgelagert hat, wäre die Kompensationsaktion nicht in allen Situationen einfach eine Löschung des letzten Ereignisses im Ereignisspeicher Aggregate Root gegeben? (Vorausgesetzt, die Persist-Implementierung erlaubt das Löschen)
Das würde für mich viel Sinn machen (und wäre ein weiterer großer Vorteil dieser Kombination), aber wie gesagt, ich könnte diese Annahmen auf der Grundlage eines falschen / unvollständigen Verständnisses dieser Konzepte treffen.
Ich hoffe, das wurde nicht zu langatmig.
Vielen Dank.
quelle
Der Vollständigkeit halber habe ich mir überlegt, ein relevantes Snippet von Martin Fowler über Möglichkeiten zur Wiederherstellung des Zustands beizufügen:
Von: http://martinfowler.com/eaaDev/EventSourcing.html
quelle
Konzeptionell:
Wir können unseren zukünftigen Status nur ändern, indem wir einen anderen Befehl ausführen (Aktion kompensieren), der dazu führen sollte, dass Ereignisse den Status der Anwendung ändern.
Um die Frage zu "verwirren", denken Sie an diesen Ausdruck "Löschen des letzten Ereignisses":
Kurz gesagt, Sie haben keine Möglichkeit, Ereignisse innerhalb des CQRS-Musters zu löschen.
Sie können den Ereignisspeicher verkleinern, indem Sie einen Snapshot-Status erstellen (der auf allen Ereignissen basiert, die zu diesem Status führen). Dieser physikalische Aspekt hat jedoch nichts mit dem Konzept des Ereignisses zu tun.
quelle
Geert-Jan, ich denke auch, dass die Ausgleichsaktion einfach die entsprechenden Ereignisse löschen kann. Es ist sinnvoll und zeigt einen weiteren Vorteil des Event-Sourcing-Entwurfsmusters: die einfachere Implementierung des Entwurfsmusters "Compensating Transaction".
Einige sagen, das Löschen des Ereignisses verstoße gegen die "Prinzipien" des Event-Sourcing oder des CQRS. Ich denke, das ist eine begrenzende Verallgemeinerung. Ich denke, es ist in Ordnung, ein Ereignis zu löschen, wenn es im Rahmen einer globalen Transaktion erstellt wurde, die storniert wird. Betrachten Sie den Pseudocode:
Angenommen, Ihr Ereignisspeicher ist eine Transaktionsdatenbank. Im Pseudocode können Sie sich die Situation vorstellen, in der Sie das erste Ereignis eingefügt haben, aber beim Versuch, das zweite Ereignis einzufügen, wurde eine Ausnahme ausgelöst. Der Rollback-Befehl würde natürlich das Einfügen des ersten Ereignisses rückgängig machen. Ist das vernünftig?
Wenn es für eine ACID-Datenbanktransaktion (Transaktion mit Festschreiben / Zurücksetzen) angemessen ist, warum wäre es für eine Ausgleichstransaktion nicht angemessen?
Bei der Ausführung der globalen Saga-Transaktion können Datenänderungen rückgängig gemacht werden (durch Kompensation). Das Ereignis, das während der Transaktion erstellt wurde, muss nicht beibehalten werden, da die Transaktion nicht abgeschlossen wurde.
Wenn die Kompensation nun versucht, ein Ereignis zu löschen, und dieses Ereignis nicht das neueste Ereignis auf einem Objekt ist, sollte das Löschen nicht erfolgen. Im Allgemeinen ist dies jedoch unwahrscheinlich, insbesondere bei leseintensiven Lösungen.
quelle
Lassen Sie uns mit dem Gedanken spielen, dass der Ereignisspeicher nur Daten sind, die Sie speichern möchten. Zum Beispiel können wir eine Festplatte haben, am Anfang beginnen und Daten darauf schreiben. Jedes Mal, wenn wir ein Ereignis erhalten, hängen wir unsere vorherigen Daten an, sodass wir einfach weiter auf die Festplatte schreiben, auf der wir das letzte Mal angehalten haben. Wenn wir ein Ereignis entfernen möchten, gehen wir zurück, entfernen Sie diesen Teil von der Festplatte und lassen Sie eine Lücke. Das Zurückbewegen von alleine verlangsamt unseren Veranstaltungsspeicher, aber damit können wir leben. Wenn wir ein Dateisystem verwenden, wird versucht, die Lücke mit letzteren Ereignissen zu füllen, sodass wir am Ende einen langsamen fragmentierten Speicher haben oder eine Defragmentierung durchführen können. Keiner von ihnen ist etwas, was wir mögen. Wenn es sich um Datenbanken handelt, erhalten Sie dies, wenn Sie eine relationale Datenbank anstelle einer Datenbank zum Anhängen verwenden, in der Ihre Ereignisse gespeichert werden:
ref: https://cambridge-intelligence.com/bringing-time-series-data-to-life-with-keylines/
Ofc. Für eine normale Site ist das egal, aber diese Lösungen sind für riesige Websites wie Facebook, Google usw. konzipiert. Die Frage ist also nicht wirklich sinnvoll, denn wie würden Sie ein Ereignis in einer Append-Only-Datenbank löschen und wie würden Sie das tun Sie nennen Kompensation so etwas wie den Bau einer Zeitmaschine und das Zurückversetzen in die Vergangenheit, um ein Ereignis zu ändern oder zu verhindern?
So viel ich weiss. Die einzige Möglichkeit, dies zu beheben, besteht darin, einen neuen Ereignisspeicher zu erstellen, in dem Sie die nicht gewünschten Ereignisse ausschließen und anschließend den alten Ereignisspeicher entfernen. Dies ist jedoch eine extreme Lösung, um ein einzelnes Ereignis zu entfernen. Wenn es sich um GDPR handelt, ist die einzige mir bekannte, relativ gute Lösung, persönliche Daten verschlüsselt im Ereignisspeicher zu speichern und den Verschlüsselungsschlüssel aus einer anderen Datenbank zu entfernen.
quelle