Quando entrano in gioco i gestori di eventi di dominio?
-
28-10-2019 - |
Domanda
Ho un semplice dominio di esami di due radici aggregate e un'entità regolare.Tenant
, UserGroup
e User
dove in questo particolare campione il Tenant
e User
compensare i due Aggregateroots.
Quando viene ricevuto un comando dal livello dell'interfaccia utente/servizio, raggiunge il gestore dei comandi che manipola il dominio di scrittura.
Potresti dire che User
non dovrebbe essere un Aggregatereot Per niente ma poiché sarà referenziato da altri, non può essere un'entità regolare. (sì?)
Questi due aggregateroot devono comunicare. UN User
non può essere creato senza appartenere a a UserGroup
, che è un'entità nel contesto limitato di Tenant
. Presumibilmente, possiamo creare, poiché è un semplice vincolo, un utente tramite il costruttore. User.Create(TenantId, UserGroupId)
Genera un DomainEvent
con data, aggregateversion e aggregateid (dell'utente). Ora arriviamo alle parti sfocate.
Aperto commettendo questo evento nel negozio, questo evento viene trasmesso sul bus (memoria, qualunque cosa). È questo il punto in cui i gestori di eventi del dominio, simili ai gestori di comandi, catturano l'utente creato e notifica/manipola il Tenant
'S UserGroup
Per aggiungere il UserId
?
Sono i miei pensieri sulla risoluzione di questo per andare nella direzione del tutto sbagliata?
Soluzione
UN Saga
Potrebbe essere quello che stai cercando.
In poche parole: una saga può essere implementata come un gestore di eventi che ascolta eventi specifici e problemi comandi a diverse radici aggregate o persino attraverso i confini del contesto.
Nel tuo caso potrebbe sembrare così:
public class RegisterUserSaga : Handles<UserCreated>
{
public void Handle<UserCreated>(UserCreated evnt) {
var tenantId = // you probably know how to find this
var groupId = // same here
var command = new RegisterUserForTenant(evnt.UserId, tenantId, groupId);
Bus.Send(command);
}
}
Leggi di più sulle saghe in Questo articolo Di Rinat Abdullin o Watch "CQR, condizioni di gara e saghe - oh mio!" di Udi Dahan
Aggiornare:
Dopo la nostra discussione estesa nei commenti proverò a mostrare come questo potrebbe funzionare da un angolo diverso (pseudo codice a venire). Speriamo che faccia un po 'più di luce su una possibile soluzione:
// Aggregates:
Tenant
Guid TenantId
List<Guid> UserGroups
UserGroup
Guid UserGroupId
List<Guid> Users
User
Guid UserId
Some more details
// Commands:
RequestRegistration(userId, userGroupId, user details)
CreateUser(userId, user details)
AddUserToGroup(userId, userGroupId)
// The initial command would be:
RequestRegistration (leading to a RegistrationRequested event)
// The Saga handles the RegistrationRequested and all subsequent events
UserRegistrationSaga
Handle(RegistrationRequested)
-> send CreateUser command (which eventually leads to a UserCreated event)
Handle(UserCreated)
-> send AddUserToGroup command (-> UserAddedToGroup event)
Handle(UserAddedToGroup)
-> Done