Rebus - выход из приложения методом Handle - PullRequest
1 голос
/ 26 июня 2019

Я реализую расширенный шаблон (https://www.enterpriseintegrationpatterns.com/patterns/messaging/DataEnricher.html), используя очередь команд / потребителей, где потребитель является обогащателем и публикует обогащенное сообщение в отдельной конечной точке (в данном случае это база данных SQL). Потребитель работает как HostedService, который реализует токен отмены.

Поскольку я потребляю команды из одного транспорта и публикую события в другое, есть вероятность, что транспорт, который я публикую, не работает, а тот, из которого я потребляю, работает. В этом случае я хотел бы зарегистрировать ошибку и остановить мой размещенный сервис. Однако я не могу понять, как это будет работать, поскольку все вызовы метода Handle уже обрабатывают исключения, и я не могу получить доступ к своему токену отмены. У кого-нибудь есть идеи?

Это черновик того, что я хочу сделать.

    public async Task Handle(EditedEventData message)
        {
            var enricher = _enricherFactory.GetEnricher(message);
            object @event = await enricher.EnrichAsync(message);

            var transformers = _transformerFactory.GetTransformers(message);
            var messages = new List<object>();

            foreach (var transformer in transformers)
            {
                messages.AddRange(transformer.Transform(@event, message));
            }

            foreach (var item in messages)
            {
                try
                {
                    await _bus.Publish(item);
                }
                catch (Exception ex)
                {
                    _logger.LogCritical("Publishing event message {@item} failed with error {ex}", item, ex);
                    //how do I exit from here?
                }
            }
        }

1 Ответ

1 голос
/ 26 июня 2019

На вашем месте я бы придумал какую-то службу приложений, например IApplicationControlService, который вы можете настроить для внедрения в ваши обработчики с использованием любого контейнера IoC, который вы используете.

Это может выглядеть примерно так:

public interface IApplicationControlService
{
    void RequestApplicationShutdown();
}

и тогда ваш код может просто

public class YourHandler : IHandleMessages<EditedEventData>
{
    readonly IApplicationControlService applicationControlService;

    public YourHandler(IApplicationControlService applicationControlService)
    {
        this.applicationControlService = applicationControlService;
    }

    public async Task Handle(EditedEventData message)
    {
        // (...)

        foreach (var item in messages)
        {
            try
            {
                await _bus.Publish(item);
            }
            catch (Exception ex)
            {
                _logger.LogCritical("Publishing event message {@item} failed with error {ex}", item, ex);

                applicationControlService.RequestApplicationShutdown();
            }
        }
    }
}

запросить остановку приложения при возникновении ошибки.

Реализация IApplicationControlService может тогда быть чем-то вроде

public class BruteForceApplicationControlService : IApplicationControlService
{
    public void RequestApplicationShutdown()
    {
        Environment.FailFast("you should probably not do THIS ?");
    }
}

или что-то более мягкое the суть в том, что вы сможете предоставить способ запроса приложения на закрытие «извне», скорее всего, из места, где ваше приложение собрано (т. Е. «корень композиции» )

...