3

我有一个简单的订单处理应用程序并尝试应用弹簧状态机来处理订单状态。而且我想知道如何在来自休息服务的多个请求期间处理同一订单的订单状态。

订单状态:

enum OrderEvents {
    FULFILL,
    PAY,
    CANCEL
}

订单事件:

enum OrderStates {
    SUBMITTED,
    PAID,
    FULFILLED,
    CANCELLED    
}

状态机配置:

@Log
@Configuration
@EnableStateMachineFactory
class SimpleEnumStatemachineConfiguration extends StateMachineConfigurerAdapter<OrderStates, OrderEvents> {

    @Override
    public void configure(StateMachineTransitionConfigurer<OrderStates, OrderEvents> transitions) throws Exception {
        transitions
                .withExternal().source(OrderStates.SUBMITTED).target(OrderStates.PAID).event(OrderEvents.PAY)
                .and()
                .withExternal().source(OrderStates.PAID).target(OrderStates.FULFILLED).event(OrderEvents.FULFILL)
                .and()
                .withExternal().source(OrderStates.SUBMITTED).target(OrderStates.CANCELLED).event(OrderEvents.CANCEL)
                .and()
                .withExternal().source(OrderStates.PAID).target(OrderStates.CANCELLED).event(OrderEvents.CANCEL);
    }

    @Override
    public void configure(StateMachineStateConfigurer<OrderStates, OrderEvents> states) throws Exception {
        states
                .withStates()
                .initial(OrderStates.SUBMITTED)
                .state(OrderStates.PAID)
                .end(OrderStates.FULFILLED)
                .end(OrderStates.CANCELLED);
    }

    @Override
    public void configure(StateMachineConfigurationConfigurer<OrderStates, OrderEvents> config) throws Exception {
        config.withConfiguration()
                .autoStartup(true)
    }
}

在我的订单服务中,我打电话

StateMachine<OrderStates, OrderEvents> sm = this.factory.getStateMachine(orderIdKey);

但似乎每次都会为相同的 orderIdKey 创建新的状态机。那么,如何访问在下一个状态下提交订单时创建的状态机?

4

1 回答 1

2

你基本上有两个选择:

a) 使用状态机持久化器为给定orderId状态机持久化,如此所述。

b) 为给定的(每个 HTTP 请求)创建一个新的状态机,并根据给定orderId的状态重新水化 SM 状态。SM 对象被认为是轻量级的,因此这也是一种可行的方法。下面是一个代码示例:order entityorderId

StateMachine<Status, Event> build(long orderId) {
  orderService.getOrder(orderId) //returns Optional
  .map(order -> {
     StateMachine<Status, Event> sm = stateMachineFactory.getStateMachine(Long.toString(orderId));
     sm.stop();
     rehydrateState(sm, sm.getExtendedState, order.getStatus());
     sm.start();
     return sm;
   })
  .orElseGet(() -> createNewStateMachine(orderId);
}


void rehydrateState(StateMachine<Status, Event> newStateMachine, ExtendedState extendedState, Status orderStatus) {
  newStateMachine.getStateMachineAccessor().doWithAllRegions(sma ->
   sma.resetStateMachine(new DefaultStateMachineContext<>(orderStatus, null, null, extendedState));
  });
}
于 2019-03-04T09:54:02.863 回答