akka-persistence (cqrs?) событийный аутсорсинг и побочные эффекты - PullRequest
0 голосов
/ 07 июня 2018

Я пытаюсь выяснить, как смоделировать состояние удаленного устройства IoT с постоянным субъектом, например:

Пользователь хочет включить свет, чтобы мы максимальнологический.

  1. Пользователь отправляет OnCommand
  2. постоянный субъект получает команду, генерирует LightTurnedOnEvent и обновляет свое состояние до on

Так что это имеет смысл, но проблема здесь в том, что свет фактически никогда не включается.Итак, тогда мы создадим LightControlActor, который знает низкоуровневое аппаратно-управляемое вуду.Этот актер слушает LightTurnedOnEvent, и когда он получает это, он делает это и включает свет.

Круто, теперь у нас включен свет!Но не счастлив.LightTurnedOnEvent вроде как лежит здесь, свет еще не включен.Следуя этой логике, * 109 * должен быть сгенерирован LightControlActor, а мой постоянный субъект должен сгенерировать SentRequestToTurnOnLight, но теперь это усложняется для меня со всей различной семантикой.

  1. Пользователь отправляет OnCommand
  2. Постоянные актеры получают OnCommand генерируют RequestedLightTurnOnEvent и устанавливают состояние в ожидание.

  3. LightController обнаруживает RequestedLightTurnOnEvent и пытается повернутьна свет во внешней системе.

И что тогда?Теперь, как мне обновить состояние персистента?Разве LightController отправил какую-то странную команду SetStateToOnCommand?

Так как мне обновить постоянное состояние, когда свет фактически включен?

Ответы [ 2 ]

0 голосов
/ 08 июня 2018

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

Идея с событиями заключается в том, что они имеют в своем ограниченном контексте .В вашем случае LightTurnedOnEvent принадлежит постоянному субъекту и имеет строгое значение только в его контексте.От POV владельца актера свет должен быть включен, и будущее TurnOnCommand не изменит это состояние, новое событие не будет излучено (оно идемпотентно).

Если вы хотите, чтобы это событие имело другие последствия, вам нужна Сага (или как вы хотите ее называть), которая отреагирует на это событие и отправит другую команду другому актеру в другом контексте, т.е. вконтекст HW.Этот актер HW будет испускать свои собственные события, относящиеся только к его контексту, то есть LightBulbCoupledToPowerSource или что-то вроде этого;его можно даже назвать LightTurnedOnEvent, как и другое, но в отдельном пространстве имен , очень вероятно, с другими свойствами.

Чтобы лучше увидеть это разделение интересов / контекстов, мы можем представитьситуация, в которой сага в ответ на LightTurnedOnEvent посылает 3 команды 3 различным лампочкам, например, в большой комнате.

0 голосов
/ 07 июня 2018

Одна идея состоит в том, чтобы использовать что-то вроде «саги» для своих событий.

LightController: State idle
lightController ! OnCommand
    persist(LightTurnOnAttempted)
    lightControl ! LightTurnOnCommand
    become(pending)

LightControl:
lightControl ! LightTurnOnCommand
    performLightTurnOnAsyncFunction.map(_ => TurnOnLightCommand) pipeTo lightController

LightController: State pending
lightController ! TurnOnLightCommand
    persist(LightTurnedOn)
    become(initialized)

Это дает вам прекрасный контроль.В случае сбоя и в процессе восстановления вы можете проверить, был ли индикатор включен или LightController находился в состоянии ожидания.Если он находился в состоянии ожидания, вы можете отправить LightTurnOnCommand.

...