Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Deferred events are not handled in case the transition to the desired state was done by timerOnce #1110

Open
maayanhope opened this issue Aug 15, 2023 · 6 comments
Labels
status/need-triage Team needs to triage and take a first look

Comments

@maayanhope
Copy link

seems that if there are deferred events that are pending for a state and the state is reached by a timer (timeroonce) that these deferred events are not handled

statemachine.zip

Is this a bug?

@github-actions github-actions bot added the status/need-triage Team needs to triage and take a first look label Aug 15, 2023
@rishiraj88
Copy link

Why attached a zip file? Better to add links to relevant code file, or not?

@maayanhope
Copy link
Author

I wanted to send some example code,
how do you normally do it?

@maayanhope
Copy link
Author

package test;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.Message;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.statemachine.StateContext;
import org.springframework.statemachine.StateMachine;
import org.springframework.statemachine.config.StateMachineFactory;
import org.springframework.statemachine.listener.StateMachineListenerAdapter;
import org.springframework.statemachine.state.State;
import org.springframework.statemachine.transition.Transition;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import reactor.core.publisher.Mono;

import java.util.concurrent.BrokenBarrierException;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = SimpleStateMachineConfiguration3.class)
public class StateMachineTester3 {

@Autowired
private StateMachineFactory<String, String> stateMachineFactory;

@Test
public void testState1() throws InterruptedException, BrokenBarrierException {


	StateMachine<String, String> stateMachine = stateMachineFactory.getStateMachine("dddd" + i);

	stateMachine.addStateListener(new StateMachineListenerAdapter<>() {
		private StateContext<String, String> stateContext;

		@Override
		public void stateContext(StateContext<String, String> stateContext) {
			this.stateContext = stateContext;
		}

		@Override
		public void eventNotAccepted(Message<String> event) {
			SimpleStateMachineConfiguration2.print("----------- EventNotAccepted: Payload: " + event.getPayload() + " state:" + stateContext.getStateMachine().getState().getId());
		}

	});
	stateMachine.start();


	stateMachine.sendEvent("E1");  // Start S1

	// 1 MS --> S1->S2
	Thread.sleep(2);
	stateMachine.sendEvent(Mono.just(MessageBuilder.withPayload("E3").build())).subscribe(ret -> {
		System.out.println(ret.getResultType()); // this event is deffered
	});

	Thread.sleep(100);
	stateMachine.sendEvent(Mono.just(MessageBuilder.withPayload("E4").build())).subscribe(ret -> {
		System.out.println(ret.getResultType()); // this event will 
	});


	Thread.sleep(3000);
	SimpleStateMachineConfiguration3.print("--- cur state = " + stateMachine.getState().getId() + " ---");
	SimpleStateMachineConfiguration3.print("--- " + SimpleStateMachineConfiguration3.sum.get() + " ---");
	Thread.sleep(1000);

}

}

@maayanhope
Copy link
Author

package test;

import org.springframework.context.annotation.Configuration;
import org.springframework.statemachine.action.Action;
import org.springframework.statemachine.config.EnableStateMachineFactory;
import org.springframework.statemachine.config.StateMachineConfigurerAdapter;
import org.springframework.statemachine.config.builders.StateMachineStateConfigurer;
import org.springframework.statemachine.config.builders.StateMachineTransitionConfigurer;

import java.util.Arrays;
import java.util.HashSet;
import java.util.concurrent.atomic.AtomicInteger;

@configuration
@EnableStateMachineFactory
public class SimpleStateMachineConfiguration3
extends StateMachineConfigurerAdapter<String, String> {

public static AtomicInteger sum = new AtomicInteger();

public static void print(String msg) {
    System.out.println("[" + System.currentTimeMillis() + "][" + Thread.currentThread().getName() + "] " + msg);
}


public Action<String, String> printS2() {
    return stateContext -> {
        print("-----------s2?. " + stateContext.getStateMachine().getState().getId());
    };
}

public Action<String, String> print(int i) {
    return stateContext -> {
        sum.incrementAndGet();
        print("----------- cur state. " + i + " " + stateContext.getStateMachine().getState().getId());
    };
}

@Override
public void configure(StateMachineStateConfigurer<String, String> states)
        throws Exception {

    states.withStates()
            .initial("START")
            .end("END")
            .states(new HashSet<>(Arrays.asList("S1", "S2", "S3")))
            .state("S1", "E3")

    ;


}


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


    transitions
            .withExternal()
            .source("START").target("S1").event("E1").and()
            .withExternal()
            .source("S1").target("S2").timerOnce(10)
            .action(printS2())
            .and()
            .withExternal()
            .source("S2").target("S3").event("E3").action(print(3))
            .and()
            .withExternal()
            .source("S2").target("S2").event("E4").action(print(4)) // this is just to trigger the deferred event

    ;

}

}

@gpando
Copy link

gpando commented Aug 15, 2023

The best thing is to create a project on GitHub and share it.

@maayanhope
Copy link
Author

https://github.com/maayanhope/statemachinedeferredtest/tree/main/src

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
status/need-triage Team needs to triage and take a first look
Projects
None yet
Development

No branches or pull requests

3 participants