Spring 状态机不接受来自多个用户的相同事件

Spring State machine not accepting same event from multiple users

我有以下 StatesEventsTransitions 的简单状态机。

状态:WIP, SUBMITTED, REJECTED, APPROVED

事件:SUBMIT, APPROVE, REJECT

转换:

@Override
public void configure(StateMachineTransitionConfigurer<States,Events> transitions) 
                          throws Exception {
    transitions
        .withExternal()
            .source(States.WIP)
            .target(States.SUBMIT)
            .event(Events.SUBMIT)
            .and()
        .withExternal()
            .source(States.SUBMITTED)
            .target(States.APPROVED)
            .event(Events.APPROVE)
            .and()
        .withExternal()
            .source(States.SUBMITTED)
            .target(States.REJECTED)
            .event(Events.REJECT);;
}
  1. WIP 到 SUBMITTED 事件
  2. 已提交以批准事件
  3. 已提交但因拒绝事件而被拒绝

我已经将WIP设置为初始状态如下:

@Override
public void configure(StateMachineStateConfigurer<States, Events> states) 
            throws Exception {
    states
    .withStates()
        .initial(States.WORK_IN_PROGRESS)
        .states(EnumSet.allOf(States.class));
}

多个用户将与此状态机交互。当针对源状态和目标状态的组合多次引发同一事件时,状态机只会接受第一个事件,而不会接受后续事件。

这是状态机的有效行为吗?如果是,是否需要添加任何额外的配置?

只有在代理人和审批人都只处理一组文档的情况下,在这样的场景中使用一个状态机实例才有效。自然地,它会给现实世界的用例带来问题,因为代理只能在批准者将机器恢复到可以提交文档的状态时提交新文档。

因此,您需要为每组提交的文档创建一个专用实例。这可以通过从配置 http://docs.spring.io/spring-statemachine/docs/1.0.0.RELEASE/reference/htmlsingle/#sm-factories or manually using builder http://docs.spring.io/spring-statemachine/docs/1.0.0.RELEASE/reference/htmlsingle/#state-machine-via-builder 公开工厂来完成。然后你需要手动控制你正在和哪台机器通话。

您提到文档可以坐等几天等待某人批准,如果您需要重新启动持有状态机的进程,这会产生问题。 (你会用简单的进程内状态机丢失状态)

我建议使用一些不同的方法来解决这个问题。检查持久性示例 http://docs.spring.io/spring-statemachine/docs/1.0.0.RELEASE/reference/htmlsingle/#statemachine-examples-persist,这是一个演示,其中 "stuff" 保存在数据库中,并且使用单个状态机实例通过状态机更新数据库。这允许您将您的东西保存在持久存储中并在状态机中处理转换逻辑。

我们目前正在尝试通过尝试实现更好的持久模型并可能通过 spring 安全和 spring 会话引入一些魔法来使这些使用场景更易于使用 ease/protect 不同的角色在状态机中可以做什么。请继续关注未来的发布。