4

我有简单的状态机,下面有States,EventsTransitions.

状态: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. 提交到 REJECTED 的 REJECT 事件

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

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

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

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

4

1 回答 1

6

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

因此,您需要为每组提交的文档提供一个专用实例。这可以通过从配置http://docs.spring.io/spring-statemachine/docs/1.0.0.RELEASE/reference/htmlsingle/#sm-factories或手动使用构建器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这是一个演示,其中“东西”保存在数据库中,并且单个状态机实例用于通过状态机更新数据库。这允许您将您的东西保存在持久存储中并在状态机中处理转换逻辑。

我们目前正试图通过尝试实现更好的持久模型来使这些使用场景更易于使用,并可能通过 spring security 和 spring session 引入一些魔法来缓解/保护可以在状态机中执行操作的不同角色。所以请继续关注未来的版本。

于 2015-10-27T15:01:27.703 回答