首页 文章

akka-persistence(cqrs?)的事件来源和副作用

提问于
浏览
2

我试图弄清楚如何使用持久性actor来模拟远程“IoT”设备的状态,例如:

用户想打开灯,这样我们才能做到最合乎逻辑 .

  • 用户发送 OnCommand

  • 持久化actor接收命令,生成 LightTurnedOnEvent 并将其状态更新为 on

所以这是有道理的,但这里的问题是灯光实际上从未打开过 . 好的,那么我们 Build 一个知道低级硬件控制伏都教的 LightControlActor . 这个演员倾听 LightTurnedOnEvent ,当它得到它时,它会做到这一点并且在光线上转动 .

Awsome现在我们开灯了!但不开心 . LightTurnedOnEvent 有点躺在这里,光还没有打开 . 遵循这个逻辑 LightTurnedOnEvent 应该由 LightControlActor 生成,我的持久化演员应该生成一些 SentRequestToTurnOnLight 但现在这对我来说变得复杂,具有所有不同的语义 .

  • 用户发送 OnCommand

  • 持久性actor recivecs OnCommand generate RequestedLightTurnOnEvent 并将状态设置为pending .

  • LightController拾取 RequestedLightTurnOnEvent 并尝试打开外部系统上的指示灯 .

那么什么呢?现在我如何更新持久化演员的状态?让LightController发送一些veird命令 SetStateToOnCommand

那么当实际打开灯时,如何更新持久状态?

2 回答

  • 1

    一个想法是为你的活动选择类似“saga”的东西 .

    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 .

  • 0

    但即使硬件控制器这么说,你也永远不知道灯亮了,即灯泡可能会损坏 .

    事件的想法是它们在有限的背景下的含义 . 在您的情况下, LightTurnedOnEvent 由持久性actor拥有,并且仅在其上下文中具有严格意义 . 从业主演员的POV开始,灯应该亮,未来 TurnOnCommand 不会改变这个状态,不会发出新事件(它是幂等的) .

    如果您希望此事件具有其他含义,则需要一个对此事件作出反应的Saga(或任何您想要调用的事件),并在另一个上下文中(即在HW上下文中)将另一个命令发送给另一个actor . 这个HW演员将发出自己的事件,仅在其上下文中相关,即 LightBulbCoupledToPowerSource 或类似的东西;它甚至可以像另一个一样命名为 LightTurnedOnEvent ,但在一个单独的命名空间中,很可能与其他属性一样 .

    为了更好地看到这种关注/背景的分离,我们可以想象一种情况,其中一个Saga,例如,响应于 LightTurnedOnEvent 将向3个不同的灯泡发送3个命令 .

相关问题