Есть ли какой-нибудь способ сохранить контекст событий домена незнакомым с NServiceBus 6 и удалением IBus?

Я сталкиваюсь с ситуацией, когда в настоящее время мы используем интерфейс IBus (NServiceBus v5) в обработчиках событий домена для отправки команд в бэкэнд-сервис для обработки. С IBus эти команды могут быть отправлены независимо от того, что вызвало событие, будь то при получении запроса Web API или в качестве части обработчика NServiceBus (модель общего домена). Но в NServiceBus v6 с переходом к контекстно-зависимым интерфейсам, IEndpointInstance или IMessageHandlerContext, кажется, что мои обработчики событий домена теперь должны стать осведомленными о контексте. И, кроме того, похоже, что IMessageHandlerContext доступен только через внедрение метода, поэтому мне может потребоваться разбросать этот параметр по всему стеку вызовов?

Есть ли какой-то подход, который я не вижу, с помощью которого я могу не знать контекст обработчиков событий моего домена? Или я следовал какой-то плохой практике, которая раскрывается через этот запах кода?

РЕДАКТИРОВАТЬ

Вот попытка свести сценарий к наиболее значимым частям. В модели домена есть порядок, статус которого может измениться. Когда статус заказа меняется, мы запускаем событие домена StatusChanged через издателя. Подписчик на это конкретное событие домена записывает запись об изменении статуса, а также отправляет команду NServiceBus для передачи этого статуса - обработчик для этой конкретной команды будет следовать некоторой дополнительной логике в отношении того, отправлять ли электронные письма, SMS-сообщения и т. Д.., детали которого я не думаю, имеют отношение.

Заказать доменный объект

public class Order
{
    private OrderStatusCode _statusCode;

    public OrderStatusCode StatusCode
    {
        get { return _statusCode; }
        private set { _statusCode = value; }
    }

    public void ChangeStatus(OrderStatusCode status)
    {
        Status = status;

        Publish(new StatusChanged(CreateOrderSnapshot(), status));
    }

    protected void Publish<T>(T @event) where T : IDomainEvent
    {
        DomainEventPublisher.Instance.Publish(@event);
    }
}

Издатель событий домена

public class DomainEventPublisher : IDomainEventPublisher
{
    private static IDomainEventPublisher _instance;
    public static IDomainEventPublisher Instance
    {
        get { return _instance ?? (_instance = new DomainEventPublisher()); }
    }

    public ISubscriptionService SubscriptionService { get; set; }

    public void Publish<T>(T @event) where T : IDomainEvent
    {
        if (SubscriptionService == null) return;

        var subscriptions = SubscriptionService.GetSubscriptions<T>();
        subscriptions.ToList().ForEach(x => PublishToConsumer(x, @event).GetAwaiter().GetResult());
    }

    private static async Task PublishToConsumer<T>(IEventSubscriber<T> x, T eventMessage) where T : IDomainEvent
    {
        await x.HandleEvent(eventMessage);
    }
}

Обработчик событий домена изменен статус

public class StatusChangedHandler : IEventSubscriber<StatusChanged>
{
    private readonly IBus _bus;
    private readonly IOrdersRepository _ordersRepository;

    public StatusChangedHandler(IBus bus, IOrdersRepository ordersRepository)
    {
        _bus = bus;
        _ordersRepository = ordersRepository;
    }

    public async Task HandleEvent(StatusChanged @event)
    {
        var statusTrailEntry = new OrderStatusTrailEntry(@event.OrderSnapshot, @event.Status);

        var txOptions = new TransactionOptions { IsolationLevel = IsolationLevel.ReadCommitted };
        using (
            var scope = new TransactionScope(TransactionScopeOption.Required, txOptions))
        {
            await _ordersRepository.SaveStatusTrail(statusTrailEntry);

            if (communicateStatus)
            {
                _bus.Send(new SendCommunicationCommand(@event.OrderSnapshot, @event.Status));
            }
            scope.Complete();
        }
    }
}

Дело в том, что до сих пор ни одному из приведенного выше примера кода не требовалось знать, изменилось ли состояние в результате запроса, поступающего через запрос Web API, или в результате изменения состояния в контексте сообщения NServiceBus. обработчик (внутри службы Windows) - интерфейс IBus не зависит от контекста. Но с различием между IEndpointInstance и IMessageHandlerContext в NServiceBus v6 я не чувствую, что у меня такая же гибкость.

Если я правильно понимаю, я могу зарегистрировать IEndpointInstance в своем контейнере и внедрить его в EventSubscriber, так что я буду покрыт в случае вызова веб-API, но мне также потребуется добавить IMessageHandlerContext в качестве параметра опционально передаваться через стек вызовов из ChangeStatus в Publisher и, наконец, в подписчик событий домена, если происходит изменение состояния в контексте обработчика сообщений. На самом деле не хочется добавлять этот параметр по всему стеку вызовов.

0 ответов

Другие вопросы по тегам