Zdaję sobie sprawę, że powyższe pytanie prawdopodobnie rodzi kilka „co?”, Ale spróbuję wyjaśnić:
Próbuję oprzeć głowę na kilku pokrewnych koncepcjach, w zasadzie wzorcu Saga ( http://www.rgoarchitects.com/Files/SOAPatterns/Saga.pdf ) w połączeniu z Event-Sourcing (koncepcja DDD) : http://en.wikipedia.org/wiki/Domain-driven_design )
Dobry post, który go otacza: https://blog.jonathanoliver.com/cqrs-sagas-with-event-sourcing-part-ii-of-ii/
Przechodzę do pytania za minutę, ale myślę, że najpierw muszę spróbować streścić to, co rozumiem (co może być nie tak, więc proszę popraw, jeśli tak jest), ponieważ może to mieć wpływ na to, dlaczego jestem zadając pytanie na początek:
- Wzorzec Saga jest rodzajem brokera, który wydał akcję (użytkownik końcowy, zautomatyzowany itp. Zasadniczo wszystko, co ma zmienić dane) dzieli tę akcję na działania biznesowe i wysyła każde z tych działań jako wiadomości do szyny komunikatów, która z kolei wysyła je do odpowiednich zagregowanych korzeni, którymi należy się zająć.
- Te zagregowane korzenie mogą działać całkowicie autonomicznie (ładne rozdzielenie problemów, świetna skalowalność itp.)
- Sama instancja Saga nie zawiera żadnej logiki biznesowej, która jest zawarta w zagregowanych korzeniach, do których wysyła działania. Jedyną „logiką” zawartą w Sadze jest logika „procesowa” (często implementowana jako Statemachine), która określa na podstawie otrzymanych działań (a także zdarzeń kontrolnych), co robić (tj. Jakie działania wysłać)
- Wzory Saga implementują rodzaj rozproszonego wzorca transakcji. Tj .: gdy jeden z zagregowanych korzeni (które znów działają autonomicznie, nie wiedząc o istnieniu siebie nawzajem) zawiedzie, cała akcja może wymagać wycofania.
- Jest to realizowane przez posiadanie wszystkich zagregowanych korzeni, po zakończeniu ich sprawozdania z działalności z powrotem do Sagi. (W przypadku sukcesu, jak i błędu)
- W przypadku, gdy wszystkie zagregowane korzenie zwrócą sukces, wewnętrzny statemachine, jeśli Saga określa, co dalej (lub zdecyduje, że to zrobione)
- W przypadku niepowodzenia Saga przekazuje wszystkim zagregowanym korzeniom, które brały udział w ostatnim działaniu, tak zwane Akcje kompensacyjne, tj .: działanie mające na celu cofnięcie ostatniego działania każdego z zagregowanych korzeni.
- Może to być po prostu „głosowanie minus 1”, jeśli akcja brzmiała „plus głos”, ale może to być bardziej skomplikowane, jak przywrócenie posta na blogu do jego poprzedniej wersji.
- Pozyskiwanie zdarzeń (patrz łączący oba posty na blogu) ma na celu zewnętrzne zapisanie wyników każdego działania, które każde z zagregowanych źródeł podejmuje w scentralizowanym magazynie zdarzeń (w tym kontekście zmiany nazywane są „zdarzeniami”)
- Ten magazyn zdarzeń jest „pojedynczą wersją prawdy” i można go użyć do odtworzenia stanu wszystkich bytów po prostu poprzez iterację przechowywanych zdarzeń (zasadniczo jak dziennik zdarzeń)
- Połączenie tych dwóch (tj. Zezwolenie na łączenie korzeni z wykorzystaniem Event-sourcingu w celu outsourcingu zapisywania ich zmian przed zgłoszeniem się do Sagi) daje wiele fajnych możliwości, z których jedna dotyczy mojego pytania ...
Czułem, że muszę to zdjąć z ramienia, ponieważ za jednym razem trzeba to dużo uchwycić. Biorąc pod uwagę ten kontekst / sposób myślenia (ponownie, proszę poprawić, jeśli jest źle)
pytanie: kiedy zagregowany root otrzyma akcję kompensacji i jeśli ten agregat root zlecił outsourcing zmian stanu za pomocą pozyskiwania zdarzeń, czy akcja kompensacji we wszystkich sytuacjach nie byłaby po prostu usunięciem ostatniego zdarzenia w magazynie zdarzeń biorąc pod uwagę Root Aggregate? (Zakładając, że implementacja trwała umożliwia usuwanie)
Miałoby to dla mnie wiele sensu (i byłaby kolejną wielką zaletą tej kombinacji), ale jak powiedziałem, mogę przyjmować te założenia w oparciu o niepoprawne / niepełne zrozumienie tych pojęć.
Mam nadzieję, że nie rozwinęło się to zbyt długo.
Dzięki.
źródło
Dla kompletności pomyślałem o dołączeniu odpowiedniego fragmentu Martina Fowlera o sposobach przywrócenia stanu:
Od: http://martinfowler.com/eaaDev/EventSourcing.html
źródło
Koncepcyjnie:
Możemy zmienić nasz przyszły stan tylko poprzez wykonanie innego polecenia (Kompensacja), co powinno spowodować zmianę stanu zdarzeń przez aplikację.
Aby „dezorientować” pytanie, pomyśl o tym frazie „usuń ostatnie zdarzenie”:
Krótko mówiąc, nie masz opcji usuwania zdarzeń w ramach wzorca CQRS.
Możesz zmniejszyć swój magazyn zdarzeń, tworząc stan migawki (który jest oparty na wszystkich zdarzeniach prowadzących do tego stanu), ale ten aspekt fizyczny nie ma nic wspólnego z pojęciem zdarzenia.
źródło
Geert-Jan, również uważam, że akcja kompensacyjna może po prostu usunąć odpowiednie zdarzenie (zdarzenia). Ma to sens i pokazuje kolejną zaletę wzorca projektowego Sourcing Event: łatwiejsze wdrożenie wzorca projektowego Transakcji kompensacyjnej.
Niektórzy twierdzą, że usunięcie wydarzenia narusza „zasady” pozyskiwania zdarzeń lub CQRS. Myślę, że jest to ograniczenie uogólniające. Myślę, że można usunąć zdarzenie, jeśli zostało utworzone w ramach anulowanej transakcji globalnej. Rozważ pseudokod:
Załóżmy, że Twój magazyn zdarzeń jest transakcyjną bazą danych. W pseudokodzie można wyobrazić sobie sytuację, w której wstawiono pierwsze zdarzenie, ale podczas próby wstawienia drugiego zdarzenia został zgłoszony wyjątek. Polecenie wycofania naturalnie cofnęłoby wstawienie pierwszego zdarzenia. Czy to rozsądne?
Jeśli jest to uzasadnione dla transakcji bazy danych ACID (transakcja z zatwierdzeniem / wycofaniem), dlaczego nie byłoby uzasadnione dla transakcji kompensującej?
Podczas realizacji globalnej transakcji Saga zmiany danych można cofnąć (za wynagrodzeniem). Nie ma potrzeby zatrzymywania zdarzenia utworzonego podczas transakcji, ponieważ transakcja nie została zakończona.
Teraz, jeśli kompensacja próbuje usunąć zdarzenie, a to zdarzenie nie jest najnowszym zdarzeniem na obiekcie, usunięcie nie powinno nastąpić. Ale ogólnie rzecz biorąc, jest to mało prawdopodobne, szczególnie w przypadku rozwiązań wymagających intensywnego odczytu.
źródło
Zagrajmy z myślą, że przechowywanie zdarzeń to tylko dane, które chcesz zapisać. Na przykład możemy mieć dysk twardy, możemy zacząć od początku i zapisywać na nim dane. Za każdym razem, gdy mamy zdarzenie, dołączamy nasze poprzednie dane, więc po prostu kontynuujemy zapisywanie na dysku, na którym ostatnio się zatrzymaliśmy. Kiedy chcemy usunąć zdarzenie, cofamy się, usuwamy tę część z dysku i pozostawiamy lukę. Cofanie się samoistnie spowalnia magazynowanie wydarzeń, ale możemy z tym żyć. Jeśli użyjemy systemu plików, który spróbuje wypełnić lukę późniejszymi zdarzeniami, w rezultacie będziemy mieć powolne pofragmentowane miejsce do przechowywania danych lub możemy przeprowadzić defragmentację. Żadne z nich nie jest czymś, co lubimy. Jeśli mówimy o bazach danych, otrzymujesz to, jeśli do przechowywania zdarzeń używasz relacyjnej bazy danych zamiast tylko bazy danych dołączającej:
ref: https://cambridge-intelligence.com/bringing-time-series-data-to-life-with-keylines/
Ofc. w przypadku zwykłej witryny nie ma to znaczenia, ale te rozwiązania są przeznaczone dla dużych witryn, takich jak Facebook, Google itp. Tak naprawdę pytanie nie ma sensu, ponieważ jak usunąć zdarzenie w bazie danych dołączającej i jak nazywasz odszkodowanie czymś w rodzaju budowy wehikułu czasu i cofania się w czasie, aby zmienić lub zapobiec zdarzeniu?
Afaik. jedynym sposobem na rozwiązanie tego jest utworzenie nowego magazynu zdarzeń, w którym wykluczone zostaną zdarzenia, których nie chcesz mieć, a następnie usunięcie starego magazynu zdarzeń. Ale to ekstremalne rozwiązanie, aby usunąć pojedyncze zdarzenie. Jeśli mówimy o RODO, to jedynym relatywnie dobrym rozwiązaniem, jakie znam, jest przechowywanie danych osobowych zaszyfrowanych w pamięci zdarzeń i usuwanie klucza szyfrowania z innej bazy danych.
źródło