|
24 | 24 | import static org.mockito.Mockito.times;
|
25 | 25 | import static org.mockito.Mockito.verify;
|
26 | 26 | import static org.testng.Assert.assertFalse;
|
| 27 | +import static org.testng.Assert.assertNull; |
27 | 28 | import static org.testng.Assert.assertEquals;
|
28 | 29 | import static org.testng.Assert.assertTrue;
|
29 | 30 |
|
30 | 31 | import com.google.common.collect.Lists;
|
| 32 | +import com.google.common.collect.Range; |
| 33 | + |
31 | 34 | import java.util.ArrayList;
|
32 | 35 | import java.util.Collections;
|
33 | 36 | import java.util.HashMap;
|
|
42 | 45 | import java.util.stream.Collectors;
|
43 | 46 | import java.util.stream.IntStream;
|
44 | 47 | import lombok.Cleanup;
|
| 48 | + |
| 49 | +import org.apache.bookkeeper.mledger.impl.PositionImpl; |
| 50 | +import org.apache.pulsar.broker.service.persistent.PersistentTopic; |
45 | 51 | import org.apache.pulsar.client.admin.PulsarAdminException;
|
46 | 52 | import org.apache.pulsar.client.impl.ClientBuilderImpl;
|
47 | 53 | import org.apache.pulsar.client.impl.ConsumerImpl;
|
@@ -351,4 +357,66 @@ public int choosePartition(Message<?> msg, TopicMetadata metadata) {
|
351 | 357 | }
|
352 | 358 | consumer.close();
|
353 | 359 | }
|
| 360 | + |
| 361 | + /** |
| 362 | + * It tests acking of messageId created from byte[] and validates client acks messages successfully. |
| 363 | + * @throws Exception |
| 364 | + */ |
| 365 | + @Test |
| 366 | + public void testMultiTopicAckWithByteMessageId() throws Exception { |
| 367 | + String topicName = newTopicName(); |
| 368 | + int numPartitions = 2; |
| 369 | + int numMessages = 100000; |
| 370 | + admin.topics().createPartitionedTopic(topicName, numPartitions); |
| 371 | + |
| 372 | + Producer<Long>[] producers = new Producer[numPartitions]; |
| 373 | + |
| 374 | + for (int i = 0; i < numPartitions; i++) { |
| 375 | + producers[i] = pulsarClient.newProducer(Schema.INT64) |
| 376 | + // produce to each partition directly so that order can be maintained in sending |
| 377 | + .topic(topicName + "-partition-" + i).enableBatching(true).maxPendingMessages(30000) |
| 378 | + .maxPendingMessagesAcrossPartitions(60000).batchingMaxMessages(10000) |
| 379 | + .batchingMaxPublishDelay(5, TimeUnit.SECONDS).batchingMaxBytes(4 * 1024 * 1024) |
| 380 | + .blockIfQueueFull(true).create(); |
| 381 | + } |
| 382 | + |
| 383 | + @Cleanup |
| 384 | + Consumer<Long> consumer = pulsarClient.newConsumer(Schema.INT64) |
| 385 | + // consume on the partitioned topic |
| 386 | + .topic(topicName).subscriptionInitialPosition(SubscriptionInitialPosition.Earliest) |
| 387 | + .receiverQueueSize(numMessages).subscriptionName(methodName).subscribe(); |
| 388 | + |
| 389 | + // produce sequence numbers to each partition topic |
| 390 | + long sequenceNumber = 1L; |
| 391 | + for (int i = 0; i < numMessages; i++) { |
| 392 | + for (Producer<Long> producer : producers) { |
| 393 | + producer.newMessage().value(sequenceNumber).sendAsync(); |
| 394 | + } |
| 395 | + sequenceNumber++; |
| 396 | + } |
| 397 | + for (Producer<Long> producer : producers) { |
| 398 | + producer.flush(); |
| 399 | + producer.close(); |
| 400 | + } |
| 401 | + |
| 402 | + // receive and validate sequences in the partitioned topic |
| 403 | + Map<String, AtomicLong> receivedSequences = new HashMap<>(); |
| 404 | + int receivedCount = 0; |
| 405 | + while (receivedCount < numPartitions * numMessages) { |
| 406 | + Message<Long> message = consumer.receiveAsync().get(5, TimeUnit.SECONDS); |
| 407 | + byte[] idByte = message.getMessageId().toByteArray(); |
| 408 | + MessageId id = MessageId.fromByteArray(idByte); |
| 409 | + consumer.acknowledge(id); |
| 410 | + receivedCount++; |
| 411 | + AtomicLong receivedSequenceCounter = receivedSequences.computeIfAbsent(message.getTopicName(), |
| 412 | + k -> new AtomicLong(1L)); |
| 413 | + Assert.assertEquals(message.getValue().longValue(), receivedSequenceCounter.getAndIncrement()); |
| 414 | + } |
| 415 | + Assert.assertEquals(numPartitions * numMessages, receivedCount); |
| 416 | + consumer.close(); |
| 417 | + |
| 418 | + PersistentTopic topic = (PersistentTopic) pulsar.getBrokerService().getTopic(topicName + "-partition-0", false).get().get(); |
| 419 | + Range<PositionImpl> range = topic.getManagedLedger().getCursors().iterator().next().getLastIndividualDeletedRange(); |
| 420 | + assertNull(range); |
| 421 | + } |
354 | 422 | }
|
0 commit comments