Search in sources :

Example 1 with Base64UrlNamingStrategy

use of org.springframework.amqp.core.Base64UrlNamingStrategy in project spring-cloud-stream by spring-cloud.

the class RabbitBinderCleanerTests method testCleanStream.

@Test
public void testCleanStream() {
    final RabbitBindingCleaner cleaner = new RabbitBindingCleaner();
    final String stream1 = new Base64UrlNamingStrategy("foo").generateName();
    String stream2 = stream1 + "-1";
    String firstQueue = null;
    CachingConnectionFactory connectionFactory = rabbitTestSupport.getResource();
    RabbitAdmin rabbitAdmin = new RabbitAdmin(connectionFactory);
    for (int i = 0; i < 5; i++) {
        String queue1Name = AbstractBinder.applyPrefix(BINDER_PREFIX, stream1 + ".default." + i);
        String queue2Name = AbstractBinder.applyPrefix(BINDER_PREFIX, stream2 + ".default." + i);
        if (firstQueue == null) {
            firstQueue = queue1Name;
        }
        rabbitAdmin.declareQueue(new Queue(queue1Name, true, false, false));
        rabbitAdmin.declareQueue(new Queue(queue2Name, true, false, false));
        rabbitAdmin.declareQueue(new Queue(AbstractBinder.constructDLQName(queue1Name), true, false, false));
        TopicExchange exchange = new TopicExchange(queue1Name);
        rabbitAdmin.declareExchange(exchange);
        rabbitAdmin.declareBinding(BindingBuilder.bind(new Queue(queue1Name)).to(exchange).with(queue1Name));
        exchange = new TopicExchange(queue2Name);
        rabbitAdmin.declareExchange(exchange);
        rabbitAdmin.declareBinding(BindingBuilder.bind(new Queue(queue2Name)).to(exchange).with(queue2Name));
    }
    final TopicExchange topic1 = new TopicExchange(AbstractBinder.applyPrefix(BINDER_PREFIX, stream1 + ".foo.bar"));
    rabbitAdmin.declareExchange(topic1);
    rabbitAdmin.declareBinding(BindingBuilder.bind(new Queue(firstQueue)).to(topic1).with("#"));
    String foreignQueue = UUID.randomUUID().toString();
    rabbitAdmin.declareQueue(new Queue(foreignQueue));
    rabbitAdmin.declareBinding(BindingBuilder.bind(new Queue(foreignQueue)).to(topic1).with("#"));
    final TopicExchange topic2 = new TopicExchange(AbstractBinder.applyPrefix(BINDER_PREFIX, stream2 + ".foo.bar"));
    rabbitAdmin.declareExchange(topic2);
    rabbitAdmin.declareBinding(BindingBuilder.bind(new Queue(firstQueue)).to(topic2).with("#"));
    new RabbitTemplate(connectionFactory).execute(new ChannelCallback<Void>() {

        @Override
        public Void doInRabbit(Channel channel) throws Exception {
            String queueName = AbstractBinder.applyPrefix(BINDER_PREFIX, stream1 + ".default." + 4);
            String consumerTag = channel.basicConsume(queueName, new DefaultConsumer(channel));
            try {
                waitForConsumerStateNot(queueName, 0);
                doClean(cleaner, stream1, false);
                fail("Expected exception");
            } catch (RabbitAdminException e) {
                assertThat(e).hasMessageContaining("Queue " + queueName + " is in use");
            }
            channel.basicCancel(consumerTag);
            waitForConsumerStateNot(queueName, 1);
            try {
                doClean(cleaner, stream1, false);
                fail("Expected exception");
            } catch (RabbitAdminException e) {
                assertThat(e).hasMessageContaining("Cannot delete exchange ");
                assertThat(e).hasMessageContaining("; it has bindings:");
            }
            return null;
        }

        private void waitForConsumerStateNot(String queueName, long state) throws InterruptedException {
            int n = 0;
            QueueInfo queue = client.getQueue("/", queueName);
            while (n++ < 100 && (queue == null || queue.getConsumerCount() == state)) {
                Thread.sleep(100);
                queue = client.getQueue("/", queueName);
            }
            assertThat(n).withFailMessage("Consumer state remained at " + state + " after 10 seconds").isLessThan(100);
        }
    });
    // easier than deleting the binding
    rabbitAdmin.deleteExchange(topic1.getName());
    rabbitAdmin.declareExchange(topic1);
    rabbitAdmin.deleteQueue(foreignQueue);
    connectionFactory.destroy();
    Map<String, List<String>> cleanedMap = doClean(cleaner, stream1, false);
    assertThat(cleanedMap).hasSize(2);
    List<String> cleanedQueues = cleanedMap.get("queues");
    // should *not* clean stream2
    assertThat(cleanedQueues).hasSize(10);
    for (int i = 0; i < 5; i++) {
        assertThat(cleanedQueues.get(i * 2)).isEqualTo(BINDER_PREFIX + stream1 + ".default." + i);
        assertThat(cleanedQueues.get(i * 2 + 1)).isEqualTo(BINDER_PREFIX + stream1 + ".default." + i + ".dlq");
    }
    List<String> cleanedExchanges = cleanedMap.get("exchanges");
    assertThat(cleanedExchanges).hasSize(6);
    // wild card *should* clean stream2
    cleanedMap = doClean(cleaner, stream1 + "*", false);
    assertThat(cleanedMap).hasSize(2);
    cleanedQueues = cleanedMap.get("queues");
    assertThat(cleanedQueues).hasSize(5);
    for (int i = 0; i < 5; i++) {
        assertThat(cleanedQueues.get(i)).isEqualTo(BINDER_PREFIX + stream2 + ".default." + i);
    }
    cleanedExchanges = cleanedMap.get("exchanges");
    assertThat(cleanedExchanges).hasSize(6);
}
Also used : RabbitTemplate(org.springframework.amqp.rabbit.core.RabbitTemplate) QueueInfo(com.rabbitmq.http.client.domain.QueueInfo) DefaultConsumer(com.rabbitmq.client.DefaultConsumer) Channel(com.rabbitmq.client.Channel) RabbitAdmin(org.springframework.amqp.rabbit.core.RabbitAdmin) RabbitBindingCleaner(org.springframework.cloud.stream.binder.rabbit.admin.RabbitBindingCleaner) URISyntaxException(java.net.URISyntaxException) MalformedURLException(java.net.MalformedURLException) RabbitAdminException(org.springframework.cloud.stream.binder.rabbit.admin.RabbitAdminException) TopicExchange(org.springframework.amqp.core.TopicExchange) Base64UrlNamingStrategy(org.springframework.amqp.core.Base64UrlNamingStrategy) CachingConnectionFactory(org.springframework.amqp.rabbit.connection.CachingConnectionFactory) List(java.util.List) Queue(org.springframework.amqp.core.Queue) RabbitAdminException(org.springframework.cloud.stream.binder.rabbit.admin.RabbitAdminException) Test(org.junit.jupiter.api.Test)

Example 2 with Base64UrlNamingStrategy

use of org.springframework.amqp.core.Base64UrlNamingStrategy in project spring-cloud-stream by spring-cloud.

the class RabbitExchangeQueueProvisioner method doProvisionConsumerDestination.

private ConsumerDestination doProvisionConsumerDestination(String name, String group, ExtendedConsumerProperties<RabbitConsumerProperties> properties) {
    boolean anonymous = !StringUtils.hasText(group);
    String anonymousGroup = null;
    if (anonymous) {
        anonymousGroup = new Base64UrlNamingStrategy(properties.getExtension().getAnonymousGroupPrefix() == null ? "" : properties.getExtension().getAnonymousGroupPrefix()).generateName();
    }
    String baseQueueName;
    if (properties.getExtension().isQueueNameGroupOnly()) {
        baseQueueName = anonymous ? anonymousGroup : group;
    } else {
        baseQueueName = groupedName(name, anonymous ? anonymousGroup : group);
    }
    if (this.logger.isInfoEnabled()) {
        this.logger.info("declaring queue for inbound: " + baseQueueName + ", bound to: " + name);
    }
    String prefix = properties.getExtension().getPrefix();
    final String exchangeName = applyPrefix(prefix, name);
    Exchange exchange = buildExchange(properties.getExtension(), exchangeName);
    if (properties.getExtension().isDeclareExchange()) {
        declareExchange(exchangeName, anonymous ? anonymousGroup : group, exchange);
    }
    String queueName = applyPrefix(prefix, baseQueueName);
    boolean partitioned = !anonymous && properties.isPartitioned();
    boolean durable = !anonymous && properties.getExtension().isDurableSubscription();
    Queue queue;
    if (anonymous) {
        String anonQueueName = queueName;
        queue = new AnonymousQueue((org.springframework.amqp.core.NamingStrategy) () -> anonQueueName, queueArgs(queueName, properties.getExtension(), false));
    } else {
        if (partitioned) {
            String partitionSuffix = "-" + properties.getInstanceIndex();
            queueName += partitionSuffix;
        }
        if (durable) {
            queue = new Queue(queueName, true, false, false, queueArgs(queueName, properties.getExtension(), false));
        } else {
            queue = new Queue(queueName, false, false, true, queueArgs(queueName, properties.getExtension(), false));
        }
    }
    Binding binding = null;
    if (properties.getExtension().isBindQueue()) {
        if (properties.getExtension().getContainerType().equals(ContainerType.STREAM)) {
            queue.getArguments().put("x-queue-type", "stream");
        }
        declareQueue(queueName, queue);
        String[] routingKeys = bindingRoutingKeys(properties.getExtension());
        if (ObjectUtils.isEmpty(routingKeys)) {
            binding = declareConsumerBindings(name, null, properties, exchange, partitioned, queue);
        } else {
            for (String routingKey : routingKeys) {
                binding = declareConsumerBindings(name, routingKey, properties, exchange, partitioned, queue);
            }
        }
    }
    if (durable) {
        autoBindDLQ(applyPrefix(properties.getExtension().getPrefix(), baseQueueName), queueName, group, properties.getExtension());
    }
    return new RabbitConsumerDestination(queue.getName(), binding, anonymous ? baseQueueName : group, name);
}
Also used : Exchange(org.springframework.amqp.core.Exchange) DirectExchange(org.springframework.amqp.core.DirectExchange) FanoutExchange(org.springframework.amqp.core.FanoutExchange) HeadersExchange(org.springframework.amqp.core.HeadersExchange) TopicExchange(org.springframework.amqp.core.TopicExchange) Binding(org.springframework.amqp.core.Binding) Base64UrlNamingStrategy(org.springframework.amqp.core.Base64UrlNamingStrategy) AnonymousQueue(org.springframework.amqp.core.AnonymousQueue) Base64UrlNamingStrategy(org.springframework.amqp.core.Base64UrlNamingStrategy) Queue(org.springframework.amqp.core.Queue) AnonymousQueue(org.springframework.amqp.core.AnonymousQueue)

Aggregations

Base64UrlNamingStrategy (org.springframework.amqp.core.Base64UrlNamingStrategy)2 Queue (org.springframework.amqp.core.Queue)2 TopicExchange (org.springframework.amqp.core.TopicExchange)2 Channel (com.rabbitmq.client.Channel)1 DefaultConsumer (com.rabbitmq.client.DefaultConsumer)1 QueueInfo (com.rabbitmq.http.client.domain.QueueInfo)1 MalformedURLException (java.net.MalformedURLException)1 URISyntaxException (java.net.URISyntaxException)1 List (java.util.List)1 Test (org.junit.jupiter.api.Test)1 AnonymousQueue (org.springframework.amqp.core.AnonymousQueue)1 Binding (org.springframework.amqp.core.Binding)1 DirectExchange (org.springframework.amqp.core.DirectExchange)1 Exchange (org.springframework.amqp.core.Exchange)1 FanoutExchange (org.springframework.amqp.core.FanoutExchange)1 HeadersExchange (org.springframework.amqp.core.HeadersExchange)1 CachingConnectionFactory (org.springframework.amqp.rabbit.connection.CachingConnectionFactory)1 RabbitAdmin (org.springframework.amqp.rabbit.core.RabbitAdmin)1 RabbitTemplate (org.springframework.amqp.rabbit.core.RabbitTemplate)1 RabbitAdminException (org.springframework.cloud.stream.binder.rabbit.admin.RabbitAdminException)1