Как использовать Spring Sub State Machine? - PullRequest
0 голосов
/ 28 апреля 2020

Для нашего случая использования я хотел бы реализовать машину состояний, в состояниях которой также должны быть машины состояний (подчиненные машины состояний), чтобы вспомогательные машины могли работать асинхронно. Я видел, что интерфейс StateConfigurer предоставляет методы, которые принимают StateMachine, а также StateMachineFactory:

  • StateConfigurer#state(S state, StateMachine<S, E> stateMachine)
  • StateConfigurer#state(S state, StateMachineFactory<S, E> stateMachineFactory)

Не могли бы вы рассказать, как настроить родительский автомат состояний StateMachineConfig с помощью второго метода, описанного выше, чтобы регионы использовали вспомогательные автоматы состояний.

Вот соответствующая часть моего кода (на основе пример Tasks ):

(для простоты я удалил события здесь)

@Configuration
public class Application implements CommandLineRunner {

    private final static Log log = LogFactory.getLog(Application.class);

    @Autowired
    StateMachine<States, Events> stateMachine;

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

    @Override
    public void run(String... args) {
        stateMachine.start();
    }

    @Configuration
    @EnableStateMachine
    static class StateMachineConfig
            extends EnumStateMachineConfigurerAdapter<States, Events> {

        @Autowired
        @Qualifier("subStateMachineFactory")
        private StateMachineFactory<States, Events> stateMachineFactory;

        @Override
        public void configure(StateMachineStateConfigurer<States, Events> states)
                throws Exception {
            states
                .withStates()
                    .initial(States.READY)
                    .fork(States.FORK)
                    .state(States.TASKS)
                    .join(States.JOIN)
                    .and()
                    .withStates()
                        .parent(States.TASKS)
                        .initial(States.T1)
                        .state(States.T1_PROCESSING, stateMachineFactory)
                        .end(States.T1E)
                        .and()
                    .withStates()
                        .parent(States.TASKS)
                        .initial(States.T2)
                        .state(States.T2_PROCESSING, stateMachineFactory)
                        .end(States.T2E)
                        .and()
                    .withStates()
                        .parent(States.TASKS)
                        .initial(States.T3)
                        .state(States.T3_PROCESSING, stateMachineFactory)
                        .end(States.T3E);
        }

        @Override
        public void configure(StateMachineTransitionConfigurer<States, Events> transitions)
                throws Exception {

            transitions
                .withExternal()
                    .source(States.READY).target(States.FORK)
                    .event(Events.RUN)
                    .and()
                .withFork()
                    .source(States.FORK).target(States.TASKS)
                    .and()
                .withExternal()
                    .source(States.T1).target(States.T1_PROCESSING)
                    .and()
                .withExternal()
                    .source(States.T2).target(States.T2_PROCESSING)
                    .and()
                .withExternal()
                    .source(States.T3).target(States.T3_PROCESSING)
                    .and()
                .withExternal()
                    .source(States.T1_PROCESSING).target(States.T1E)
                    .and()
                .withExternal()
                    .source(States.T2_PROCESSING).target(States.T2E)
                    .and()
                .withExternal()
                    .source(States.T3_PROCESSING).target(States.T3E)
                    .and()
                .withJoin()
                    .source(States.TASKS).target(States.JOIN);

        }

        @Bean(name = StateMachineSystemConstants.TASK_EXECUTOR_BEAN_NAME)
        public TaskExecutor taskExecutor() {
            ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
            taskExecutor.setCorePoolSize(5);
            return taskExecutor;
        }

    }

    @Configuration
    @EnableStateMachineFactory(name = "subStateMachineFactory")
    static class SubStateMachineConfig
            extends EnumStateMachineConfigurerAdapter<States, Events> {

        @Override
        public void configure(StateMachineConfigurationConfigurer<States, Events> stateMachineConfigurationConfigurer) throws Exception {
            stateMachineConfigurationConfigurer
                    .withConfiguration()
                    .autoStartup(true)
                    .taskExecutor(subStateMachineTaskExecutor());
        }

        @Override
        public void configure(StateMachineStateConfigurer<States, Events> stateMachineStateConfigurer)
                throws Exception {
            stateMachineStateConfigurer
                    .withStates()
                        .initial(States.T1_SUB)
                        .state(States.T1_SUB_PROCESSING)
                        .end(States.T1E_SUB);
        }

        @Override
        public void configure(StateMachineTransitionConfigurer<States, Events> stateMachineTransitionConfigurer)
                throws Exception {
            stateMachineTransitionConfigurer
                    .withExternal()
                        .source(States.T1_SUB).target(States.T1_SUB_PROCESSING)
                        .action((context -> log.info(context.getStateMachine().getId() + ": T1_SUB ------> T1_SUB_PROCESSING")))
                        .and()
                    .withExternal()
                        .source(States.T1_SUB_PROCESSING).target(States.T1E_SUB);
        }

        @Bean
        public TaskExecutor subStateMachineTaskExecutor() {
            ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
            taskExecutor.setCorePoolSize(5);
            return taskExecutor;
        }
    }

    public enum States {
        READY,
        FORK, JOIN,
        TASKS, T1, T1_PROCESSING, T1E, T2, T2_PROCESSING, T2E, T3, T3_PROCESSING, T3E,
        T1_SUB, T1_SUB_PROCESSING, T1E_SUB
    }

    public enum Events {
        T1_PROCESS, T2_PROCESS, T3_PROCESS, RUN,
        T1_SUB_PROCESS
    }

    @Target(ElementType.METHOD)
    @Retention(RetentionPolicy.RUNTIME)
    @OnTransition
    public @interface StatesOnTransition {

        States[] source() default {};

        States[] target() default {};

    }
}

Версия Spring-Boot: 2.2.6.RELEASE Версия Spring-Statemachine: 2.2.0.RELEASE

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...