Как восстановить конечный автомат из контекста, встроенного во время выполнения? - PullRequest
0 голосов
/ 15 февраля 2019

У меня есть конечный автомат

@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.status == INVITATION.Я хочу продолжить обработку модели с помощью машины состояний, но экземпляр машины состояний начнет обработку с начальным состоянием ПРОЕКТ , но мне нужно продолжить обработку с состояния ПРИГЛАШЕНИЕ .Другими словами, я хочу выполнить

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

и выполнить действие ActionDeclined().Я не хочу сохранять контекст конечного автомата в БД.Я хочу установить состояние stateMachine для состояния моей модели во время выполнения.Как я могу сделать это правильно?Использование конструктора DefaultStateContext или другой, более красивый способ?

1 Ответ

0 голосов
/ 15 февраля 2019

Одним из возможных подходов является создание StateMachine на лету и регидрация конечного автомата из БД с использованием состояния Order.В этом случае вам необходимо выполнить следующие шаги:

  • Сброс StateMachine во всех регионах
  • Загрузка Order статуса из БД
  • Создать новый DefaultStateMachineContext и заполните соответственно

Предположим, у вас есть метод сборки, который возвращает новые конечные автоматы для обработки событий заказа (используя 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));
  });
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...