首页 > 解决方案 > Rebus - 从 Handle 方法中退出应用程序

问题描述

我正在使用一个命令/消费者队列实现一个丰富器模式(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?
                }
            }
        }

标签: rebus

解决方案


如果我是你,我会想出某种应用程序服务,例如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 ");
    }
}

或更温和的东西——关键是,您将能够提供一种方法来请求您的应用程序“从外部”关闭,很可能是从您的应用程序组装的地方(即“组合根”


推荐阅读