Дождитесь окончания саги Mass Transit - PullRequest
0 голосов
/ 05 марта 2019

Я пытаюсь создать сагу, которая возвращает вызывающему результат, как шаблон запроса / ответа.Я могу запустить сагу, если вызову метод 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();

Как я могу заставить вызывающего абонента запустить сагу и ждать, пока она не закончится и что-то сделать с ее ответом

1 Ответ

0 голосов
/ 05 марта 2019

Я смог найти решение сам.

Проблема заключалась в том, что я был озадачен тем, как вызвать сагу с помощью вызова Request.Я думал, что должен объявить

Request<in TInstance, TRequest, TResponse>

(Автоматизированный)

, который не работал для меня.

И событие, которое я использовал для запуска саги, имело своеинтерфейс

Event<IStartSaga>

, который не был тем, который я использовал при вызове метода Request

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();

Так что исправление было изменить объявление события на

Event<MyRequest>

Теперь сага начинается всякий раз, когда я вызываю запрос с сообщением MyResquest.И вызывающая сторона ждет ответа от саги.

Я внес некоторые другие изменения, чтобы немного очистить код, и перенес его в github.

...