MassTransit传奇/状态机未将请求响应返回到控制器 [英] MassTransit saga/statemachine not returning the request response to the controller

查看:60
本文介绍了MassTransit传奇/状态机未将请求响应返回到控制器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我觉得我已经很接近完成这项工作了,但似乎无法完全解决问题……

I feel like I'm so close to getting this working but can't seem to get it over the line...

我有一个带有saga/state机器的.NET Core ASP应用程序,在大多数情况下似乎运行良好.它:

I have a .NET Core ASP application with saga/state machine that seems to work well for the most part. It:

  1. 接收请求
  2. 发布由路由清单获取的事件
  3. 路由清单完成后,它会发布一个事件
  4. 该事件是传奇故事
  5. 传奇然后将请求发送给请求/响应使用者
  6. 回应又回到了传奇故事
  7. 然后我使用RespondAsync尝试将响应发送回原始调用控制器,但是but回没有结果

我的控制器如下:

private readonly IRequestClient<IRequestLink, IRequestLinkCompleted> _client;

public async Task<IActionResult> CreateLinkAsync([FromBody]CreateLinkRequest request)
{
        var requestLink = new RequestLink            {

            GroupName = $"{request.Name} Group",
            Name = request.Name,
            LinkId = Guid.NewGuid()
        };

        var result = await _client.Request(requestLink).ConfigureAwait(false);

        return Ok();
}

我的传奇的简化版本如下:

A cut down version of my saga looks like:

Request(() => LinkRequest, x => x.RequestId, cfg =>
        {
            cfg.ServiceAddress = new Uri($"rabbitmq://localhost/request_end_point_name");
            cfg.SchedulingServiceAddress = new Uri($"rabbitmq://localhost/request_end_point_name");
            cfg.Timeout = TimeSpan.FromSeconds(30);
        });


During(RequestReceived,
                When(LinkCreatedEvent)
                    .Request(LinkRequest, context => new SelectUrlByPublicId(context.Data.DatabaseId, context.Data.LinkId))
                    .TransitionTo(LinkRequest.Pending));

            During(LinkRequest.Pending,                
                When(LinkRequest.Completed)
                    .ThenAsync(context => context.RespondAsync(new RequestLinkCompleted
                    {
                        CorrelationId = LinkRequest.GetRequestId(context.Instance),
                        DatabaseId = context.Data.DatabaseId
                    }))
                    .Finalize());

最后在启动代码中,我将请求/响应配置为:

And finally in my start up code I configure the request/response as such:

services.AddScoped<IRequestClient<IRequestLink, IRequestLinkCompleted>>(x => new MessageRequestClient<IRequestLink, IRequestLinkCompleted>(_bus, new Uri($"{messageBusSettings.Host}/create_link_saga"), TimeSpan.FromSeconds(30)));

我猜 RespondAsync 调用没有使用正确的/原始的 requestId,但我不知道如何检查或更改它.有人可以帮忙吗?

I'm guessing that the RespondAsync call isn't using the right/original requestId but I've got no idea how I check or change that. can anyone help?

推荐答案

由于原始请求的上下文丢失,因此您基本上需要自己执行 RespondAsync 中的操作.

Since the context of the original request is lost, you need to do essentially what was being done in RespondAsync yourself.

  1. 从请求消息上下文保存 ResponseAddress
  2. 从同一上下文中保存 RequestId

在你的传奇中,当需要响应时,你需要使用 context.GetSendEndpoint(context.Instance.SavedResponseAddress) 然后调用 Send 设置 委托中的RequestId 以匹配原始上下文中保存的RequestId.

In your saga, when it's time to respond, you need to use context.GetSendEndpoint(context.Instance.SavedResponseAddress) and then call Send setting the RequestId in the delegate to match the saved RequestId from the original context.

现在,您可能需要将它们保存在路由清单变量中,因为您的传奇并没有得到命令,只是后续事件,但是最终效果是一样的,原始请求消息消失了,传奇也从未看到过

Now, you might need to save these in routing slip variables since your saga doesn't get the command, just the subsequent events, but the net effect is the same, the original request message is gone and never seen by the saga.

这篇关于MassTransit传奇/状态机未将请求响应返回到控制器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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