Search in sources :

Example 1 with EntryCacheImpl

use of org.apache.bookkeeper.mledger.impl.EntryCacheImpl in project pulsar by yahoo.

the class PersistentTopicE2ETest method testActiveSubscriptionWithCache.

/**
     * Validation: 1. validates active-cursor after active subscription 2. validate active-cursor with subscription 3.
     * unconsumed messages should be present into cache 4. cache and active-cursor should be empty once subscription is
     * closed
     *
     * @throws Exception
     */
@Test
public void testActiveSubscriptionWithCache() throws Exception {
    final String topicName = "persistent://prop/use/ns-abc/topic2";
    final String subName = "sub2";
    Message msg;
    int recvQueueSize = 4;
    ConsumerConfiguration conf = new ConsumerConfiguration();
    conf.setSubscriptionType(SubscriptionType.Exclusive);
    conf.setReceiverQueueSize(recvQueueSize);
    // (1) Create subscription
    Consumer consumer = pulsarClient.subscribe(topicName, subName, conf);
    Producer producer = pulsarClient.createProducer(topicName);
    // (2) Produce Messages
    for (int i = 0; i < recvQueueSize / 2; i++) {
        String message = "my-message-" + i;
        producer.send(message.getBytes());
        msg = consumer.receive();
        consumer.acknowledge(msg);
    }
    PersistentTopic topicRef = (PersistentTopic) pulsar.getBrokerService().getTopicReference(topicName);
    // (3) Get Entry cache
    ManagedLedgerImpl ledger = (ManagedLedgerImpl) topicRef.getManagedLedger();
    Field cacheField = ManagedLedgerImpl.class.getDeclaredField("entryCache");
    cacheField.setAccessible(true);
    EntryCacheImpl entryCache = (EntryCacheImpl) cacheField.get(ledger);
    /************* Validation on non-empty active-cursor **************/
    // (4) Get ActiveCursor : which is list of active subscription
    Iterable<ManagedCursor> activeCursors = ledger.getActiveCursors();
    ManagedCursor curosr = activeCursors.iterator().next();
    // (4.1) Validate: active Cursor must be non-empty
    assertNotNull(curosr);
    // (4.2) Validate: validate cursor name
    assertEquals(subName, curosr.getName());
    // (4.3) Validate: entryCache should have cached messages
    assertTrue(entryCache.getSize() != 0);
    /************* Validation on empty active-cursor **************/
    // (5) Close consumer: which (1)removes activeConsumer and (2)clears the entry-cache
    consumer.close();
    Thread.sleep(1000);
    // (5.1) Validate: active-consumer must be empty
    assertFalse(ledger.getActiveCursors().iterator().hasNext());
    // (5.2) Validate: Entry-cache must be cleared
    assertTrue(entryCache.getSize() == 0);
}
Also used : ManagedLedgerImpl(org.apache.bookkeeper.mledger.impl.ManagedLedgerImpl) Field(java.lang.reflect.Field) Message(com.yahoo.pulsar.client.api.Message) Consumer(com.yahoo.pulsar.client.api.Consumer) Producer(com.yahoo.pulsar.client.api.Producer) PersistentTopic(com.yahoo.pulsar.broker.service.persistent.PersistentTopic) ConsumerConfiguration(com.yahoo.pulsar.client.api.ConsumerConfiguration) EntryCacheImpl(org.apache.bookkeeper.mledger.impl.EntryCacheImpl) ManagedCursor(org.apache.bookkeeper.mledger.ManagedCursor) Test(org.testng.annotations.Test)

Example 2 with EntryCacheImpl

use of org.apache.bookkeeper.mledger.impl.EntryCacheImpl in project pulsar by yahoo.

the class SimpleProducerConsumerTest method testActiveAndInActiveConsumerEntryCacheBehavior.

/**
     * Usecase 1: Only 1 Active Subscription - 1 subscriber - Produce Messages - EntryCache should cache messages -
     * EntryCache should be cleaned : Once active subscription consumes messages
     *
     * Usecase 2: 2 Active Subscriptions (faster and slower) and slower gets closed - 2 subscribers - Produce Messages -
     * 1 faster-subscriber consumes all messages and another slower-subscriber none - EntryCache should have cached
     * messages as slower-subscriber has not consumed messages yet - close slower-subscriber - EntryCache should be
     * cleared
     *
     * @throws Exception
     */
@Test
public void testActiveAndInActiveConsumerEntryCacheBehavior() throws Exception {
    log.info("-- Starting {} test --", methodName);
    final long batchMessageDelayMs = 100;
    final int receiverSize = 10;
    final String topicName = "cache-topic";
    final String sub1 = "faster-sub1";
    final String sub2 = "slower-sub2";
    ConsumerConfiguration conf = new ConsumerConfiguration();
    conf.setSubscriptionType(SubscriptionType.Shared);
    conf.setReceiverQueueSize(receiverSize);
    ProducerConfiguration producerConf = new ProducerConfiguration();
    if (batchMessageDelayMs != 0) {
        producerConf.setBatchingEnabled(true);
        producerConf.setBatchingMaxPublishDelay(batchMessageDelayMs, TimeUnit.MILLISECONDS);
        producerConf.setBatchingMaxMessages(5);
    }
    /************ usecase-1: *************/
    // 1. Subscriber Faster subscriber
    Consumer subscriber1 = pulsarClient.subscribe("persistent://my-property/use/my-ns/" + topicName, sub1, conf);
    final String topic = "persistent://my-property/use/my-ns/" + topicName;
    Producer producer = pulsarClient.createProducer(topic, producerConf);
    PersistentTopic topicRef = (PersistentTopic) pulsar.getBrokerService().getTopicReference(topic);
    ManagedLedgerImpl ledger = (ManagedLedgerImpl) topicRef.getManagedLedger();
    Field cacheField = ManagedLedgerImpl.class.getDeclaredField("entryCache");
    cacheField.setAccessible(true);
    Field modifiersField = Field.class.getDeclaredField("modifiers");
    modifiersField.setAccessible(true);
    modifiersField.setInt(cacheField, cacheField.getModifiers() & ~Modifier.FINAL);
    EntryCacheImpl entryCache = spy((EntryCacheImpl) cacheField.get(ledger));
    cacheField.set(ledger, entryCache);
    Message msg = null;
    // 2. Produce messages
    for (int i = 0; i < 30; i++) {
        String message = "my-message-" + i;
        producer.send(message.getBytes());
    }
    // 3. Consume messages
    for (int i = 0; i < 30; i++) {
        msg = subscriber1.receive(5, TimeUnit.SECONDS);
        subscriber1.acknowledge(msg);
    }
    // Verify: EntryCache has been invalidated
    verify(entryCache, atLeastOnce()).invalidateEntries(any());
    // sleep for a second: as ledger.updateCursorRateLimit RateLimiter will allow to invoke cursor-update after a
    // second
    //
    Thread.sleep(1000);
    // produce-consume one more message to trigger : ledger.internalReadFromLedger(..) which updates cursor and
    // EntryCache
    producer.send("message".getBytes());
    msg = subscriber1.receive(5, TimeUnit.SECONDS);
    // Verify: cache has to be cleared as there is no message needs to be consumed by active subscriber
    assertTrue(entryCache.getSize() == 0);
    /************ usecase-2: *************/
    // 1.b Subscriber slower-subscriber
    Consumer subscriber2 = pulsarClient.subscribe("persistent://my-property/use/my-ns/" + topicName, sub2, conf);
    // Produce messages
    final int moreMessages = 10;
    for (int i = 0; i < receiverSize + moreMessages; i++) {
        String message = "my-message-" + i;
        producer.send(message.getBytes());
    }
    // Consume messages
    for (int i = 0; i < receiverSize + moreMessages; i++) {
        msg = subscriber1.receive(5, TimeUnit.SECONDS);
        subscriber1.acknowledge(msg);
    }
    // sleep for a second: as ledger.updateCursorRateLimit RateLimiter will allow to invoke cursor-update after a
    // second
    //
    Thread.sleep(1000);
    // produce-consume one more message to trigger : ledger.internalReadFromLedger(..) which updates cursor and
    // EntryCache
    producer.send("message".getBytes());
    msg = subscriber1.receive(5, TimeUnit.SECONDS);
    // Verify: as active-subscriber2 has not consumed messages: EntryCache must have those entries in cache
    assertTrue(entryCache.getSize() != 0);
    // 3.b Close subscriber2: which will trigger cache to clear the cache
    subscriber2.close();
    // Verify: EntryCache should be cleared
    assertTrue(entryCache.getSize() == 0);
    subscriber1.close();
    log.info("-- Exiting {} test --", methodName);
}
Also used : ManagedLedgerImpl(org.apache.bookkeeper.mledger.impl.ManagedLedgerImpl) Field(java.lang.reflect.Field) PersistentTopic(com.yahoo.pulsar.broker.service.persistent.PersistentTopic) EntryCacheImpl(org.apache.bookkeeper.mledger.impl.EntryCacheImpl) Test(org.testng.annotations.Test)

Aggregations

PersistentTopic (com.yahoo.pulsar.broker.service.persistent.PersistentTopic)2 Field (java.lang.reflect.Field)2 EntryCacheImpl (org.apache.bookkeeper.mledger.impl.EntryCacheImpl)2 ManagedLedgerImpl (org.apache.bookkeeper.mledger.impl.ManagedLedgerImpl)2 Test (org.testng.annotations.Test)2 Consumer (com.yahoo.pulsar.client.api.Consumer)1 ConsumerConfiguration (com.yahoo.pulsar.client.api.ConsumerConfiguration)1 Message (com.yahoo.pulsar.client.api.Message)1 Producer (com.yahoo.pulsar.client.api.Producer)1 ManagedCursor (org.apache.bookkeeper.mledger.ManagedCursor)1