Wszelkie informacje, które kruszywo wymaga do podjęcia decyzji biznesowych, powinny być przechowywane jako część stanu kruszywa. W związku z tym, po odebraniu polecenia, aby wpłacić pieniądze na konto klienta, powinieneś już mieć stan bieżący/aktualizacyjny dla tego klienta, który może zawierać bieżące saldo dla każdego z jego kont.
Sugerowałbym również, że agregat nigdy nie powinien iść do modelu odczytu w celu pobrania informacji. W zależności od tego, co próbujesz osiągnąć, możesz wzbogacić komendę o dodatkowe szczegóły z modelu odczytu (gdzie stan nie jest krytyczny), ale agregat sam powinien wyciągnąć swój własny znany stan.
EDIT
Po ponownym przeczytaniu pytanie, zdaję sobie sprawę, że mówisz o śledzenie stanu na wielu agregatów. To wchodzi w królestwo sagi. Możesz stworzyć sagę, która śledzi próg wymagany do uzyskania 10% najlepszych wyników. Tak więc, gdy klient dokonuje depozytu, saga może śledzić, gdzie umieszcza je w rankingu. Jeśli klient przekroczył nagłówek, możesz opublikować polecenie z sagi, aby wskazać, że spełnia on wymagane kryteria.
W twoim przypadku Twoja saga może śledzić całkowitą kwotę wszystkich depozytów, więc po dokonaniu depozytu można podjąć decyzję, czy klient znajduje się obecnie w top 10%. Inne pytania, które możesz zadać sobie samemu ... jeśli klient wpłaci X $ kwoty pieniędzy, a następnie natychmiast rozszerzy $ Y, aby wrócić z powrotem do threashold; co powinno się stać? Itp
Bardzo surowy agregat/metody handle saga ...
public class Client : Aggregate
{
public void Handle(DepositMoney command)
{
// What if the account is not known? Has insufficient funds? Is locked? etc...
// Track the minimum amount of state required to make whatever choice is required.
var account = State.Accounts[command.AccountId];
// Balance here would reflect a point in time, and should not be directly persisted to the read model;
// use an atomic update to increment the balance for the read-model in your denormalizer.
Raise(new MoneyDeposited { Amount = command.Amount, Balance = account.Balance + command.Amount });
}
public void Handle(ElevateClientStatus command)
{
// you are now a VIP... raise event to update state accordingly...
}
}
public class TopClientSaga : Saga
{
public void Handle(MoneyDeposited e)
{
// Increment the total deposits... sagas need to be thread-safe (i.e., locked while state is changing).
State.TotalDeposits += e.Amount;
//TODO: Check if client is already a VIP; if yes, nothing needs to happen...
// Depositing money itself changes the 10% threshold; what happens to clients that are no longer in the top 10%?
if (e.Balance > State.TotalDeposits * 0.10)
{
// you are a top 10% client... publish some command to do whatever needs to be done.
Publish(new ElevateClientStatus { ClientId = e.ClientId, ... });
}
}
// handle withdrawls, money tranfers etc?
}
Dziękuję za odpowiedź Calgary, masz mój punkt widzenia. Muszę przeczytać więcej o wzorze Saga, a następnie odpowiedzieć sformułowaną opinią. –
, więc sugerujesz, że mam sagę, która jest tworzona i usuwana z aplikacją, jak singleton. ta saga śledzi całkowitą kwotę zdeponowanych pieniędzy. każdy klient, który wpłacił pieniądze, dodaje sumę do całkowitej sumy sagi. do przechowywania całkowitej kwoty używam magazynu zdarzeń? Pytam, ponieważ po uruchomieniu aplikacji muszę załadować bieżącą całkowitą ilość. to ma sens? dzięki –
@JP - saga będzie zarządzać własnym stanem. W pewnym momencie utworzysz 'Oddział' lub' 'Bank', który może uruchomić sagę do śledzenia depozytów ogółem. Za każdym razem, gdy dokonywany jest depozyt lub inne powiązane zdarzenie, stan sagi byłby odzyskiwany (idealnie buforowany w pamięci), tak, że zawsze zna on sumę bieżącą. Jeśli twoja aplikacja musi znać sumę z innych powodów, to być może suma staje się własnością stanu skupienia 'bank' lub' branch'. Twoje agregaty/sagi są autorytetem dla wszystkich danych, nie chcesz iść do modelu odczytu dla tego typu informacji. Ma sens? –