Add BackOffExecution to isolate state

This commit separates the BackOff configuration from an actual
 execution. BackOffExecution now contains all the state of a
 particular execution and BackOff is only meant to start (i.e.
 create) a new execution.

 The method "reset" has been removed as its no longer necessary:
 when an execution does not need to be used for a given operation
 anymore it can be simply discarded.

 Issue: SPR-11746
This commit is contained in:
Stephane Nicoll
2014-05-09 16:39:01 +02:00
parent 49040a2925
commit 89fc3c0257
10 changed files with 270 additions and 167 deletions

View File

@@ -29,6 +29,7 @@ import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import org.springframework.util.BackOff;
import org.springframework.util.BackOffExecution;
/**
*
@@ -39,7 +40,9 @@ public class DefaultMessageListenerContainerTests {
@Test
public void applyBackOff() {
BackOff mock = mock(BackOff.class);
given(mock.nextBackOff()).willReturn(BackOff.STOP);
BackOffExecution execution = mock(BackOffExecution.class);
given(execution.nextBackOff()).willReturn(BackOffExecution.STOP);
given(mock.start()).willReturn(execution);
DefaultMessageListenerContainer container = createContainer(mock, createFailingContainerFactory());
container.start();
@@ -48,34 +51,40 @@ public class DefaultMessageListenerContainerTests {
container.refreshConnectionUntilSuccessful();
assertEquals(false, container.isRunning());
verify(mock).nextBackOff();
verify(mock).start();
verify(execution).nextBackOff();
}
@Test
public void applyBackOffRetry() {
BackOff mock = mock(BackOff.class);
given(mock.nextBackOff()).willReturn(50L, BackOff.STOP);
BackOffExecution execution = mock(BackOffExecution.class);
given(execution.nextBackOff()).willReturn(50L, BackOffExecution.STOP);
given(mock.start()).willReturn(execution);
DefaultMessageListenerContainer container = createContainer(mock, createFailingContainerFactory());
container.start();
container.refreshConnectionUntilSuccessful();
assertEquals(false, container.isRunning());
verify(mock, times(2)).nextBackOff();
verify(mock).start();
verify(execution, times(2)).nextBackOff();
}
@Test
public void recoverResetBackOff() {
BackOff mock = mock(BackOff.class);
given(mock.nextBackOff()).willReturn(50L, 50L, 50L); // 3 attempts max
BackOffExecution execution = mock(BackOffExecution.class);
given(execution.nextBackOff()).willReturn(50L, 50L, 50L); // 3 attempts max
given(mock.start()).willReturn(execution);
DefaultMessageListenerContainer container = createContainer(mock, createRecoverableContainerFactory(1));
container.start();
container.refreshConnectionUntilSuccessful();
assertEquals(true, container.isRunning());
verify(mock, times(1)).nextBackOff(); // only on attempt as the second one lead to a recovery
verify(mock, times(1)).reset(); // reset should have been called
verify(mock).start();
verify(execution, times(1)).nextBackOff(); // only on attempt as the second one lead to a recovery
}
@SuppressWarnings("unchecked")