Я пытаюсь создать сагу, которая возвращает вызывающему результат, как шаблон запроса / ответа.Я могу запустить сагу, если вызову метод Send, но не отправив запрос.
Итак, логика саги работает нормально, но ничего не возвращает клиенту.
Или отправка запроса обрабатывается его потребителем и возвращает ответ клиенту, но никогда не запускает сагу.
ОБНОВЛЕНИЕ: Ответ на masstransit отложенный ответ вsagas , кажется, не относится к моему вопросу по двум причинам:
1) Я не смог запустить сагу, вызвав метод Request;
2) Если явызовите метод Send для отправки запроса и, позднее, отправьте ответ, поток вызывающей стороны не ждет возврата ответа, прежде чем перейти к следующей строке кода;
[END OFОБНОВЛЕНИЕ]
Полный код здесь .Ниже приведены более подходящие фрагменты:
Вот класс саги:
public class MySaga : MassTransitStateMachine<MySagaState>
{
public static Uri address = new Uri($"loopback://localhost/req_resp_saga");
public Event<IStartSagaCommand> StartSaga { get; private set; }
public Request<MySagaState, MyRequest, MyResponse> SomeRequest { get; private set; }
public MySaga()
{
InstanceState(s => s.CurrentState);
Event(() => StartSaga,
cc =>
cc.CorrelateBy(state => state.Data, context => context.Message.Data)
.SelectId(context => Guid.NewGuid()));
Request(() => SomeRequest, x => x.NullableCorrelationId, cfg =>
{
cfg.ServiceAddress = address;
cfg.SchedulingServiceAddress = address;
cfg.Timeout = TimeSpan.FromSeconds(30);
});
Initially(
When(StartSaga)
.Then(context =>
{
context.Instance.Data = context.Data.Data;
})
.ThenAsync(
context => Console.Out.WriteLineAsync($"Saga started: " +
$" {context.Data.Data} received"))
.Request(SomeRequest, context => new MyRequest() { CorrelationId = context.Instance.CorrelationId, RequestMessage = "Please do this" })
.TransitionTo(SomeRequest.Pending)
.ThenAsync(context => Console.Out.WriteLineAsync($"Transition completed: " +
$" {(context.Instance.CurrentState == SomeRequest.Pending ? "pending" : "done")} received"))
//.Then(context =>
//{
// var endpoint = context.GetSendEndpoint(address).GetAwaiter().GetResult();
// endpoint.Send(new MyResponse() { CorrelationId = context.Instance.CorrelationId, ResponseMessage = "Your wish is my command" });
//})
);
During(SomeRequest.Pending,
When(SomeRequest.Completed)
.ThenAsync(
context => Console.Out.WriteLineAsync($"Saga ended: " +
$" {context.Data.ResponseMessage} received"))
.Finalize()
);
}
}
Это запускает сагу, но не дожидается ее окончания и ответа:
var address = new Uri($"loopback://localhost/req_resp_saga");
var endPoint = bus.GetSendEndpoint(address)
.Result;
endPoint.Send<IStartSagaCommand>(new { Data = "Hello World!!" });
И это ждет ответа, но не затрагивает сагу:
var address = new Uri($"loopback://localhost/req_resp_saga");
var requestClient = new MessageRequestClient<MyRequest, MyResponse>(bus, address, TimeSpan.FromSeconds(30));
var response = requestClient.Request(new MyRequest() { CorrelationId = Guid.NewGuid(), RequestMessage = "Please do this" })
.GetAwaiter()
.GetResult();
Как я могу заставить вызывающего абонента запустить сагу и ждать, пока она не закончится и что-то сделать с ее ответом