Search in sources :

Example 1 with BackOffDelayPolicy

use of com.rabbitmq.stream.BackOffDelayPolicy in project rabbitmq-stream-java-client by rabbitmq.

the class ConsumersCoordinatorTest method metadataUpdate_shouldCloseConsumerIfStreamIsDeleted.

@Test
void metadataUpdate_shouldCloseConsumerIfStreamIsDeleted() throws Exception {
    BackOffDelayPolicy delayPolicy = fixedWithInitialDelay(ms(50), ms(50));
    when(environment.topologyUpdateBackOffDelayPolicy()).thenReturn(delayPolicy);
    scheduledExecutorService = Executors.newSingleThreadScheduledExecutor();
    when(environment.scheduledExecutorService()).thenReturn(scheduledExecutorService);
    when(consumer.isOpen()).thenReturn(true);
    when(locator.metadata("stream")).thenReturn(metadata(null, replicas())).thenReturn(metadata("stream", null, null, Constants.RESPONSE_CODE_STREAM_DOES_NOT_EXIST));
    when(clientFactory.client(any())).thenReturn(client);
    when(client.subscribe(subscriptionIdCaptor.capture(), anyString(), any(OffsetSpecification.class), anyInt(), anyMap())).thenReturn(new Client.Response(Constants.RESPONSE_CODE_OK));
    AtomicInteger messageHandlerCalls = new AtomicInteger();
    coordinator.subscribe(consumer, "stream", OffsetSpecification.first(), null, NO_OP_SUBSCRIPTION_LISTENER, (offset, message) -> messageHandlerCalls.incrementAndGet());
    verify(clientFactory, times(1)).client(any());
    verify(client, times(1)).subscribe(anyByte(), anyString(), any(OffsetSpecification.class), anyInt(), anyMap());
    assertThat(messageHandlerCalls.get()).isEqualTo(0);
    messageListener.handle(subscriptionIdCaptor.getValue(), 1, 0, new WrapperMessageBuilder().build());
    assertThat(messageHandlerCalls.get()).isEqualTo(1);
    metadataListener.handle("stream", Constants.RESPONSE_CODE_STREAM_NOT_AVAILABLE);
    Thread.sleep(delayPolicy.delay(0).toMillis() * 5);
    verify(consumer, times(1)).closeAfterStreamDeletion();
    verify(client, times(1)).subscribe(anyByte(), anyString(), any(OffsetSpecification.class), anyInt(), anyMap());
    verify(client, times(0)).unsubscribe(anyByte());
    assertThat(coordinator.poolSize()).isZero();
}
Also used : OffsetSpecification(com.rabbitmq.stream.OffsetSpecification) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) WrapperMessageBuilder(com.rabbitmq.stream.codec.WrapperMessageBuilder) BackOffDelayPolicy(com.rabbitmq.stream.BackOffDelayPolicy) Test(org.junit.jupiter.api.Test) ParameterizedTest(org.junit.jupiter.params.ParameterizedTest)

Example 2 with BackOffDelayPolicy

use of com.rabbitmq.stream.BackOffDelayPolicy in project rabbitmq-stream-java-client by rabbitmq.

the class ConsumersCoordinatorTest method shouldRetryRedistributionIfMetadataIsNotUpdatedImmediately.

@Test
void shouldRetryRedistributionIfMetadataIsNotUpdatedImmediately() throws Exception {
    BackOffDelayPolicy delayPolicy = fixedWithInitialDelay(ms(100), ms(100));
    when(environment.topologyUpdateBackOffDelayPolicy()).thenReturn(delayPolicy);
    scheduledExecutorService = Executors.newSingleThreadScheduledExecutor();
    when(environment.scheduledExecutorService()).thenReturn(scheduledExecutorService);
    when(consumer.isOpen()).thenReturn(true);
    when(locator.metadata("stream")).thenReturn(metadata(null, replicas())).thenReturn(metadata(null, Collections.emptyList())).thenReturn(metadata(null, Collections.emptyList())).thenReturn(metadata(null, replicas()));
    when(clientFactory.client(any())).thenReturn(client);
    when(client.subscribe(subscriptionIdCaptor.capture(), anyString(), any(OffsetSpecification.class), anyInt(), anyMap())).thenReturn(new Client.Response(Constants.RESPONSE_CODE_OK));
    AtomicInteger messageHandlerCalls = new AtomicInteger();
    Runnable closingRunnable = coordinator.subscribe(consumer, "stream", OffsetSpecification.first(), null, NO_OP_SUBSCRIPTION_LISTENER, (offset, message) -> messageHandlerCalls.incrementAndGet());
    verify(clientFactory, times(1)).client(any());
    verify(client, times(1)).subscribe(anyByte(), anyString(), any(OffsetSpecification.class), anyInt(), anyMap());
    assertThat(messageHandlerCalls.get()).isEqualTo(0);
    messageListener.handle(subscriptionIdCaptor.getValue(), 1, 0, new WrapperMessageBuilder().build());
    assertThat(messageHandlerCalls.get()).isEqualTo(1);
    metadataListener.handle("stream", Constants.RESPONSE_CODE_STREAM_NOT_AVAILABLE);
    Thread.sleep(delayPolicy.delay(0).toMillis() + delayPolicy.delay(1).toMillis() * 5);
    verify(client, times(2)).subscribe(anyByte(), anyString(), any(OffsetSpecification.class), anyInt(), anyMap());
    assertThat(messageHandlerCalls.get()).isEqualTo(1);
    messageListener.handle(subscriptionIdCaptor.getValue(), 0, 0, new WrapperMessageBuilder().build());
    assertThat(messageHandlerCalls.get()).isEqualTo(2);
    when(client.unsubscribe(subscriptionIdCaptor.getValue())).thenReturn(new Client.Response(Constants.RESPONSE_CODE_OK));
    closingRunnable.run();
    verify(client, times(1)).unsubscribe(subscriptionIdCaptor.getValue());
    messageListener.handle(subscriptionIdCaptor.getValue(), 0, 0, new WrapperMessageBuilder().build());
    assertThat(messageHandlerCalls.get()).isEqualTo(2);
    assertThat(coordinator.poolSize()).isZero();
}
Also used : OffsetSpecification(com.rabbitmq.stream.OffsetSpecification) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) WrapperMessageBuilder(com.rabbitmq.stream.codec.WrapperMessageBuilder) BackOffDelayPolicy(com.rabbitmq.stream.BackOffDelayPolicy) Test(org.junit.jupiter.api.Test) ParameterizedTest(org.junit.jupiter.params.ParameterizedTest)

Example 3 with BackOffDelayPolicy

use of com.rabbitmq.stream.BackOffDelayPolicy in project rabbitmq-stream-java-client by rabbitmq.

the class ConsumersCoordinatorTest method shouldRemoveClientSubscriptionManagerFromPoolIfEmptyAfterMetadataUpdate.

@Test
void shouldRemoveClientSubscriptionManagerFromPoolIfEmptyAfterMetadataUpdate() throws Exception {
    BackOffDelayPolicy delayPolicy = fixedWithInitialDelay(ms(50), ms(50));
    when(environment.topologyUpdateBackOffDelayPolicy()).thenReturn(delayPolicy);
    scheduledExecutorService = Executors.newSingleThreadScheduledExecutor();
    when(environment.scheduledExecutorService()).thenReturn(scheduledExecutorService);
    when(consumer.isOpen()).thenReturn(true);
    when(locator.metadata("stream")).thenReturn(metadata(null, replicas().subList(0, 1)));
    when(clientFactory.client(any())).thenReturn(client);
    when(client.subscribe(subscriptionIdCaptor.capture(), anyString(), any(OffsetSpecification.class), anyInt(), anyMap())).thenReturn(new Client.Response(Constants.RESPONSE_CODE_OK));
    int extraSubscriptionCount = ConsumersCoordinator.MAX_SUBSCRIPTIONS_PER_CLIENT / 5;
    int subscriptionCount = ConsumersCoordinator.MAX_SUBSCRIPTIONS_PER_CLIENT + extraSubscriptionCount;
    IntStream.range(0, subscriptionCount).forEach(i -> {
        coordinator.subscribe(consumer, "stream", OffsetSpecification.first(), null, NO_OP_SUBSCRIPTION_LISTENER, (offset, message) -> {
        });
    });
    // the extra is allocated on another client from the same pool
    verify(clientFactory, times(2)).client(any());
    verify(client, times(subscriptionCount)).subscribe(anyByte(), anyString(), any(OffsetSpecification.class), anyInt(), anyMap());
    List<ConsumersPoolInfo> info = MonitoringTestUtils.extract(coordinator);
    assertThat(info).hasSize(1).element(0).extracting(pool -> pool.consumerCount()).isEqualTo(subscriptionCount);
    // let's kill the first client connection
    metadataListeners.get(0).handle("stream", Constants.RESPONSE_CODE_STREAM_NOT_AVAILABLE);
    Thread.sleep(delayPolicy.delay(0).toMillis() * 5);
    info = MonitoringTestUtils.extract(coordinator);
    assertThat(info).hasSize(1).element(0).extracting(pool -> pool.consumerCount()).isEqualTo(subscriptionCount);
    // the MAX consumers must have been re-allocated to the existing client and a new one
    // let's add a new subscription to make sure we are still using the same pool
    coordinator.subscribe(consumer, "stream", OffsetSpecification.first(), null, NO_OP_SUBSCRIPTION_LISTENER, (offset, message) -> {
    });
    verify(clientFactory, times(2 + 1)).client(any());
    verify(client, times(subscriptionCount + ConsumersCoordinator.MAX_SUBSCRIPTIONS_PER_CLIENT + 1)).subscribe(anyByte(), anyString(), any(OffsetSpecification.class), anyInt(), anyMap());
    info = MonitoringTestUtils.extract(coordinator);
    assertThat(info).hasSize(1).element(0).extracting(pool -> pool.consumerCount()).isEqualTo(subscriptionCount + 1);
}
Also used : BeforeEach(org.junit.jupiter.api.BeforeEach) Arrays(java.util.Arrays) Assertions.assertThat(org.assertj.core.api.Assertions.assertThat) TestUtils.b(com.rabbitmq.stream.impl.TestUtils.b) MockitoAnnotations(org.mockito.MockitoAnnotations) StreamException(com.rabbitmq.stream.StreamException) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) Duration(java.time.Duration) Map(java.util.Map) ConsumersPoolInfo(com.rabbitmq.stream.impl.MonitoringTestUtils.ConsumersPoolInfo) MethodSource(org.junit.jupiter.params.provider.MethodSource) ClientFactory(com.rabbitmq.stream.impl.Utils.ClientFactory) TestUtils.namedConsumer(com.rabbitmq.stream.impl.TestUtils.namedConsumer) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) MessageListener(com.rabbitmq.stream.impl.Client.MessageListener) Collectors(java.util.stream.Collectors) Executors(java.util.concurrent.Executors) BackOffDelayPolicy(com.rabbitmq.stream.BackOffDelayPolicy) Test(org.junit.jupiter.api.Test) CountDownLatch(java.util.concurrent.CountDownLatch) ArgumentMatchers.anyByte(org.mockito.ArgumentMatchers.anyByte) List(java.util.List) Stream(java.util.stream.Stream) Constants(com.rabbitmq.stream.Constants) OffsetSpecification(com.rabbitmq.stream.OffsetSpecification) Mockito.mock(org.mockito.Mockito.mock) CopyOnWriteArrayList(java.util.concurrent.CopyOnWriteArrayList) ArgumentMatchers.any(org.mockito.ArgumentMatchers.any) IntStream(java.util.stream.IntStream) Mock(org.mockito.Mock) StreamDoesNotExistException(com.rabbitmq.stream.StreamDoesNotExistException) TestUtils.latchAssert(com.rabbitmq.stream.impl.TestUtils.latchAssert) ArgumentMatchers.anyMap(org.mockito.ArgumentMatchers.anyMap) BackOffDelayPolicy.fixedWithInitialDelay(com.rabbitmq.stream.BackOffDelayPolicy.fixedWithInitialDelay) Captor(org.mockito.Captor) WrapperMessageBuilder(com.rabbitmq.stream.codec.WrapperMessageBuilder) ArrayList(java.util.ArrayList) ArgumentCaptor(org.mockito.ArgumentCaptor) Assertions.assertThatThrownBy(org.assertj.core.api.Assertions.assertThatThrownBy) ScheduledExecutorService(java.util.concurrent.ScheduledExecutorService) ArgumentMatchers.anyInt(org.mockito.ArgumentMatchers.anyInt) QueryOffsetResponse(com.rabbitmq.stream.impl.Client.QueryOffsetResponse) ExecutorService(java.util.concurrent.ExecutorService) SubscriptionListener(com.rabbitmq.stream.SubscriptionListener) Mockito.times(org.mockito.Mockito.times) Mockito.when(org.mockito.Mockito.when) Mockito.verify(org.mockito.Mockito.verify) Consumer(java.util.function.Consumer) AfterEach(org.junit.jupiter.api.AfterEach) ParameterizedTest(org.junit.jupiter.params.ParameterizedTest) Collections(java.util.Collections) TestUtils.metadata(com.rabbitmq.stream.impl.TestUtils.metadata) ArgumentMatchers.anyString(org.mockito.ArgumentMatchers.anyString) OffsetSpecification(com.rabbitmq.stream.OffsetSpecification) ConsumersPoolInfo(com.rabbitmq.stream.impl.MonitoringTestUtils.ConsumersPoolInfo) BackOffDelayPolicy(com.rabbitmq.stream.BackOffDelayPolicy) Test(org.junit.jupiter.api.Test) ParameterizedTest(org.junit.jupiter.params.ParameterizedTest)

Example 4 with BackOffDelayPolicy

use of com.rabbitmq.stream.BackOffDelayPolicy in project rabbitmq-stream-java-client by rabbitmq.

the class ConsumersCoordinatorTest method metadataUpdate_shouldCloseConsumerIfRetryTimeoutIsReached.

@Test
void metadataUpdate_shouldCloseConsumerIfRetryTimeoutIsReached() throws Exception {
    Duration retryTimeout = Duration.ofMillis(200);
    BackOffDelayPolicy delayPolicy = fixedWithInitialDelay(ms(50), ms(50), ms(200));
    when(environment.topologyUpdateBackOffDelayPolicy()).thenReturn(delayPolicy);
    scheduledExecutorService = Executors.newSingleThreadScheduledExecutor();
    when(environment.scheduledExecutorService()).thenReturn(scheduledExecutorService);
    when(consumer.isOpen()).thenReturn(true);
    when(locator.metadata("stream")).thenReturn(metadata(null, replicas())).thenThrow(new IllegalStateException());
    when(clientFactory.client(any())).thenReturn(client);
    when(client.subscribe(subscriptionIdCaptor.capture(), anyString(), any(OffsetSpecification.class), anyInt(), anyMap())).thenReturn(new Client.Response(Constants.RESPONSE_CODE_OK));
    AtomicInteger messageHandlerCalls = new AtomicInteger();
    coordinator.subscribe(consumer, "stream", OffsetSpecification.first(), null, NO_OP_SUBSCRIPTION_LISTENER, (offset, message) -> messageHandlerCalls.incrementAndGet());
    verify(clientFactory, times(1)).client(any());
    verify(client, times(1)).subscribe(anyByte(), anyString(), any(OffsetSpecification.class), anyInt(), anyMap());
    assertThat(messageHandlerCalls.get()).isEqualTo(0);
    messageListener.handle(subscriptionIdCaptor.getValue(), 1, 0, new WrapperMessageBuilder().build());
    assertThat(messageHandlerCalls.get()).isEqualTo(1);
    metadataListener.handle("stream", Constants.RESPONSE_CODE_STREAM_NOT_AVAILABLE);
    Thread.sleep(delayPolicy.delay(0).toMillis() + retryTimeout.toMillis() * 2);
    verify(consumer, times(1)).closeAfterStreamDeletion();
    verify(client, times(1)).subscribe(anyByte(), anyString(), any(OffsetSpecification.class), anyInt(), anyMap());
    verify(client, times(0)).unsubscribe(anyByte());
    assertThat(coordinator.poolSize()).isZero();
}
Also used : OffsetSpecification(com.rabbitmq.stream.OffsetSpecification) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) WrapperMessageBuilder(com.rabbitmq.stream.codec.WrapperMessageBuilder) Duration(java.time.Duration) BackOffDelayPolicy(com.rabbitmq.stream.BackOffDelayPolicy) Test(org.junit.jupiter.api.Test) ParameterizedTest(org.junit.jupiter.params.ParameterizedTest)

Example 5 with BackOffDelayPolicy

use of com.rabbitmq.stream.BackOffDelayPolicy in project rabbitmq-stream-java-client by rabbitmq.

the class ConsumersCoordinatorTest method shouldRedistributeConsumerOnMetadataUpdate.

@Test
void shouldRedistributeConsumerOnMetadataUpdate() throws Exception {
    BackOffDelayPolicy delayPolicy = fixedWithInitialDelay(ms(100), ms(100));
    when(environment.topologyUpdateBackOffDelayPolicy()).thenReturn(delayPolicy);
    scheduledExecutorService = Executors.newSingleThreadScheduledExecutor();
    when(environment.scheduledExecutorService()).thenReturn(scheduledExecutorService);
    when(consumer.isOpen()).thenReturn(true);
    when(locator.metadata("stream")).thenReturn(metadata(null, replicas()));
    when(clientFactory.client(any())).thenReturn(client);
    StreamConsumer consumerClosedAfterMetadataUpdate = mock(StreamConsumer.class);
    when(consumerClosedAfterMetadataUpdate.isOpen()).thenReturn(false);
    when(client.subscribe(subscriptionIdCaptor.capture(), anyString(), any(OffsetSpecification.class), anyInt(), anyMap())).thenReturn(new Client.Response(Constants.RESPONSE_CODE_OK));
    AtomicInteger messageHandlerCalls = new AtomicInteger();
    Runnable closingRunnable = coordinator.subscribe(consumer, "stream", OffsetSpecification.first(), null, NO_OP_SUBSCRIPTION_LISTENER, (offset, message) -> messageHandlerCalls.incrementAndGet());
    verify(clientFactory, times(1)).client(any());
    verify(client, times(1)).subscribe(anyByte(), anyString(), any(OffsetSpecification.class), anyInt(), anyMap());
    coordinator.subscribe(consumerClosedAfterMetadataUpdate, "stream", OffsetSpecification.first(), null, NO_OP_SUBSCRIPTION_LISTENER, (offset, message) -> {
    });
    verify(client, times(1 + 1)).subscribe(anyByte(), anyString(), any(OffsetSpecification.class), anyInt(), anyMap());
    assertThat(messageHandlerCalls.get()).isEqualTo(0);
    firstMessageListener().handle(subscriptionIdCaptor.getAllValues().get(0), 1, 0, new WrapperMessageBuilder().build());
    assertThat(messageHandlerCalls.get()).isEqualTo(1);
    this.metadataListeners.forEach(ml -> ml.handle("stream", Constants.RESPONSE_CODE_STREAM_NOT_AVAILABLE));
    Thread.sleep(delayPolicy.delay(0).toMillis() * 5);
    // the second consumer does not re-subscribe because it returns it is not open
    verify(client, times(2 + 1)).subscribe(anyByte(), anyString(), any(OffsetSpecification.class), anyInt(), anyMap());
    assertThat(messageHandlerCalls.get()).isEqualTo(1);
    lastMessageListener().handle(subscriptionIdCaptor.getAllValues().get(0), 0, 0, new WrapperMessageBuilder().build());
    assertThat(messageHandlerCalls.get()).isEqualTo(2);
    when(client.unsubscribe(subscriptionIdCaptor.getValue())).thenReturn(new Client.Response(Constants.RESPONSE_CODE_OK));
    closingRunnable.run();
    verify(client, times(1)).unsubscribe(subscriptionIdCaptor.getValue());
    lastMessageListener().handle(subscriptionIdCaptor.getValue(), 0, 0, new WrapperMessageBuilder().build());
    assertThat(messageHandlerCalls.get()).isEqualTo(2);
    assertThat(coordinator.poolSize()).isZero();
}
Also used : OffsetSpecification(com.rabbitmq.stream.OffsetSpecification) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) WrapperMessageBuilder(com.rabbitmq.stream.codec.WrapperMessageBuilder) BackOffDelayPolicy(com.rabbitmq.stream.BackOffDelayPolicy) Test(org.junit.jupiter.api.Test) ParameterizedTest(org.junit.jupiter.params.ParameterizedTest)

Aggregations

BackOffDelayPolicy (com.rabbitmq.stream.BackOffDelayPolicy)5 OffsetSpecification (com.rabbitmq.stream.OffsetSpecification)5 WrapperMessageBuilder (com.rabbitmq.stream.codec.WrapperMessageBuilder)5 AtomicInteger (java.util.concurrent.atomic.AtomicInteger)5 Test (org.junit.jupiter.api.Test)5 ParameterizedTest (org.junit.jupiter.params.ParameterizedTest)5 Duration (java.time.Duration)2 BackOffDelayPolicy.fixedWithInitialDelay (com.rabbitmq.stream.BackOffDelayPolicy.fixedWithInitialDelay)1 Constants (com.rabbitmq.stream.Constants)1 StreamDoesNotExistException (com.rabbitmq.stream.StreamDoesNotExistException)1 StreamException (com.rabbitmq.stream.StreamException)1 SubscriptionListener (com.rabbitmq.stream.SubscriptionListener)1 MessageListener (com.rabbitmq.stream.impl.Client.MessageListener)1 QueryOffsetResponse (com.rabbitmq.stream.impl.Client.QueryOffsetResponse)1 ConsumersPoolInfo (com.rabbitmq.stream.impl.MonitoringTestUtils.ConsumersPoolInfo)1 TestUtils.b (com.rabbitmq.stream.impl.TestUtils.b)1 TestUtils.latchAssert (com.rabbitmq.stream.impl.TestUtils.latchAssert)1 TestUtils.metadata (com.rabbitmq.stream.impl.TestUtils.metadata)1 TestUtils.namedConsumer (com.rabbitmq.stream.impl.TestUtils.namedConsumer)1 ClientFactory (com.rabbitmq.stream.impl.Utils.ClientFactory)1