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);
}
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);
}
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
}
}
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);
}
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);
}
Aggregations