INT-3198: Add 'recovery-interval' for redis-q-c-a
JIRA: https://jira.springsource.org/browse/INT-3198 * Expose `RedisQueueMessageDrivenEndpoint.recoveryInterval` to Namespace support * Add parser's tests * Rename parser test class * Polishing for concurrency of`RedisQueueMessageDrivenEndpointTests#testInt3196Recovery` test * Add documentation for 'recovery-interval' and Redis Events implementation Doc Polishing Add more delay because of unsolvable race condition in the Redis Subscription - see DATAREDIS-242
This commit is contained in:
committed by
Gary Russell
parent
f169555224
commit
93bcfdbc55
@@ -50,6 +50,7 @@ public class RedisQueueInboundChannelAdapterParser extends AbstractChannelAdapte
|
||||
IntegrationNamespaceUtils.setReferenceIfAttributeDefined(builder, element, "error-channel");
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "expect-message");
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "receive-timeout");
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "recovery-interval");
|
||||
builder.addPropertyReference("outputChannel", channelName);
|
||||
|
||||
return builder.getBeanDefinition();
|
||||
|
||||
@@ -392,6 +392,15 @@
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="recovery-interval" type="xsd:string" default="5000">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
Specify the time in milliseconds for which the listener task should sleep after catching
|
||||
an Exception on a Redis operation, before restarting the listener task.
|
||||
Default is 5 seconds.
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="expect-message" type="xsd:string" default="false">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
serializer="serializer"
|
||||
error-channel="errorChannel"
|
||||
receive-timeout="2000"
|
||||
recovery-interval="3000"
|
||||
task-executor="executor"
|
||||
auto-startup="false"
|
||||
phase="100"/>
|
||||
@@ -46,7 +46,7 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
*/
|
||||
@ContextConfiguration
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
public class RedisMessageDrivenEndpointParserTests {
|
||||
public class RedisQueueInboundChannelAdapterParserTests {
|
||||
|
||||
@Autowired
|
||||
@Qualifier("redisConnectionFactory")
|
||||
@@ -90,6 +90,7 @@ public class RedisMessageDrivenEndpointParserTests {
|
||||
assertEquals("si.test.Int3017.Inbound1", TestUtils.getPropertyValue(this.defaultAdapter, "boundListOperations.key"));
|
||||
assertFalse(TestUtils.getPropertyValue(this.defaultAdapter, "expectMessage", Boolean.class));
|
||||
assertEquals(new Long(1000), TestUtils.getPropertyValue(this.defaultAdapter, "receiveTimeout", Long.class));
|
||||
assertEquals(new Long(5000), TestUtils.getPropertyValue(this.defaultAdapter, "recoveryInterval", Long.class));
|
||||
assertNull(TestUtils.getPropertyValue(this.defaultAdapter, "errorChannel"));
|
||||
assertThat(TestUtils.getPropertyValue(this.defaultAdapter, "taskExecutor"), Matchers.instanceOf(ErrorHandlingTaskExecutor.class));
|
||||
assertThat(TestUtils.getPropertyValue(this.defaultAdapter, "serializer"), Matchers.instanceOf(JdkSerializationRedisSerializer.class));
|
||||
@@ -103,6 +104,7 @@ public class RedisMessageDrivenEndpointParserTests {
|
||||
assertEquals("si.test.Int3017.Inbound2", TestUtils.getPropertyValue(this.customAdapter, "boundListOperations.key"));
|
||||
assertTrue(TestUtils.getPropertyValue(this.customAdapter, "expectMessage", Boolean.class));
|
||||
assertEquals(new Long(2000), TestUtils.getPropertyValue(this.customAdapter, "receiveTimeout", Long.class));
|
||||
assertEquals(new Long(3000), TestUtils.getPropertyValue(this.customAdapter, "recoveryInterval", Long.class));
|
||||
assertSame(this.errorChannel, TestUtils.getPropertyValue(this.customAdapter, "errorChannel"));
|
||||
assertSame(this.taskExecutor, TestUtils.getPropertyValue(this.customAdapter, "taskExecutor"));
|
||||
assertSame(this.serializer, TestUtils.getPropertyValue(this.customAdapter, "serializer"));
|
||||
@@ -20,12 +20,15 @@ import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertSame;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.hamcrest.Matchers;
|
||||
import org.junit.Test;
|
||||
@@ -213,6 +216,8 @@ public class RedisQueueMessageDrivenEndpointTests extends RedisAvailableTests {
|
||||
|
||||
final List<ApplicationEvent> exceptionEvents = new ArrayList<ApplicationEvent>();
|
||||
|
||||
final CountDownLatch exceptionsLatch = new CountDownLatch(2);
|
||||
|
||||
RedisQueueMessageDrivenEndpoint endpoint = new RedisQueueMessageDrivenEndpoint(queueName, this.connectionFactory);
|
||||
endpoint.setBeanFactory(Mockito.mock(BeanFactory.class));
|
||||
endpoint.setApplicationEventPublisher(new ApplicationEventPublisher() {
|
||||
@@ -220,6 +225,7 @@ public class RedisQueueMessageDrivenEndpointTests extends RedisAvailableTests {
|
||||
@Override
|
||||
public void publishEvent(ApplicationEvent event) {
|
||||
exceptionEvents.add(event);
|
||||
exceptionsLatch.countDown();
|
||||
}
|
||||
});
|
||||
endpoint.setOutputChannel(channel);
|
||||
@@ -228,16 +234,26 @@ public class RedisQueueMessageDrivenEndpointTests extends RedisAvailableTests {
|
||||
endpoint.afterPropertiesSet();
|
||||
endpoint.start();
|
||||
|
||||
int n = 0;
|
||||
do {
|
||||
n++;
|
||||
if (n == 100) {
|
||||
break;
|
||||
}
|
||||
Thread.sleep(100);
|
||||
} while (!endpoint.isListening());
|
||||
|
||||
assertTrue(n < 100);
|
||||
|
||||
((DisposableBean) this.connectionFactory).destroy();
|
||||
|
||||
Thread.sleep(300);
|
||||
assertTrue(exceptionsLatch.await(10, TimeUnit.SECONDS));
|
||||
|
||||
assertThat(exceptionEvents.size(), Matchers.greaterThan(0));
|
||||
for (ApplicationEvent exceptionEvent : exceptionEvents) {
|
||||
assertThat(exceptionEvent, Matchers.instanceOf(RedisExceptionEvent.class));
|
||||
assertSame(endpoint, exceptionEvent.getSource());
|
||||
assertThat(((IntegrationEvent) exceptionEvent).getCause().getClass(),
|
||||
Matchers.isIn(Arrays.<Class<? extends Throwable>> asList(RedisSystemException.class, RedisConnectionFailureException.class)));
|
||||
Matchers.isIn(Arrays.<Class<? extends Throwable>>asList(RedisSystemException.class, RedisConnectionFailureException.class)));
|
||||
}
|
||||
|
||||
((InitializingBean) this.connectionFactory).afterPropertiesSet();
|
||||
|
||||
@@ -68,6 +68,8 @@ public class RedisAvailableTests {
|
||||
while (n++ < 100 && !connection.isSubscribed()) {
|
||||
Thread.sleep(100);
|
||||
}
|
||||
// TODO: remove this additional delay when/if https://jira.springsource.org/browse/DATAREDIS-242 is resolved
|
||||
Thread.sleep(250);
|
||||
assertTrue("RedisMessageListenerContainer Failed to Subscribe", n < 100);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user