如何在 RegisterHandler 中处理 ServiceStack RabbitMQ 消息,第 2 部分 [英] How to Nak a ServiceStack RabbitMQ message within the RegisterHandler, Part 2

查看:46
本文介绍了如何在 RegisterHandler 中处理 ServiceStack RabbitMQ 消息,第 2 部分的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

作为对我的原始问题的跟进,当从我的网络服务抛出异常时,它们被 ServiceStack 转换为更多HTTP 友好响应代码,这对感兴趣的一方来说是有问题的,Windows 服务(MQ 逻辑服务器)只收到 500 内部服务器错误.

As a follow up to my original question, when throwing exceptions from my web service, they are converted by ServiceStack into more HTTP friendly response codes, which is problematic for the interested party, a windows service (MQ Logic Server) which only receives a 500 internal server error.

有没有办法将 OutBoundAgentNotFoundException 保留在内部异常属性中,以便我可以在其他地方检查它并对其采取行动?

Is there a way to persist the OutBoundAgentNotFoundException in the inner exception property so that I can inspect it elsewhere and action off of it?

Web 服务端点:

//This is a callback that the phone system uses to notify us of what routing decision was made.
//It's now up to this method to assign it to the agent, or send it back to the queue via exceptions
public object Get(OutBoundILeadRequest request)
{
    if (request == null) throw new ArgumentNullException("request");

    _log.Debug("OutBoundILeadRequest: {0}".Fmt(request.ToJson()));

    // assign the agent to the lead

    // Agent phone extension is called, 1 and 2 are pressed, accepts call "Agent":"9339","Status":"0"
    // Agent phone extension is called, 1 and 2 are pressed, but no answer or wrong number "Agent":"9339","Status":"0"
    if (request.Status == "0" && !string.IsNullOrEmpty(request.Agent))
    {
        //assignment

    }


    // throw will send it back to the queue and then it will be re-tried, then it will be sent to the dlq  
    // https://stackoverflow.com/questions/27519209


    // Agent phone extension is called, but no response from Agent => "AgentsTalking":"0","Status":"3" 
    // this action puts them in NOT READY (Cisco Agent Desktop)            
    if (request.Status == "3" && !string.IsNullOrEmpty(request.AgentsTalking) && request.AgentsTalking == "0")
    {
        //retry

    }


    // No one assigned to this Phone Queue is in a ready state => "AgentsTalking":"number of agents on the phone","Status":"1" (Potentially can redistribute the phone)
    if (request.Status == "1" && !string.IsNullOrEmpty(request.AgentsTalking) && request.AgentsTalking != "0")
    {
        //retry
        throw new OutBoundAgentNotFoundException("<NEW MEWSSAGE HERE 1>");
    }

    // No one assigned to this Phone Queue is in a ready state => "AgentsTalking":"0","Status":"1" (No one in the Call Center)
    if (request.Status == "1" && !string.IsNullOrEmpty(request.AgentsTalking) && request.AgentsTalking == "0")
    {
        //retry
        throw new OutBoundAgentNotFoundException("<NEW MEWSSAGE HERE 2>");
    }
    // 'should' not get here 
    throw new OutBoundAgentNotFoundException("<NEW MEWSSAGE HERE 3>");
}

在windows服务中注册处理程序:

registration of the handler in the windows service:

mqServer.RegisterHandler<OutboundILeadPhone>(m =>
{
    var db = container.Resolve<IFrontEndRepository>();
    db.SaveMessage(m as Message);
    return ServiceController.ExecuteMessage(m);
}, PhoneApi.OnExceptionLeadInformation , 1);

windows 服务异常处理程序:

windows service exception handler:

public static void OnExceptionLeadInformation(IMessage<OutboundILeadPhone> request, Exception exception)
{

      // Here is where I'd like to inspect the type of exception and Nak/requeue the Message

}

windows 服务端点:

windows service endpoint:

//This method is being called in response to a message being published by the 
//RabittMQ Broker (Queue mq:OutboundILeadPhone.inq)
//The result of sucessuflully processing this message will result in a message being published to 
// (Queue mq:OutboundILeadPhone.outq)
public object Post(OutboundILeadPhone request)
{
    if (request == null) throw new ArgumentNullException("request");

    //By default there is only 1 worker thread (per message type) 
    //that's used to process the request, so you can just add a 
    //Thread.Sleep() in your Service to delay processing of the request 
    //as the next request only gets processed after the previous one has finished. 

    int delay = 2000;
    Thread.Sleep(delay); //todo:smp configurable

    var profiler = Profiler.Current;
    using (profiler.Step("PhoneApi DirectApiServices POST OutboundILeadPhone"))
    {
        try
        {





        }
        catch (Exception exception)
        {
            _log.Error(request.ToJson(), exception);
            throw;
        }

    }
    /*_log.Debug(profiler.GetTimingHierarchy());*/

    return null;
}

谢谢,斯蒂芬

推荐答案

我刚刚提交了一个更改,将原始异常存储在 InnerException 中,MQ 错误处理程序现在通过 MessageHandler 处理消息,因此您的错误回调现在可以访问检索消息的原始 MqClient 实例,可用于 NAK 消息,例如:

I've just committed a change that will store the original exception in InnerException and the MQ Error handler now gets passed the MessageHandler processing the message so your error callback now has access to the original MqClient instance that retrieved the message, which can be used to NAK the message, e.g:

public CustomException LastCustomException;

public void HandleMqCustomException(IMessageHandler mqHandler, 
    IMessage<MqCustomException> message, Exception ex)
{
    LastCustomException = ex.InnerException as CustomException;

    bool requeue = !(ex is UnRetryableMessagingException)
        && message.RetryAttempts < 1;

    if (requeue)
    {
        message.RetryAttempts++;
    }

    message.Error = ex.ToResponseStatus();
    mqHandler.MqClient.Nak(message, requeue: requeue, exception: ex);
}

这是来自 MqAppHostTests 显示了如何从服务中检索原始异常并从原始 MQ 客户端实例中获取消息.

This is is from MqAppHostTests which shows how to retrieve the original exception from the Service and Nak the message from the original MQ Client instance.

此更改可从 v4.0.35+ 开始,现在 可在我的获取.

This change is available from v4.0.35+ that's now available on MyGet.

这篇关于如何在 RegisterHandler 中处理 ServiceStack RabbitMQ 消息,第 2 部分的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆