当前位置: 首页 > 面试题库 >

如何从运行时构建的上下文中还原状态机?

盖和洽
2023-03-14
问题内容

我有一个状态机

@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 继续处理。换句话说我要执行

stateMachine.sendEvent(MessageBuilder
  .withPayload(Event.DECLINED)
  .setHeader("orderId", order.id)
  .build()
)

并执行动作ActionDeclined()。我不想在DB中保留状态机的上下文。我想将stateMachine的状态设置为运行时模型的状态。我怎样才能正确地做到这一点?使用DefaultStateContext构造函数还是还有其他更漂亮的方法?


问题答案:

一种可行的方法是StateMachine即时创建并使用的状态从数据库中重新补充状态机Order。在这种情况下,您需要执行以下步骤:

  • 重设StateMachine所有地区
  • Order从数据库加载状态
  • 新建DefaultStateMachineContext并相应地填充

假设您有一个build方法,该方法返回用于处理订单事件的新状态机(使用StateMachineFactory),但是对于现有订单,它将从数据库中重新补充状态。

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));
  });
}


 类似资料:
  • 我最近使用钩子编写了一个表组件,每次页面加载时都会有一个对后端的API调用,因此同时会显示一个加载微调器,直到有来自API的响应为止。我使用redux作为状态管理,所以当有来自API的响应时,将调度一个操作并更新状态。所以这里的问题是,通常在类组件中,我们可以使用 但是我不知道如何使用钩子实现同样的效果。我还提到了这个stackoverflow问题如何比较反应挂钩的旧值和新值使用效果? 但这个解决

  • 说我有以下几点: 并且在该操作创建器中,我想访问全局存储状态(所有还原器)。这样做是否更好: 或者这个:

  • 我使用jsonschema生成器基于我的POJO生成JSON模式文件。目前,我正在通过一个在<code>gradle构建</code>步骤中运行的测试来完成这项工作。这工作正常,但感觉不对,因为我所做的并不是测试任何东西。 我还找到了这个答案,其中详细说明了如何在上运行它,但这也不理想,因为它会在每次应用程序出现时毫无意义地执行它,但在我构建时不会。 因此,有没有一种方法可以告诉gradle(在中

  • 我想通过liquibase-maven-plugin运行一个liquibase更新,但是changeset yml文件在一个。jar中,我通过依赖项拉入这个文件。 当我用TotalCommander打开。jar时,它具有以下结构:xy.jar/changelog/changeset.yml。

  • 我是一个新手,我想建立动态地图 最终地图检查={'卧房':'床','浴室':'bathbub\u轮廓'}; 它显示一个错误 lib/模板/general.dart:164: 18:错误:无法从返回类型为MapEntry的函数返回类型为Row的值 “行”来自“包:flatter/src/widgets/basic”。dart’(“../flight/packages/flight/lib/src/w