Сага MassTransit с настойчивостью Redis дает метод Accpet не имеет исключения реализации

Я пытаюсь добавить настойчивость Redis в свою сагу, которая управляет вызовами на маршрутизацию (а также дополнительные сообщения другим потребителям в зависимости от результата маршрутизации) в надежде, что это решит еще одну проблему тайм-аута, которую я продолжаю .

Однако я получаю сообщение об ошибке, которое попадает в мою очередь saga_error в RabbitMQ.

Ошибка, показанная в сообщении:

Метод Accept в типе GreenPipes.DynamicInternal.Automatonymous.State из сборки AutomatonymousGreenPipes.DynamicInternalc83411641fad46798326d78fe60522c9, Version = 0.0.0.0, Culture = нейтральный, PublicKeyToken = null не имеет реализации

Мой код конфигурации корреляции:

InstanceState(s => s.CurrentState);

Event(() => RequestLinkEvent, x => x.CorrelateById(context => context.Message.LinkId).SelectId(y => y.Message.LinkId));
Event(() => LinkCreatedEvent, x => x.CorrelateById(context => context.Message.LinkId));
Event(() => CreateLinkGroupFailedEvent, x => x.CorrelateById(context => context.Message.LinkId));
Event(() => CreateLinkFailedEvent, x => x.CorrelateById(context => context.Message.LinkId));
Event(() => RequestLinkFailedEvent, x => x.CorrelateById(context => context.Message.LinkId));

Request(() => LinkRequest, x => x.UrlRequestId, cfg =>
            {
                cfg.ServiceAddress = new Uri($"{hostAddress}/{nameof(SelectUrlByPublicId)}");
                cfg.SchedulingServiceAddress = new Uri($"{hostAddress}/{nameof(SelectUrlByPublicId)}");
                cfg.Timeout = TimeSpan.FromSeconds(30);
            });

LinkId в приведенном выше коде всегда является уникальным Guid.

Проблема, кажется, возникает, когда сага считывает событие, которое было отправлено из моей маршрутной квитанции (будь то событие успеха или неудачи).

Пример неработающего интерфейса событий:

public interface ILinkCreated
{
    Guid? CorrelationId { get; set; }
    int DatabaseId { get; set; }
    Guid LinkId { get; set; }
    string LinkName { get; set; }
}

Если я вернусь к InMemorySagaRepository, все будет работать (локально). Я перепробовал так много разных комбинаций вещей и теперь наткнулся на кирпичную стену.

Я обновил все пакеты до последней версии. Я также проверял свою базу данных Redis и вижу, что экземпляр конечного автомата каждый раз работает правильно.

Я также видел, что у кого-то в группах Google была такая же проблема, но на его сообщение нет ответа.


person Ben Thomson    schedule 08.08.2018    source источник
comment
Опубликуйте свой код конфигурации корреляции.   -  person Alexey Zimarev    schedule 08.08.2018
comment
Я обновил свой пост   -  person Ben Thomson    schedule 08.08.2018
comment
Опубликуйте код для своего события, я предполагаю, что это интерфейс с методом, а методы не поддерживаются и не должны добавляться в контракты сообщений. Ваш Accept, вероятно, является таким методом.   -  person Chris Patterson    schedule 09.08.2018
comment
Я обновил свой пост. Как видите, это действительно простой интерфейс и не имеет методов (реализующий класс тоже идентичен). Первоначально я думал, что это могут быть мои интерфейсы, и поиграл с несколькими разными конфигурациями, но не повезло. Если вы думаете, что это может быть ошибка в MT, я могу попробовать все подключить и отладить через нее (я хотел бы иметь возможность каким-то образом помочь MT, потому что вы, ребята, были очень полезны, и мне нравится, как это работает).   -  person Ben Thomson    schedule 10.08.2018
comment
Я отлаживал через MassTransit.RedisIntegration и узнал больше. Ошибка возникает в методе Deserialize ‹T› (строка json) в TypedDatabase.cs. Если вы измените T на мой фактический класс (я скопировал его, чтобы проверить), а затем выполните Deserialize ‹MyClass›, ошибок не произойдет. Я думаю, что T представляет собой тип GreenPipes.DynamicInternal.Automatonymous.State, который, как мне кажется, создается программно в классе GreenPipes DynamicImplementationBuilder.cs. Я предполагаю, что это добавляет метод Accpet, но я недостаточно понимаю, что происходит, чтобы это исправить.   -  person Ben Thomson    schedule 23.08.2018
comment
Вот дерьмо, думаю, я только что понял это. Я сохраняю CurrentState в экземпляре как состояние, а не строку или int. Что за придурок.   -  person Ben Thomson    schedule 23.08.2018


Ответы (2)


Проблема здесь в запросе-ответе.

Работает это так:

  1. MT помещает идентификатор запроса в свойство состояния саги UrlRequestId
  2. Запрос отправлен
  3. Вы получаете ответ, ответ содержит адрес запрашивающей стороны и идентификатор запроса в своем заголовке.
  4. MT использует репозиторий саг, чтобы найти ваш экземпляр с помощью repo.Find(x => x.UrlRequestId == message.Headers.RequestId) (следовательно, это не настоящий код, но вот что происходит)
  5. Redis (или любой другой KVS) не поддерживает запросы, поэтому мы не поддерживаем запросы и в репозиториях саги, и вы получаете исключение «не реализовано»

Ваша спецификация корреляции для ответов не действует, поскольку Request всегда использует заголовки для поиска экземпляра саги, которому принадлежит ответ.

Вы можете обойти это, не используя запрос-ответ, а вместо этого генерируя событие, используя context.Publish(new LinkCreatedEvent { ... , CorrelationId = context.Message.CorrelationId }) и используя обычную корреляцию.

person Alexey Zimarev    schedule 08.08.2018
comment
К сожалению, это не решило проблему. Я удалил запрос-ответ, и возникла та же проблема. Ошибка возникает, когда сага пытается прочитать событие, которое, как мне кажется, опубликовано в маршрутной квитанции. - person Ben Thomson; 08.08.2018
comment
Ну, я не знал про маршрутную квитанцию, в вопросе она не упоминалась. Какая версия MT и GreenPipes у вас установлена? - person Alexey Zimarev; 08.08.2018
comment
Извините, это было в исходном вопросе, но больше в качестве примечания. Я обновил вопрос, чтобы было понятнее. Я использую версию 5.1.4 MT, которая установила версию 2.1.1 GreenPipes в качестве зависимости. - person Ben Thomson; 09.08.2018

Итак, чтобы ответить на свой вопрос и, возможно, пролить свет на мою глупость. На самом деле проблема была вызвана тем, как я настроил свой StateMachineInstance.

Вместо CurrentState типа State, как показано ниже:

public State CurrentState {get; set;}

Я должен был указать это как строку как таковую:

public string CurrentState { get; set;}

Теперь его можно правильно десериализовать в объект. Я подозреваю, что это могло вызвать проблемы с тайм-аутом в InMemorySagaRepository на моем промежуточном сервере.

person Ben Thomson    schedule 23.08.2018