Skip to content

Resetting spring state machine results in infinite loop #1011

Open
@spac-valentin

Description

@spac-valentin

I am exploring Spring state machine and was testing a scenario where state machine would run to completion after resetting from a specific state but it runs in an infinite loop. The below code is enough to reproduce the issue.

Basically, there is one state machine that on event e1 will transition from s1 to s2 and then it will transition to s3 and s4 (triggerless transition). I want to make this state machine run from s2 to completion, but it ends up in a infinite loop, executing (and printing) s3 action

    @Test
    public void loop() throws Exception {
        var sm = buildMachine();

        Flux.fromIterable(sm.getStateMachineAccessor().withAllRegions())
                .flatMap(region -> region.resetStateMachineReactively(new DefaultStateMachineContext<>("s2", null, null, null)))
                .subscribe();

        sm.startReactively().block();
        sm.sendEvent(Mono.just(MessageBuilder
                .withPayload("e1")
                .build())).subscribe();
    }

    @SneakyThrows
    StateMachine<String, String> buildMachine() {
        StateMachineBuilder.Builder<String, String> builder = StateMachineBuilder.builder();

        builder.configureConfiguration()
                .withConfiguration()
                .autoStartup(false);

        builder.configureStates()
                .withStates()
                .initial("s1")
                .end("s4")
                .states(Set.of("s1", "s2", "s3", "s4"));

        // @formatter:off
        builder.configureTransitions()
                .withExternal()
                    .source("s1")
                    .event("e1")
                    .target("s2")
                    .action((p) -> logger.info("s2 action"), (p) -> logger.info("s2 action failed"))

                .and()
                .withExternal()
                    .source("s2")
                    .target("s3")
                    .action((p) -> logger.info("s3 action"))

                .and()
                    .withExternal()
                    .source("s3")
                    .target("s4");
        // @formatter:on

        return builder.build();
    }

What am I missing here?

Note: posted on StackOverflow too

Metadata

Metadata

Assignees

No one assigned

    Labels

    status/need-triageTeam needs to triage and take a first look

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions