代码之家  ›  专栏  ›  技术社区  ›  Patrik

阿克卡坚持(cqrs?)事件来源和副作用

  •  2
  • Patrik  · 技术社区  · 7 年前

    我正试图找出如何用一个持久的参与者来模拟远程“物联网”设备的状态,例如:

    用户想打开一盏灯,所以我们做最合乎逻辑的。

    1. 用户发送 OnCommand
    2. 持久参与者接收命令,生成 LightTurnedOnEvent 并将其状态更新为 on

    所以这是有道理的,但这里的问题是灯实际上从来没有打开过。好的,那么我们建立一个 LightControlActor 知道低级硬件控制巫毒的人。这个演员在听 无光 当它得到它,它做它的事情,并打开灯。

    噢,现在我们有灯开了!但不快乐。 无光 有点躺在这里,灯还没亮。遵循这个逻辑 无光 应该由 光控制器 我的执着的演员应该 SentRequestToTurnOnLight 但现在这对我来说变得复杂了,有着不同的语义。

    1. 用户发送 指挥部
    2. 持久性参与者recivecs 指挥部 生成 RequestedLightTurnOnEvent 并将state设置为pending。

    3. Lightcontroller在 请求的LightTurnoneEvent 试着打开外部系统的灯。

    那又怎样?现在如何更新持久参与者的状态?让灯光控制器发送一些veird命令 SetStateToOnCommand ?

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

    2 回复  |  直到 7 年前
        1
  •  1
  •   Branislav Lazic akhouri    7 年前

    一个想法是用类似“传奇”的东西来描述你的活动。

    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

        2
  •  0
  •   Constantin Galbenu    7 年前

    但你永远无法确定灯是否打开,即使硬件控制器这么说,也就是说灯泡可能损坏。

    事件的概念是它们在 有界上下文 . 对你来说, LightTurnedOnEvent 由持久的参与者拥有,并且只有在其上下文中才有严格的含义。从主人公的视角看光 应该 有前途 TurnOnCommand 不会更改此状态,不会发出新事件(它是等幂的)。

    如果您希望此事件具有其他含义,则需要一个saga(或任何您想调用它的内容),该saga将对此事件作出反应,并将另一个命令发送给另一个参与者,在另一个上下文中,即在hw上下文中。这个hw参与者将发出自己的事件,仅在其上下文中相关,即。 LightBulbCoupledToPowerSource 或者类似的东西;它甚至可以被命名为 无光 ,就像另一个,但是在一个单独的 命名空间 ,很可能与其他属性有关。

    为了更好地看到关注点/上下文的分离,我们可以想象这样一种情形,在这种情形下,一个传奇,作为对 无光 会向3个不同的灯泡发送3个命令,例如在一个大房间里。

    推荐文章