Получение ConsumeContext недоступно при использовании MassTransit и Automatonymous Publish после предыдущего использования RaiseEvent

Если мы настроим сагу и сразу Publish(context => ...), то сообщение успешно попадет в шину.

Если, однако, у нас есть что-то вроде

Initially(
  When(SomeCommand)
     .Then(context => { context.Instance.SomeField = 5 })
     .TransitionTo(SomeState)
     .Then(context => this.RaiseEvent(context.Instance, SomeEvent)));

During(SomeState,
  When(SomeEvent)
     // ConsumeContext is not available here
     .Publish(context => new SomeEventClass
        {
           Foo = context.Instance.SomeField
        })
     .Finalize());

Машина также никогда не переходит в состояние Final, предположительно из-за исключения, обнаруживающего ConsumeContext.

Мы видели некоторые ссылки на передачу ConsumeContext в качестве параметра в Publish(), однако неясно, в каком контексте это нужно (Intellisense просто ссылается на context1, context2, context3 и т. Д.).

Есть ли способ использовать Publish() после того, как RaiseEvent() уже был вызван? Если нет, есть ли способ опубликовать событие с помощью другого механизма?

Версия MassTransit - 5.1.5, а Automatonymous - 4.1.2.


ИЗМЕНИТЬ На основе ответа Криса Паттерсона здесь мы попытались добавить нижеприведенное за пределами любых Initially или During

WhenEnter(NewState, state => state.Publish(context => 
    new EventClass { Foo = context.Instance.Foo }
  )
  .Finalize();

Однако он по-прежнему ничего не публикует, и состояние никогда не переходит на Final. Если мы добавим Then, он также никогда не попадет в этот блок кода. Похоже, что никаких исключений не происходит. Мы также пробовали использовать When(SomeState.Enter), но он тоже не работает.

Дополнительный вопрос: возможно, это поможет мне понять, почему Publish и RaiseEvent не очень хорошо сочетаются друг с другом - зачем Publish нужен ConsumeContext? Это для того, чтобы найти автобус и крепления?


person Daniel    schedule 05.11.2018    source источник
comment
Прежде чем пытаться взглянуть на это, могли бы уточнить, в чем причина возникновения внутреннего события после перехода в следующее состояние, при котором одно сообщение публикуется и завершается? Разве вы не можете опубликовать и завершить прямо на этом этапе?   -  person Alexey Zimarev    schedule 05.11.2018
comment
@AlexeyZimarev, это огромное упрощение. Сценарий таков, что у нас должно произойти множество событий и действий, и мы хотим иметь возможность повторить попытку в определенном состоянии. Только когда все внутренние события произошли, мы хотим опубликовать окончательное сообщение. Дайте мне знать, если это непонятно.   -  person Daniel    schedule 05.11.2018
comment
Мы тоже так поступаем, но всегда пользуемся сообщениями ...   -  person Alexey Zimarev    schedule 05.11.2018
comment
@AlexeyZimarev не могли бы вы привести пример? Ни одна из координируемых служб не публикует сообщения, и возникает много накладных расходов (классы сообщений, классы потребителей), если мы идем по маршруту использования сообщений, а не внутренних событий.   -  person Daniel    schedule 05.11.2018


Ответы (2)


Вы сможете добавить

When(SomeState.Enter)

в ваш Initially раздел, и он будет использовать существующий контекст. Создавая новый EventContext с RaiseEvent, вы не сохраняете ConsumeContext.

Вы также можете добавить WhenEnter(SomeState) вне любого блока Initially или During.

person Chris Patterson    schedule 05.11.2018
comment
мы пробовали оба, и ни один из них, похоже, не работал. См. Мою правку выше. - person Daniel; 07.11.2018

Решением этого оказалось использование этого:

.Then(context => context.Raise(SomeEvent))

вместо этого:

.Then(context => this.RaiseEvent(context.Instance, SomeEvent))

Теперь это имеет смысл - последний (как упомянул Крис Паттерсон) создает новый EventContext, а первый использует данное context. Мы не знали, что Raise был методом, доступным в переданном в context.

person Daniel    schedule 08.11.2018