Когда в игру вступают обработчики событий домена? - PullRequest
10 голосов
/ 06 декабря 2011

У меня есть простой предметный домен с двумя совокупными корнями и одной регулярной сущностью. Tenant, UserGroup и User, где в данном конкретном образце Tenant и User компенсируют два AggregateRoots .

Когда команда получена от уровня UI / Service, она достигает обработчика команд, который управляет доменом только для записи.

Можно сказать, что User вовсе не должен быть AggregateRoot , но, поскольку на него будут ссылаться другие, он не может быть обычным объектом. (Да?)

Эти два AggregateRoots должны взаимодействовать. User не может быть создан без принадлежности к UserGroup, который является сущностью в ограниченном контексте Tenant. Предположительно, мы можем создать, поскольку это простое ограничение, User через конструктор. User.Create(TenantId, UserGroupId)

Генерирует DomainEvent с Date, AggregateVersion и AggregateId (для пользователя). Теперь перейдем к размытым деталям.

Открыть фиксацию этого события в хранилище, это событие транслируется на шину (память, что угодно). В этот момент обработчики событий домена, подобно обработчикам команд, ловят созданного пользователя и уведомляют / манипулируют UserGroup *1027*, чтобы добавить UserId?

Мои мысли о том, чтобы решить эту проблему, идут в совершенно неверном направлении?

1 Ответ

7 голосов
/ 06 декабря 2011

A Saga может быть тем, что вы ищете.

Проще говоря: сага может быть реализована как обработчик событий, который прослушивает определенные события и выдает команды различным агрегатным корням или даже в контекстеГраницы.

В вашем случае это может выглядеть так:

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);
    }
}

Подробнее о сагах в этой статье Рината Абдуллина или смотреть "CQRS,условия гонки и саги - о боже! " от Udi Dahan

Обновление:

После нашего расширенного обсуждения в комментариях я постараюсь показать, какэто может работать под другим углом (псевдокод вперед).Надеемся, что это проливает свет на возможное решение:

// 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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...