Fix r2bdc componentType; Redis Streams ack issue

The R2DBC channel adapters have wrong componentType

* Fix R2DBC component type to not mention `reactive-`: they are reactive by R2DBC definition

The `ReactiveRedisStreamMessageProducer` calls ack() explicitly
when populates `IntegrationMessageHeaderAccessor.ACKNOWLEDGMENT_CALLBACK` header,
but must provide an implementation of `SimpleAcknowledgment` instead

* Fix `ReactiveRedisStreamMessageProducer` to populate the proper
`IntegrationMessageHeaderAccessor.ACKNOWLEDGMENT_CALLBACK` header and in the proper moment
* Fix `ReactiveRedisStreamMessageProducerTests` to verify that `autoAck=false` works as expected
together with the `IntegrationMessageHeaderAccessor.ACKNOWLEDGMENT_CALLBACK` header functionality
This commit is contained in:
rohan mukesh
2020-10-06 16:27:27 -04:00
committed by Artem Bilan
parent 94e6521510
commit 6d6f53fa87
5 changed files with 107 additions and 10 deletions

View File

@@ -19,6 +19,7 @@ package org.springframework.integration.redis.inbound;
import static org.assertj.core.api.Assertions.assertThat;
import java.time.Duration;
import java.util.concurrent.atomic.AtomicReference;
import org.junit.After;
import org.junit.Before;
@@ -28,10 +29,15 @@ import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.stream.PendingMessagesSummary;
import org.springframework.data.redis.connection.stream.ReadOffset;
import org.springframework.data.redis.connection.stream.StreamInfo;
import org.springframework.data.redis.core.ReactiveRedisTemplate;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.stream.StreamReceiver;
import org.springframework.integration.IntegrationMessageHeaderAccessor;
import org.springframework.integration.StaticMessageHeaderAccessor;
import org.springframework.integration.acks.SimpleAcknowledgment;
import org.springframework.integration.channel.FluxMessageChannel;
import org.springframework.integration.handler.ReactiveMessageHandlerAdapter;
import org.springframework.integration.redis.outbound.ReactiveRedisStreamMessageHandler;
@@ -46,11 +52,13 @@ import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.junit4.SpringRunner;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import reactor.test.StepVerifier;
/**
* @author Attoumane Ahamadi
* @author Artem Bilan
* @author Rohan Mukesh
*
* @since 5.4
*/
@@ -76,6 +84,16 @@ public class ReactiveRedisStreamMessageProducerTests extends RedisAvailableTests
@Before
public void delKey() {
this.template.hasKey(STREAM_KEY)
.filter(Boolean::booleanValue)
.flatMapMany(b ->
this.template.opsForStream()
.groups(STREAM_KEY)
.map(StreamInfo.XInfoGroup::groupName)
.flatMap(groupName ->
this.template.opsForStream()
.destroyGroup(STREAM_KEY, groupName)))
.blockLast();
this.template.delete(STREAM_KEY).block();
}
@@ -90,10 +108,11 @@ public class ReactiveRedisStreamMessageProducerTests extends RedisAvailableTests
this.redisStreamMessageProducer.setCreateConsumerGroup(true);
this.redisStreamMessageProducer.setConsumerName(CONSUMER);
this.redisStreamMessageProducer.afterPropertiesSet();
this.redisStreamMessageProducer.start();
Flux.from(this.fluxMessageChannel).subscribe();
this.redisStreamMessageProducer.start();
this.template.opsForStream()
.groups(STREAM_KEY)
.next()
@@ -147,19 +166,81 @@ public class ReactiveRedisStreamMessageProducerTests extends RedisAvailableTests
this.redisStreamMessageProducer.setCreateConsumerGroup(false);
this.redisStreamMessageProducer.setConsumerName(CONSUMER);
this.redisStreamMessageProducer.setReadOffset(ReadOffset.latest());
this.redisStreamMessageProducer.afterPropertiesSet();
this.redisStreamMessageProducer.start();
StepVerifier stepVerifier =
Flux.from(this.fluxMessageChannel)
.as(StepVerifier::create)
.assertNext(message -> {
assertThat(message.getPayload()).isEqualTo(person);
assertThat(message.getHeaders()).containsKeys(RedisHeaders.CONSUMER_GROUP, RedisHeaders.CONSUMER);
})
.thenCancel()
.verifyLater();
this.messageHandler.handleMessage(new GenericMessage<>(person));
Flux.from(this.fluxMessageChannel)
stepVerifier.verify(Duration.ofSeconds(10));
}
@Test
@RedisAvailable
public void testReadingPendingMessageWithNoAutoACK() {
Address address = new Address("Winterfell, Westeros");
Person person = new Person(address, "John Snow");
this.template.opsForStream()
.createGroup(STREAM_KEY, this.redisStreamMessageProducer.getBeanName())
.as(StepVerifier::create)
.assertNext(message -> {
assertThat(message.getPayload()).isEqualTo(person);
assertThat(message.getHeaders()).containsKeys(RedisHeaders.CONSUMER_GROUP, RedisHeaders.CONSUMER);
})
.assertNext(message -> assertThat(message).isEqualTo("OK"))
.thenCancel()
.verify(Duration.ofSeconds(10));
this.redisStreamMessageProducer.setCreateConsumerGroup(false);
this.redisStreamMessageProducer.setAutoAck(false);
this.redisStreamMessageProducer.setConsumerName(CONSUMER);
this.redisStreamMessageProducer.setReadOffset(ReadOffset.latest());
this.redisStreamMessageProducer.afterPropertiesSet();
this.redisStreamMessageProducer.start();
AtomicReference<SimpleAcknowledgment> acknowledgmentReference = new AtomicReference<>();
StepVerifier stepVerifier =
Flux.from(this.fluxMessageChannel)
.as(StepVerifier::create)
.assertNext(message -> {
assertThat(message.getPayload()).isEqualTo(person);
assertThat(message.getHeaders())
.containsKeys(IntegrationMessageHeaderAccessor.ACKNOWLEDGMENT_CALLBACK);
acknowledgmentReference.set(StaticMessageHeaderAccessor.getAcknowledgment(message));
})
.thenCancel()
.verifyLater();
this.messageHandler.handleMessage(new GenericMessage<>(person));
stepVerifier.verify(Duration.ofSeconds(10));
Mono<PendingMessagesSummary> pending =
template.opsForStream()
.pending(STREAM_KEY, this.redisStreamMessageProducer.getBeanName());
StepVerifier.create(pending)
.assertNext(pendingMessagesSummary ->
assertThat(pendingMessagesSummary.getTotalPendingMessages()).isEqualTo(1))
.verifyComplete();
acknowledgmentReference.get().acknowledge();
Mono<PendingMessagesSummary> pendingZeroMessage = template.opsForStream().pending(STREAM_KEY,
this.redisStreamMessageProducer.getBeanName());
StepVerifier.create(pendingZeroMessage)
.assertNext(pendingMessagesSummary ->
assertThat(pendingMessagesSummary.getTotalPendingMessages()).isEqualTo(0))
.verifyComplete();
}
@Configuration