Jak obsługiwać błędy po sprawdzeniu poprawności w poleceniu (DDD + CQRS)

18

Na przykład, gdy przesyłasz formularz Rejestru, musisz sprawdzić Domain Model( WriteModelin CQRS), czy jest on w poprawnym stanie (na przykład składnia adresu e-mail, wiek itp.).

Następnie tworzysz Commandi wysyłasz do Command Bus.

Rozumiem, że polecenia nie powinny niczego zwracać.

Jak więc poradzić sobie z błędem wykraczającym poza Command Bus? (Na przykład użytkownik zarejestrował się 1 sekundę wcześniej z tym samym username/email).

Skąd wiesz, że to polecenie nie powiodło się i skąd znasz błąd?

JorgeeFG
źródło
2
Nie potrzebujesz magistrali zdarzeń. Dlaczego wszyscy uważają, że potrzebujesz magistrali zdarzeń podczas wdrażania CQRS, po prostu nie wiem. CQRS oznacza po prostu, że całkowicie oddzielasz zapisy i odczyty, robisz oddzielne obawy. Masz CQRS tak długo, jak to robisz. Twoje polecenia nie muszą nawet być asynchroniczne. Jeśli działają dla Ciebie synchroniczne polecenia z raportowaniem błędów, zrób to.
Andy,
1
Polecenia nie powinny niczego zwracać po pomyślnym zakończeniu . Pomysł zaczął się od CQS , co sugerowało, że polecenie może nadal zgłaszać wyjątek w przypadku błędu. To, co opisujesz, to polecenie jednokierunkowe. Zobacz tę odpowiedź w związku z tym.
Kasey Speakman

Odpowiedzi:

4

Rozumiem, że polecenia nie powinny niczego zwracać.

To jeden widok, ale nie do końca osadzony w kamieniu. Rozważ zapisy (PUT, POST, DELETE) w HTTP - wszystkie te wiadomości są poleceniami, w tym sensie, że są to wiadomości z żądaniem zmiany stanu zasobów, a jednak wszystkie zwracają odpowiedzi.

Jak więc radzić sobie z błędem wykraczającym poza magistralę poleceń? (Na przykład użytkownik zarejestrował się 1 sekundę wcześniej z tą samą nazwą użytkownika / adresem e-mail).

Skąd wiesz, że to polecenie nie powiodło się i skąd znasz błąd?

Tak więc w przypadku, gdy komunikujesz się bezpośrednio z programem obsługi poleceń, zwrócony komunikat jest całkowicie rozsądnym sposobem potwierdzenia, że ​​polecenie zostało odebrane i przetworzone.

Jeśli korzystasz z oprogramowania pośredniego, takiego jak magistrala, który uniemożliwia bezpośrednią komunikację z celem, sugerowałbym, abyś spojrzał na asynchroniczne wzorce przesyłania komunikatów - w jaki sposób można uzyskać od programu obsługi poleceń wysyłanie wiadomości z powrotem do gość?

Jednym z pomysłów jest podpisanie się pod wynikiem polecenia; zapożycza się od niektórych pomysłów zawartych w wzorcach integracji przedsiębiorstw Hohpe. Podstawową ideą jest to, że ponieważ klient zna wysłaną wiadomość polecenia, jest w stanie odpowiednio zasubskrybować wszelkie nowe wiadomości publikowane w wyniku komunikatu polecenia. Program obsługi poleceń, po zapisaniu danych w księdze rekordów, publikuje zdarzenia informujące, że zmiana się powiodła, a klient subskrybuje te zdarzenia - rozpoznając prawidłowe zdarzenia, biorąc pod uwagę zbieżność różnych identyfikatorów w komunikacie (identyfikator związku przyczynowego, identyfikator korelacji itd.).

Alternatywne podejścia są nieco bardziej bezpośrednie. Jednym z nich byłoby dołączenie do komunikatu wywołania zwrotnego, które może zostać wywołane przez moduł obsługi poleceń po pomyślnym przetworzeniu komunikatu.

Bardzo podobną alternatywą jest zarezerwowanie miejsca w komunikacie polecenia dla programu obsługi poleceń do napisania potwierdzenia - ponieważ klient ma już ten komunikat polecenia, obwód jest już ukończony. Pomyśl „ obietnica ” lub „ pełna przyszłość”. Komunikat informuje program obsługi poleceń, gdzie należy zapisać potwierdzenie; robienie tego sygnalizuje klientowi (zatrzask odliczający), że potwierdzenie jest dostępne.

I oczywiście masz dodatkową opcję usuwania oprogramowania pośredniego, które wydaje się przeszkadzać w wykonywaniu właściwych czynności po prostu.

Na przykład użytkownik zarejestrował się 1 sekundę wcześniej z tą samą nazwą użytkownika / adresem e-mail

Jeśli postępujesz z rejestracją użytkownika idempotentnie, niekoniecznie byłby to błąd - powtarzanie wiadomości do momentu zaobserwowania odpowiedzi jest powszechnym sposobem na zapewnienie przynajmniej raz dostawy.

VoiceOfUnreason
źródło
2

Na przykład po przesłaniu formularza rejestracyjnego należy sprawdzić w modelu domeny (WriteModel w CQRS), czy jest on w prawidłowym stanie (na przykład składnia adresu e-mail, wiek itp.)

Istnieje wiele rodzajów walidacji. Sprawdzanie poprawności podczas sprawdzania składni adresu e-mail i formatu wieku jest rodzajem sprawdzania poprawności, które może wykonać polecenie. To naprawdę nie dotyczy domeny. Może się tak wydawać, ponieważ niektórzy eksperci domeny powiedzieliby ci te specyfikacje, ale powinieneś zrobić tego rodzaju sprawdzanie poprawności w tworzeniu polecenia. W rzeczywistości ogólną ideą jest jak najszybsze sprawdzenie poprawności, ponieważ po utworzeniu polecenia i wysłaniu go do magistrali bardziej skomplikowane jest podjęcie działań.

Jak więc radzić sobie z błędem wykraczającym poza magistralę poleceń? (Na przykład użytkownik zarejestrował się 1 sekundę wcześniej z tą samą nazwą użytkownika / adresem e-mail).

Ten rodzaj walidacji jest często omawiany w społeczności CQRS od początku CQRS. Gdzie to zrobić To jest bardzo dyskutowane. Osobiście stosuję następujące podejście: przed wysłaniem polecenia do magistrali zaznaczam nazwę użytkownika / e-mail jako odebrane w sposób scentralizowany (tj. Unikalne ograniczenie indeksu dla nazwy użytkownika / e-maila). Następnie wysyłam polecenie. Wadą jest to, że jeśli polecenie się nie powiedzie, przez krótki czas nazwa użytkownika jest pobierana i nie używana; jest to do przyjęcia dla mojej firmy, prawdopodobnie dla Twojej firmy.

Skąd wiesz, że to polecenie nie powiodło się i skąd znasz błąd?

Jeśli agregacja odrzuca polecenie asynchroniczne z powodu niezmiennika domeny, należy podjąć pewne środki, wydając polecenie kompensacyjne, które w jakiś sposób powiadamia wydawcę polecenia (tj. Wysłać wiadomość e-mail z wyjaśnieniem, że polecenie nie powiodło się).

Problem ze zduplikowanym adresem e-mail polega na tym, że nie można wysłać e-maila, ponieważ ten adres należy do innej osoby, dlatego sprawdzam go przed wysłaniem polecenia do magistrali.

Constantin Galbenu
źródło
1

Walidacja powinna być przeprowadzona w dekoratorze. Następnie każde polecenie wymagające weryfikacji może zostać udekorowane jako takie.

Sprawdzanie poprawności może być obsługiwane z wyjątkami, jeśli powrócisz nieważne za pomocą polecenia, aby można je było odebrać za pomocą wywołań synchronizacyjnych lub asynchronicznych z rezultatem zwróconego zadania.

Inną możliwością jest uznanie sprawdzania poprawności za rodzaj „zapytania”, które zwróci wynik sprawdzania poprawności. Uruchom zapytanie sprawdzające poprawność, a następnie, jeśli zostanie przekazane, uruchom polecenie. Byłaby to alternatywa dla podejścia dekoratora.

Jon Raynor
źródło
Podoba mi się podejście wyjątkowe, ponieważ jest to najczystszy sposób. Ale czy wyjątki nie są na to zbyt ciężkie?
EresDev,
1
HI @EresDev - Tak, są ciężkie. Ale nie wiem, jak „prawidłowe” są twoje dane. Powiedzmy, że na 1000 rekordów 2 są nieprawidłowe. Wyjątki mogą być wykonalne, ponieważ są to naprawdę wyjątkowe warunki. Teraz rozważ 1000 rekordów z 200 nieważnymi. Z tego powodu należy unikać wyjątków tak, ponieważ 20% Twoich danych jest nieprawidłowe. Pozostawiam więc decyzję o tym, czy wybrać to podejście w oparciu o aktualną ważność danych. :)
Jon Raynor,
Dodam do tego, mówiąc, że jeśli zachowamy przykład formularza rejestracyjnego, w którym myślę, że 50% lub więcej użytkowników najpierw wstawi nieprawidłowe dane, wyjątek nadal będzie w porządku. W backendach aplikacji WWW przeważnie otrzymujesz poprawne dane, ponieważ nakładki również sprawdzają poprawność. Dostajesz tylko wtedy, gdy coś przez jakiś rzadki przypadek nie sprawdzało poprawności interfejsu lub jeśli ktoś wygłupia się. Tak więc wyjątki są w tym przypadku w porządku.
EresDev,