Search in sources :

Example 26 with PersistentSubscription

use of org.apache.pulsar.broker.service.persistent.PersistentSubscription in project incubator-pulsar by apache.

the class PersistentFailoverE2ETest method testSimpleConsumerEventsWithoutPartition.

@Test
public void testSimpleConsumerEventsWithoutPartition() throws Exception {
    final String topicName = "persistent://prop/use/ns-abc/failover-topic1";
    final String subName = "sub1";
    final int numMsgs = 100;
    TestConsumerStateEventListener listener1 = new TestConsumerStateEventListener();
    TestConsumerStateEventListener listener2 = new TestConsumerStateEventListener();
    ConsumerBuilder<byte[]> consumerBuilder = pulsarClient.newConsumer().topic(topicName).subscriptionName(subName).subscriptionType(SubscriptionType.Failover);
    // 1. two consumers on the same subscription
    ConsumerBuilder<byte[]> consumerBulder1 = consumerBuilder.clone().consumerName("1").consumerEventListener(listener1);
    Consumer<byte[]> consumer1 = consumerBulder1.subscribe();
    Consumer<byte[]> consumer2 = consumerBuilder.clone().consumerName("2").consumerEventListener(listener2).subscribe();
    verifyConsumerActive(listener1, -1);
    verifyConsumerInactive(listener2, -1);
    PersistentTopic topicRef = (PersistentTopic) pulsar.getBrokerService().getTopicReference(topicName);
    PersistentSubscription subRef = topicRef.getSubscription(subName);
    assertNotNull(topicRef);
    assertNotNull(subRef);
    // 2. validate basic dispatcher state
    assertTrue(subRef.getDispatcher().isConsumerConnected());
    assertEquals(subRef.getDispatcher().getType(), SubType.Failover);
    List<CompletableFuture<MessageId>> futures = Lists.newArrayListWithCapacity(numMsgs);
    Producer<byte[]> producer = pulsarClient.newProducer().topic(topicName).create();
    for (int i = 0; i < numMsgs; i++) {
        String message = "my-message-" + i;
        futures.add(producer.sendAsync(message.getBytes()));
    }
    FutureUtil.waitForAll(futures).get();
    futures.clear();
    rolloverPerIntervalStats();
    assertEquals(subRef.getNumberOfEntriesInBacklog(), numMsgs);
    Thread.sleep(ASYNC_EVENT_COMPLETION_WAIT);
    // 3. consumer1 should have all the messages while consumer2 should have no messages
    Message<byte[]> msg = null;
    Assert.assertNull(consumer2.receive(1, TimeUnit.SECONDS));
    for (int i = 0; i < numMsgs; i++) {
        msg = consumer1.receive(1, TimeUnit.SECONDS);
        Assert.assertNotNull(msg);
        Assert.assertEquals(new String(msg.getData()), "my-message-" + i);
        consumer1.acknowledge(msg);
    }
    rolloverPerIntervalStats();
    // 4. messages deleted on individual acks
    Thread.sleep(ASYNC_EVENT_COMPLETION_WAIT);
    assertEquals(subRef.getNumberOfEntriesInBacklog(), 0);
    for (int i = 0; i < numMsgs; i++) {
        String message = "my-message-" + i;
        futures.add(producer.sendAsync(message.getBytes()));
    }
    FutureUtil.waitForAll(futures).get();
    futures.clear();
    // 5. master consumer failure should resend unacked messages and new messages to another consumer
    for (int i = 0; i < 5; i++) {
        msg = consumer1.receive(1, TimeUnit.SECONDS);
        Assert.assertNotNull(msg);
        Assert.assertEquals(new String(msg.getData()), "my-message-" + i);
        consumer1.acknowledge(msg);
    }
    for (int i = 5; i < 10; i++) {
        msg = consumer1.receive(1, TimeUnit.SECONDS);
        Assert.assertNotNull(msg);
        Assert.assertEquals(new String(msg.getData()), "my-message-" + i);
    // do not ack
    }
    consumer1.close();
    Thread.sleep(CONSUMER_ADD_OR_REMOVE_WAIT_TIME);
    verifyConsumerActive(listener2, -1);
    verifyConsumerNotReceiveAnyStateChanges(listener1);
    for (int i = 5; i < numMsgs; i++) {
        msg = consumer2.receive(1, TimeUnit.SECONDS);
        Assert.assertNotNull(msg);
        Assert.assertEquals(new String(msg.getData()), "my-message-" + i);
        consumer2.acknowledge(msg);
    }
    Assert.assertNull(consumer2.receive(1, TimeUnit.SECONDS));
    rolloverPerIntervalStats();
    Thread.sleep(ASYNC_EVENT_COMPLETION_WAIT);
    assertEquals(subRef.getNumberOfEntriesInBacklog(), 0);
    for (int i = 0; i < numMsgs; i++) {
        String message = "my-message-" + i;
        futures.add(producer.sendAsync(message.getBytes()));
    }
    FutureUtil.waitForAll(futures).get();
    futures.clear();
    // 6. consumer subscription should send messages to the new consumer if its name is highest in the list
    for (int i = 0; i < 5; i++) {
        msg = consumer2.receive(1, TimeUnit.SECONDS);
        Assert.assertNotNull(msg);
        Assert.assertEquals(new String(msg.getData()), "my-message-" + i);
        consumer2.acknowledge(msg);
    }
    consumer1 = consumerBulder1.subscribe();
    Thread.sleep(CONSUMER_ADD_OR_REMOVE_WAIT_TIME);
    for (int i = 5; i < numMsgs; i++) {
        msg = consumer1.receive(1, TimeUnit.SECONDS);
        Assert.assertNotNull(msg);
        Assert.assertEquals(new String(msg.getData()), "my-message-" + i);
        consumer1.acknowledge(msg);
    }
    Assert.assertNull(consumer1.receive(1, TimeUnit.SECONDS));
    rolloverPerIntervalStats();
    Thread.sleep(ASYNC_EVENT_COMPLETION_WAIT);
    assertEquals(subRef.getNumberOfEntriesInBacklog(), 0);
    for (int i = 0; i < numMsgs; i++) {
        String message = "my-message-" + i;
        futures.add(producer.sendAsync(message.getBytes()));
    }
    FutureUtil.waitForAll(futures).get();
    futures.clear();
    // 7. consumer subscription should not send messages to the new consumer if its name is not highest in the list
    for (int i = 0; i < 5; i++) {
        msg = consumer1.receive(1, TimeUnit.SECONDS);
        Assert.assertNotNull(msg);
        Assert.assertEquals(new String(msg.getData()), "my-message-" + i);
        consumer1.acknowledge(msg);
    }
    TestConsumerStateEventListener listener3 = new TestConsumerStateEventListener();
    Consumer<byte[]> consumer3 = consumerBuilder.clone().consumerName("3").consumerEventListener(listener3).subscribe();
    Thread.sleep(CONSUMER_ADD_OR_REMOVE_WAIT_TIME);
    verifyConsumerInactive(listener3, -1);
    Assert.assertNull(consumer3.receive(1, TimeUnit.SECONDS));
    for (int i = 5; i < numMsgs; i++) {
        msg = consumer1.receive(1, TimeUnit.SECONDS);
        Assert.assertNotNull(msg);
        Assert.assertEquals(new String(msg.getData()), "my-message-" + i);
        consumer1.acknowledge(msg);
    }
    rolloverPerIntervalStats();
    Thread.sleep(ASYNC_EVENT_COMPLETION_WAIT);
    assertEquals(subRef.getNumberOfEntriesInBacklog(), 0);
    // 8. unsubscribe not allowed if multiple consumers connected
    try {
        consumer1.unsubscribe();
        fail("should fail");
    } catch (PulsarClientException e) {
    // ok
    }
    // 9. unsubscribe allowed if there is a lone consumer
    consumer1.close();
    Thread.sleep(CONSUMER_ADD_OR_REMOVE_WAIT_TIME);
    consumer2.close();
    Thread.sleep(CONSUMER_ADD_OR_REMOVE_WAIT_TIME);
    try {
        consumer3.unsubscribe();
    } catch (PulsarClientException e) {
        fail("Should not fail", e);
    }
    Thread.sleep(ASYNC_EVENT_COMPLETION_WAIT);
    subRef = topicRef.getSubscription(subName);
    assertNull(subRef);
    producer.close();
    consumer3.close();
    admin.persistentTopics().delete(topicName);
}
Also used : CompletableFuture(java.util.concurrent.CompletableFuture) PersistentTopic(org.apache.pulsar.broker.service.persistent.PersistentTopic) PulsarClientException(org.apache.pulsar.client.api.PulsarClientException) PersistentSubscription(org.apache.pulsar.broker.service.persistent.PersistentSubscription) Test(org.testng.annotations.Test)

Example 27 with PersistentSubscription

use of org.apache.pulsar.broker.service.persistent.PersistentSubscription in project incubator-pulsar by apache.

the class PersistentTopicConcurrentTest method testConcurrentTopicAndSubscriptionDelete.

// @Test
public void testConcurrentTopicAndSubscriptionDelete() throws Exception {
    // create topic
    final PersistentTopic topic = (PersistentTopic) brokerService.getTopic(successTopicName).get();
    PulsarApi.CommandSubscribe cmd = PulsarApi.CommandSubscribe.newBuilder().setConsumerId(1).setTopic(successTopicName).setSubscription(successSubName).setRequestId(1).setSubType(PulsarApi.CommandSubscribe.SubType.Exclusive).build();
    Future<Consumer> f1 = topic.subscribe(serverCnx, cmd.getSubscription(), cmd.getConsumerId(), cmd.getSubType(), 0, cmd.getConsumerName(), cmd.getDurable(), null, Collections.emptyMap(), cmd.getReadCompacted(), InitialPosition.Latest);
    f1.get();
    final CyclicBarrier barrier = new CyclicBarrier(2);
    final CountDownLatch counter = new CountDownLatch(2);
    final AtomicBoolean gotException = new AtomicBoolean(false);
    Thread deleter = new Thread() {

        public void run() {
            try {
                barrier.await();
                // assertTrue(topic.unsubscribe(successSubName).isDone());
                Thread.sleep(5, 0);
                log.info("deleter outcome is {}", topic.delete().get());
            } catch (Exception e) {
                e.printStackTrace();
                gotException.set(true);
            } finally {
                counter.countDown();
            }
        }
    };
    Thread unsubscriber = new Thread() {

        public void run() {
            try {
                barrier.await();
                // do subscription delete
                ConcurrentOpenHashMap<String, PersistentSubscription> subscriptions = topic.getSubscriptions();
                PersistentSubscription ps = subscriptions.get(successSubName);
                // Thread.sleep(2,0);
                log.info("unsubscriber outcome is {}", ps.doUnsubscribe(ps.getConsumers().get(0)).get());
            // assertFalse(ps.delete().isCompletedExceptionally());
            } catch (Exception e) {
                e.printStackTrace();
                gotException.set(true);
            } finally {
                counter.countDown();
            }
        }
    };
    deleter.start();
    unsubscriber.start();
    counter.await();
    assertEquals(gotException.get(), false);
}
Also used : PulsarApi(org.apache.pulsar.common.api.proto.PulsarApi) CountDownLatch(java.util.concurrent.CountDownLatch) PersistentSubscription(org.apache.pulsar.broker.service.persistent.PersistentSubscription) CyclicBarrier(java.util.concurrent.CyclicBarrier) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) Consumer(org.apache.pulsar.broker.service.Consumer) PersistentTopic(org.apache.pulsar.broker.service.persistent.PersistentTopic)

Example 28 with PersistentSubscription

use of org.apache.pulsar.broker.service.persistent.PersistentSubscription in project incubator-pulsar by apache.

the class PersistentTopicE2ETest method testTopicDeleteWithDisconnectedSubscription.

@Test
public void testTopicDeleteWithDisconnectedSubscription() throws Exception {
    final String topicName = "persistent://prop/use/ns-abc/topic8";
    final String subName = "sub1";
    // 1. client connect
    Consumer<byte[]> consumer = pulsarClient.newConsumer().topic(topicName).subscriptionName(subName).subscribe();
    PersistentTopic topicRef = (PersistentTopic) pulsar.getBrokerService().getTopicReference(topicName);
    PersistentSubscription subRef = topicRef.getSubscription(subName);
    assertNotNull(topicRef);
    assertNotNull(subRef);
    assertTrue(subRef.getDispatcher().isConsumerConnected());
    // 2. client disconnect
    consumer.close();
    assertFalse(subRef.getDispatcher().isConsumerConnected());
    // 3. delete topic
    admin.persistentTopics().delete(topicName);
    try {
        admin.persistentTopics().getStats(topicName);
    } catch (PulsarAdminException e) {
    // ok
    }
}
Also used : PersistentTopic(org.apache.pulsar.broker.service.persistent.PersistentTopic) PulsarAdminException(org.apache.pulsar.client.admin.PulsarAdminException) PersistentSubscription(org.apache.pulsar.broker.service.persistent.PersistentSubscription) Test(org.testng.annotations.Test)

Example 29 with PersistentSubscription

use of org.apache.pulsar.broker.service.persistent.PersistentSubscription in project incubator-pulsar by apache.

the class PersistentTopicE2ETest method testSubscriptionTypeTransitions.

@Test
public void testSubscriptionTypeTransitions() throws Exception {
    final String topicName = "persistent://prop/use/ns-abc/shared-topic2";
    final String subName = "sub2";
    Consumer<byte[]> consumer1 = pulsarClient.newConsumer().topic(topicName).subscriptionName(subName).subscriptionType(SubscriptionType.Exclusive).subscribe();
    Consumer<byte[]> consumer2 = null;
    Consumer<byte[]> consumer3 = null;
    PersistentTopic topicRef = (PersistentTopic) pulsar.getBrokerService().getTopicReference(topicName);
    PersistentSubscription subRef = topicRef.getSubscription(subName);
    // 1. shared consumer on an exclusive sub fails
    try {
        consumer2 = pulsarClient.newConsumer().topic(topicName).subscriptionName(subName).subscriptionType(SubscriptionType.Shared).subscribe();
        fail("should have failed");
    } catch (PulsarClientException e) {
        assertTrue(e.getMessage().contains("Subscription is of different type"));
    }
    // 2. failover consumer on an exclusive sub fails
    try {
        consumer3 = pulsarClient.newConsumer().topic(topicName).subscriptionName(subName).subscriptionType(SubscriptionType.Failover).subscribe();
        fail("should have failed");
    } catch (PulsarClientException e) {
        assertTrue(e.getMessage().contains("Subscription is of different type"));
    }
    // 3. disconnected sub can be converted in shared
    consumer1.close();
    try {
        consumer2 = pulsarClient.newConsumer().topic(topicName).subscriptionName(subName).subscriptionType(SubscriptionType.Shared).subscribe();
        assertEquals(subRef.getDispatcher().getType(), SubType.Shared);
    } catch (PulsarClientException e) {
        fail("should not fail");
    }
    // 4. exclusive fails on shared sub
    try {
        consumer1 = pulsarClient.newConsumer().topic(topicName).subscriptionName(subName).subscriptionType(SubscriptionType.Exclusive).subscribe();
        fail("should have failed");
    } catch (PulsarClientException e) {
        assertTrue(e.getMessage().contains("Subscription is of different type"));
    }
    // 5. disconnected sub can be converted in failover
    consumer2.close();
    try {
        consumer3 = pulsarClient.newConsumer().topic(topicName).subscriptionName(subName).subscriptionType(SubscriptionType.Failover).subscribe();
        assertEquals(subRef.getDispatcher().getType(), SubType.Failover);
    } catch (PulsarClientException e) {
        fail("should not fail");
    }
    // 5. exclusive consumer can connect after failover disconnects
    consumer3.close();
    try {
        consumer1 = pulsarClient.newConsumer().topic(topicName).subscriptionName(subName).subscriptionType(SubscriptionType.Exclusive).subscribe();
        assertEquals(subRef.getDispatcher().getType(), SubType.Exclusive);
    } catch (PulsarClientException e) {
        fail("should not fail");
    }
    consumer1.close();
    admin.persistentTopics().delete(topicName);
}
Also used : PersistentTopic(org.apache.pulsar.broker.service.persistent.PersistentTopic) PulsarClientException(org.apache.pulsar.client.api.PulsarClientException) PersistentSubscription(org.apache.pulsar.broker.service.persistent.PersistentSubscription) Test(org.testng.annotations.Test)

Example 30 with PersistentSubscription

use of org.apache.pulsar.broker.service.persistent.PersistentSubscription in project incubator-pulsar by apache.

the class PersistentTopicE2ETest method testMessageExpiryWithFewExpiredBacklog.

@Test
public void testMessageExpiryWithFewExpiredBacklog() throws Exception {
    int messageTTLSecs = 10;
    String namespaceName = "prop/use/expiry-check-1";
    admin.namespaces().createNamespace(namespaceName);
    admin.namespaces().setNamespaceMessageTTL(namespaceName, messageTTLSecs);
    final String topicName = "persistent://prop/use/expiry-check-1/topic1";
    final String subName = "sub1";
    final int numMsgs = 10;
    pulsarClient.newConsumer().topic(topicName).subscriptionName(subName).subscribe();
    PersistentTopic topicRef = (PersistentTopic) pulsar.getBrokerService().getTopicReference(topicName);
    PersistentSubscription subRef = topicRef.getSubscription(subName);
    assertTrue(subRef.getDispatcher().isConsumerConnected());
    Producer<byte[]> producer = pulsarClient.newProducer().topic(topicName).create();
    for (int i = 0; i < numMsgs; i++) {
        String message = "my-message-" + i;
        producer.send(message.getBytes());
    }
    rolloverPerIntervalStats();
    assertEquals(subRef.getNumberOfEntriesInBacklog(), numMsgs);
    Thread.sleep(TimeUnit.SECONDS.toMillis(messageTTLSecs));
    runMessageExpiryCheck();
    assertEquals(subRef.getNumberOfEntriesInBacklog(), numMsgs);
    Thread.sleep(TimeUnit.SECONDS.toMillis(messageTTLSecs / 2));
    runMessageExpiryCheck();
    assertEquals(subRef.getNumberOfEntriesInBacklog(), 0);
}
Also used : PersistentTopic(org.apache.pulsar.broker.service.persistent.PersistentTopic) PersistentSubscription(org.apache.pulsar.broker.service.persistent.PersistentSubscription) Test(org.testng.annotations.Test)

Aggregations

PersistentSubscription (org.apache.pulsar.broker.service.persistent.PersistentSubscription)34 PersistentTopic (org.apache.pulsar.broker.service.persistent.PersistentTopic)34 Test (org.testng.annotations.Test)20 PulsarClientException (org.apache.pulsar.client.api.PulsarClientException)13 ExecutionException (java.util.concurrent.ExecutionException)9 ManagedLedgerException (org.apache.bookkeeper.mledger.ManagedLedgerException)9 PersistentDispatcherSingleActiveConsumer (org.apache.pulsar.broker.service.persistent.PersistentDispatcherSingleActiveConsumer)9 PulsarAdminException (org.apache.pulsar.client.admin.PulsarAdminException)9 IOException (java.io.IOException)7 WebApplicationException (javax.ws.rs.WebApplicationException)7 PulsarServerException (org.apache.pulsar.broker.PulsarServerException)7 NotAllowedException (org.apache.pulsar.broker.service.BrokerServiceException.NotAllowedException)7 SubscriptionBusyException (org.apache.pulsar.broker.service.BrokerServiceException.SubscriptionBusyException)7 TopicBusyException (org.apache.pulsar.broker.service.BrokerServiceException.TopicBusyException)7 RestException (org.apache.pulsar.broker.web.RestException)7 NotFoundException (org.apache.pulsar.client.admin.PulsarAdminException.NotFoundException)7 PreconditionFailedException (org.apache.pulsar.client.admin.PulsarAdminException.PreconditionFailedException)7 PartitionedTopicMetadata (org.apache.pulsar.common.partition.PartitionedTopicMetadata)7 KeeperException (org.apache.zookeeper.KeeperException)7 CountDownLatch (java.util.concurrent.CountDownLatch)6