ServiceStack MQ:如何在RequestContext

时间:2018-06-16 10:47:47

标签: servicestack messaging multi-tenant requestcontext

我正在使用ServiceStack开发基于JWT的多租户系统。 JWT令牌包含分片信息,我使用JwtAuthProvider按照http://docs.servicestack.net/jwt-authprovider的说明将JWT令牌转换为会话对象。

现在,我想使用ServiceStack MQ进行异步处理。 MQ请求需要知道分片信息,因此我在执行它之前填充请求上下文,如下所示

mqServer.RegisterHandler<EmployeeAssignedToProject>(m =>
            {
                var req = new BasicRequest { Verb = HttpMethods.Post };
                var sessionKey = SessionFeature.GetSessionKey(m.GetBody().SessionId);
                var session = HostContext.TryResolve<ICacheClient>().Get<Context>(sessionKey);
                req.Items[Keywords.Session] = session;
                var response = ExecuteMessage(m, req);
                return response;
            });

此处,Context是我的自定义会话类。这项技术源于http://docs.servicestack.net/messaging#authenticated-requests-via-mq的指示。由于我在req的上下文中执行了该消息,因此我认为我应该能够解析Context,如下所示

container.AddScoped<Context>(c =>
        {
            var webRequest = HostContext.TryGetCurrentRequest();
            if (webRequest != null)
            {
                return webRequest.SessionAs<Context>();
            } else
            {
                return HostContext.RequestContext.Items[Keywords.Session] as Context;                    
            }
        });

但是,HostContext.RequestContext.Items始终为空。所以问题是,如何从消息处理程序注册码中填充HostContext.RequestContext.Items

我试图深入了解一下ServiceStack代码,发现ExecuteMessage(IMessage dto, IRequest req)中的ServiceController似乎没有填充RequestContext中的数据。对于我的情况,在服务实例中获取会话有点太晚了,因为服务实例依赖于某些数据库连接,其分片信息保存在会话中。

1 个答案:

答案 0 :(得分:1)

无法从IOC解析相同的请求上下文实例。请求上下文实例在MQ RegisterHandler<T>()中创建,您可以在IRequest.Items属性中添加自定义数据,例如:

mqServer.RegisterHandler<EmployeeAssignedToProject>(m =>
{
    var req = new BasicRequest { Verb = HttpMethods.Post };
    req.Items[MyKey] = MyValue; //Inject custom per-request data
    //...
    var response = ExecuteMessage(m, req);
    return response;
});

IRequest实例在整个请求管道中以及您服务中的base.Request可用。它不能从您的IOC注册中获得,因此您在调用依赖项时需要将其作为参数传递,例如:

public class MyServices : Service
{
    public IDependency MyDep { get; set; }

    public object Any(MyRequest request) => MyDep.Method(base.Request, request.Id);
}