CQRS Event Sourcing sprawdź nazwa użytkownika jest unikalna lub nie z EventStore podczas wysyłania polecenia

EventSourcing działa doskonale, gdy mamy konkretny unikalny EntityID, ale kiedy próbuję uzyskać informacje z eventStore inne niż konkretny EntityId, mam ciężki czas.

Używam CQRS z Eventsourcingiem. W ramach event-sourcingu zapisujemy zdarzenia w tabeli SQL jako kolumny (EntityID(uniqueKey), EventType,EventObject (np. UserAdded)).

Więc podczas przechowywania EventObject tylko serializujemy obiekt DotNet i przechowujemy go w SQL, więc wszystkie szczegóły dotyczące zdarzenia UserAdded będą w formacie xml. Moim zmartwieniem jest to, że chcę się upewnić, że nazwa użytkownika, która jest obecna w db, powinna być unikalna.

Tak więc podczas wykonywania polecenia AddUser muszę zapytać EventStore (SQL db) czy dana nazwa użytkownika jest już obecna w eventStore. aby to zrobić, muszę serializować wszystkie zdarzenia UserAdded/UserEdited w Event store i sprawdzić, czy żądana nazwa użytkownika jest obecna w eventStore.

Ale w ramach poleceń CQRS nie mogą kwerendy może być ze względu na stan rasy.

tak, próbowałem przed wysłaniem polecenia AddUser po prostu zapytanie eventStore i uzyskać wszystkie nazwy użytkowników przez serializując wszystkie zdarzenia (UserAdded) i pobrać nazwy użytkowników i jeśli żądana nazwa użytkownika jest unikalna, a następnie strzelać polecenie else rzucanie wyjątek, że nazwa użytkownika już istnieje.

Tak jak przy powyższym podejściu, musimy odpytywać cały db i możemy mieć setki tysięcy zdarzeń / dzień.tak więc wykonanie zapytanie / deserializacja zajmie dużo czasu, co doprowadzi do problemów z wydajnością.

Szukam lepszego podejścia / sugestii do zachowania unikalnej nazwy użytkownika poprzez pobranie wszystkich nazw użytkowników z eventStore lub dowolnego innego podejścia

Author: James Z, 2015-07-13

3 answers

Tak więc twój Klient (osoba, która wydaje polecenia) powinien mieć pełną wiarę, że polecenie, które wysyła zostanie wykonane i musi to zrobić, upewniając się, że przed wysłaniem RegisterUserCommand żaden inny użytkownik nie jest zarejestrowany pod tym adresem e-mail. Innymi słowy, twój Klient musi przeprowadzić walidację, a nie Twoja domena, a nawet usługi aplikacji otaczające domenę.

Z http://cqrs.nu/Faq

Jest to najczęściej spotykane pytanie ponieważ nie jesteśmy wyraźnie wykonywanie operacji agregacji krzyżowej po stronie zapisu. Mamy, istnieje jednak kilka opcji:

Utwórz stronę do odczytu już przydzielonych nazw użytkowników. Make the client zapytaj stronę odczytu interaktywnie, gdy użytkownik wpisuje nazwę.

Utworzyć reaktywną sagę do oznaczania i deaktywacji kont, które były niemniej jednak utworzony z duplikatem nazwy użytkownika. (Czy przez ekstremalne zbieg okoliczności lub złośliwie lub z powodu wadliwego klient.)

Jeśli ostateczna spójność nie jest wystarczająco szybka dla Ciebie, rozważ dodanie tabela po stronie zapisu, mała lokalna strona odczytu, z już przydzielone nazwy. Dokonaj łącznej transakcji obejmującej wstawiam do tego stołu.

 10
Author: Matt,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-07-13 14:53:26

Jak często, nie ma prawidłowej odpowiedzi, tylko odpowiedzi, które pasują do Twojej domeny.

Czy jesteś w środowisku, które naprawdę wymaga natychmiastowej konsekwencji ? Jakie byłyby szanse na utworzenie identycznej nazwy użytkownika między momentem sprawdzania unikalności przez zapytanie (powiedzmy po stronie klienta) a momentem przetwarzania polecenia ? Czy Twoi eksperci ds. domen tolerują na przykład jeden na milion konfliktów nazw użytkowników (które można później zrekompensować) ? Czy będziesz miał milion użytkowników w pierwsze miejsce ?

Nawet jeśli wymagana jest natychmiastowa spójność, "nazwy użytkowników powinny być unikalne"... w jakim zakresie ? A Company ? An OnlineStore ? A GameServerInstance? Czy możesz znaleźć najbardziej ograniczony zakres, w którym musi trzymać ograniczenie unikalności i uczynić ten zakres zbiorczym korzeniem, z którego wykiełkuje nowy użytkownik ? Dlaczego rozwiązanie "replay all the useradded / useredited events"miałoby być w końcu złe, jeśli zagregowany Root sprawia, że te zdarzenia są małe i proste ?

 3
Author: guillaume31,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-07-13 17:26:22

Z GetEventStore (od Grega Younga) możesz użyć dowolnego ciągu jako agregateid/StreamId. Użyj nazwy użytkownika jako identyfikatora agregatu zamiast identyfikatorów GUID lub kombinacji takiej jak " mycompany.użytkowników.john" jako klucz i.. voila! Masz za darmo unikalność nazwy użytkownika!

 2
Author: Narvalex,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-09-29 12:50:32