如何从运行时构建的上下文中还原状态机? [英] How to restore state machine from context builded in runtime?
问题描述
我有一个状态机
@EnableStateMachine
@Configuration
public class StateMachineConfiguration extends EnumStateMachineConfigurerAdapter<Status, Event> {
@Override
public void configure(StateMachineStateConfigurer<Status, Event> states) throws Exception {
states.withStates()
.initial(Status.DRAFT)
.states(EnumSet.allOf(Status.class));
}
@Override
public void configure(StateMachineTransitionConfigurer<Status, Event> transitions) throws Exception {
transitions
.withExternal()
.target(Status.INVITATION).source(Status.DRAFT)
.event(Event.INVITED)
.guard(new Guard())
.action(new ActionInvited())
.and()
.withExternal()
.target(Status.DECLINED).source(Status.INVITATION)
.event(Event.DECLINED)
.action(new ActionDeclined());
}
@Override
public void configure(StateMachineConfigurationConfigurer<Status, Event> config) throws Exception {
config.withConfiguration().autoStartup(true);
}
}
,我有一个模型,例如 Order .
模型保留在DB中.我从数据库中提取模型,现在我的模型的状态为Order.status == INVITATION
.我想继续使用状态机处理模型,但是状态机的实例将以初始状态 DRAFT 开始处理,但是我需要从状态 INVITATION 继续处理.换句话说,我要执行
and I have a model, for example Order.
Model persists in DB. I extract model from DB, now my model has a status Order.status == INVITATION
. I want to continue processing model with statemachine, but instance of statemachine will starts processing with initial state DRAFT but I needs continue processing from status INVITATION. In other words I want to execute
stateMachine.sendEvent(MessageBuilder
.withPayload(Event.DECLINED)
.setHeader("orderId", order.id)
.build()
)
并执行动作ActionDeclined()
.我不想在DB中保留状态机的上下文.我想将stateMachine的状态设置为运行时模型的状态.我该如何以正确的方式做到这一点?使用DefaultStateContext构造函数还是还有其他更漂亮的方法?
and execute action ActionDeclined()
. I don't want to persist a context of state machine in DB. I want to setting a state of stateMachine to state of my Model in runtime. How can I do that in right way? Using DefaultStateContext constructor or have an other, more beautiful way?
推荐答案
一种可行的方法是动态创建StateMachine
,并使用Order
的状态从DB重新补充状态机.
在这种情况下,您需要执行以下步骤:
One possible approach is to create the StateMachine
on the fly and to rehydrate the state machine from the DB using the state of the Order
.
In this case you need to do the following steps:
- 在所有区域重置
StateMachine
- 从数据库加载
Order
状态 - 创建新的
DefaultStateMachineContext
并进行相应填充
- Resetting the
StateMachine
in all regions - Load
Order
status from DB - Create new
DefaultStateMachineContext
and populate accordingly
假设您有一个build方法,该方法将返回用于处理订单事件的新状态机(使用
Let's assume you have a build method, which returns new state machines for processing order events (using a StateMachineFactory), but for an existing order, it will rehydrate the state from the database.
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));
});
}
这篇关于如何从运行时构建的上下文中还原状态机?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!