Fix event defer issues

- Event may get not accepted in some cases
  while it should be deferred. Check defer
  again before accept would return false.
- Relates to #131
This commit is contained in:
Janne Valkealahti
2015-12-30 08:46:52 +00:00
parent 4f5eb88626
commit 9d59209ce8
3 changed files with 41 additions and 0 deletions

View File

@@ -592,6 +592,13 @@ public abstract class AbstractStateMachine<S, E> extends StateMachineObjectSuppo
}
}
}
// if we're about to not accept event, check defer again in case
// state was changed between original check and now
if ((currentState != null && currentState.shouldDefer(message))) {
log.info("Current state " + currentState + " deferred event " + message);
stateMachineExecutor.queueDeferredEvent(message);
return true;
}
return false;
}

View File

@@ -272,6 +272,7 @@ public class DefaultStateMachineExecutor<S, E> extends LifecycleObjectSupport im
State<S,E> currentState = stateMachine.getState();
if (queuedEvent != null) {
if ((currentState != null && currentState.shouldDefer(queuedEvent))) {
log.info("Current state " + currentState + " deferred event " + queuedEvent);
queueDeferredEvent(queuedEvent);
return true;
}

View File

@@ -153,6 +153,39 @@ public class EventDeferTests extends AbstractStateMachineTests {
assertThat(machine.getState().getIds(), contains("READY"));
}
@Test
public void testDeferWithSubs2ThreadExecutor() throws Exception {
context.register(Config1.class, ExecutorConfig.class);
context.refresh();
@SuppressWarnings("unchecked")
StateMachine<String, String> machine = context.getBean(StateMachineSystemConstants.DEFAULT_ID_STATEMACHINE, StateMachine.class);
TestListener listener = new TestListener();
machine.addStateListener(listener);
machine.start();
assertThat(listener.stateMachineStartedLatch.await(3, TimeUnit.SECONDS), is(true));
assertThat(listener.stateChangedLatch.await(3, TimeUnit.SECONDS), is(true));
listener.reset(0, 0, 2, 0);
machine.sendEvent("E2");
machine.sendEvent("E2");
assertThat(listener.readyStateEnteredLatch.await(3, TimeUnit.SECONDS), is(true));
assertThat(listener.readyStateEnteredCount, is(2));
assertThat(machine.getState().getIds(), contains("READY"));
}
@Test
public void testDeferWithSubs2ThreadExecutorSmoke() throws Exception {
// smoke above test to see threading issues
for (int i = 0; i < 500; i++) {
setup();
testDeferWithSubs2ThreadExecutor();
clean();
}
}
@Test
public void testSubNotDeferOverrideSuperTransition() throws Exception {
context.register(Config3.class);