Search in sources :

Example 6 with RetentionPolicies

use of com.yahoo.pulsar.common.policies.data.RetentionPolicies in project pulsar by yahoo.

the class Namespaces method setRetention.

@POST
@Path("/{property}/{cluster}/{namespace}/retention")
@ApiOperation(value = " Set retention configuration on a namespace.")
@ApiResponses(value = { @ApiResponse(code = 403, message = "Don't have admin permission"), @ApiResponse(code = 404, message = "Namespace does not exist"), @ApiResponse(code = 409, message = "Concurrent modification"), @ApiResponse(code = 412, message = "Retention Quota must exceed backlog quota") })
public void setRetention(@PathParam("property") String property, @PathParam("cluster") String cluster, @PathParam("namespace") String namespace, RetentionPolicies retention) {
    validatePoliciesReadOnlyAccess();
    try {
        Stat nodeStat = new Stat();
        final String path = path("policies", property, cluster, namespace);
        byte[] content = globalZk().getData(path, null, nodeStat);
        Policies policies = jsonMapper().readValue(content, Policies.class);
        if (!checkQuotas(policies, retention)) {
            log.warn("[{}] Failed to update retention configuration for namespace {}/{}/{}: conflicts with backlog quota", clientAppId(), property, cluster, namespace);
            throw new RestException(Status.PRECONDITION_FAILED, "Retention Quota must exceed configured backlog quota for namespace.");
        }
        policies.retention_policies = retention;
        globalZk().setData(path, jsonMapper().writeValueAsBytes(policies), nodeStat.getVersion());
        policiesCache().invalidate(path("policies", property, cluster, namespace));
        log.info("[{}] Successfully updated retention configuration: namespace={}/{}/{}, map={}", clientAppId(), property, cluster, namespace, jsonMapper().writeValueAsString(policies.retention_policies));
    } catch (KeeperException.NoNodeException e) {
        log.warn("[{}] Failed to update retention configuration for namespace {}/{}/{}: does not exist", clientAppId(), property, cluster, namespace);
        throw new RestException(Status.NOT_FOUND, "Namespace does not exist");
    } catch (KeeperException.BadVersionException e) {
        log.warn("[{}] Failed to update retention configuration for namespace {}/{}/{}: concurrent modification", clientAppId(), property, cluster, namespace);
        throw new RestException(Status.CONFLICT, "Concurrent modification");
    } catch (RestException pfe) {
        throw pfe;
    } catch (Exception e) {
        log.error("[{}] Failed to update retention configuration for namespace {}/{}/{}", clientAppId(), property, cluster, namespace, e);
        throw new RestException(e);
    }
}
Also used : Stat(org.apache.zookeeper.data.Stat) Policies(com.yahoo.pulsar.common.policies.data.Policies) PersistencePolicies(com.yahoo.pulsar.common.policies.data.PersistencePolicies) RetentionPolicies(com.yahoo.pulsar.common.policies.data.RetentionPolicies) NoNodeException(org.apache.zookeeper.KeeperException.NoNodeException) RestException(com.yahoo.pulsar.broker.web.RestException) KeeperException(org.apache.zookeeper.KeeperException) RestException(com.yahoo.pulsar.broker.web.RestException) WebApplicationException(javax.ws.rs.WebApplicationException) SubscriptionBusyException(com.yahoo.pulsar.broker.service.BrokerServiceException.SubscriptionBusyException) KeeperException(org.apache.zookeeper.KeeperException) PulsarAdminException(com.yahoo.pulsar.client.admin.PulsarAdminException) NoNodeException(org.apache.zookeeper.KeeperException.NoNodeException) PulsarServerException(com.yahoo.pulsar.broker.PulsarServerException) Path(javax.ws.rs.Path) POST(javax.ws.rs.POST) ApiOperation(io.swagger.annotations.ApiOperation) ApiResponses(io.swagger.annotations.ApiResponses)

Example 7 with RetentionPolicies

use of com.yahoo.pulsar.common.policies.data.RetentionPolicies in project pulsar by yahoo.

the class Namespaces method setBacklogQuota.

@POST
@Path("/{property}/{cluster}/{namespace}/backlogQuota")
@ApiOperation(value = " Set a backlog quota for all the destinations on a namespace.")
@ApiResponses(value = { @ApiResponse(code = 403, message = "Don't have admin permission"), @ApiResponse(code = 404, message = "Namespace does not exist"), @ApiResponse(code = 409, message = "Concurrent modification"), @ApiResponse(code = 412, message = "Specified backlog quota exceeds retention quota. Increase retention quota and retry request") })
public void setBacklogQuota(@PathParam("property") String property, @PathParam("cluster") String cluster, @PathParam("namespace") String namespace, @QueryParam("backlogQuotaType") BacklogQuotaType backlogQuotaType, BacklogQuota backlogQuota) {
    validateAdminAccessOnProperty(property);
    validatePoliciesReadOnlyAccess();
    if (backlogQuotaType == null) {
        backlogQuotaType = BacklogQuotaType.destination_storage;
    }
    try {
        Stat nodeStat = new Stat();
        final String path = path("policies", property, cluster, namespace);
        byte[] content = globalZk().getData(path, null, nodeStat);
        Policies policies = jsonMapper().readValue(content, Policies.class);
        RetentionPolicies r = policies.retention_policies;
        if (r != null) {
            Policies p = new Policies();
            p.backlog_quota_map.put(backlogQuotaType, backlogQuota);
            if (!checkQuotas(p, r)) {
                log.warn("[{}] Failed to update backlog configuration for namespace {}/{}/{}: conflicts with retention quota", clientAppId(), property, cluster, namespace);
                throw new RestException(Status.PRECONDITION_FAILED, "Backlog Quota exceeds configured retention quota for namespace. Please increase retention quota and retry");
            }
        }
        policies.backlog_quota_map.put(backlogQuotaType, backlogQuota);
        globalZk().setData(path, jsonMapper().writeValueAsBytes(policies), nodeStat.getVersion());
        policiesCache().invalidate(path("policies", property, cluster, namespace));
        log.info("[{}] Successfully updated backlog quota map: namespace={}/{}/{}, map={}", clientAppId(), property, cluster, namespace, jsonMapper().writeValueAsString(policies.backlog_quota_map));
    } catch (KeeperException.NoNodeException e) {
        log.warn("[{}] Failed to update backlog quota map for namespace {}/{}/{}: does not exist", clientAppId(), property, cluster, namespace);
        throw new RestException(Status.NOT_FOUND, "Namespace does not exist");
    } catch (KeeperException.BadVersionException e) {
        log.warn("[{}] Failed to update backlog quota map for namespace {}/{}/{}: concurrent modification", clientAppId(), property, cluster, namespace);
        throw new RestException(Status.CONFLICT, "Concurrent modification");
    } catch (RestException pfe) {
        throw pfe;
    } catch (Exception e) {
        log.error("[{}] Failed to update backlog quota map for namespace {}/{}/{}", clientAppId(), property, cluster, namespace, e);
        throw new RestException(e);
    }
}
Also used : RetentionPolicies(com.yahoo.pulsar.common.policies.data.RetentionPolicies) Stat(org.apache.zookeeper.data.Stat) Policies(com.yahoo.pulsar.common.policies.data.Policies) PersistencePolicies(com.yahoo.pulsar.common.policies.data.PersistencePolicies) RetentionPolicies(com.yahoo.pulsar.common.policies.data.RetentionPolicies) NoNodeException(org.apache.zookeeper.KeeperException.NoNodeException) RestException(com.yahoo.pulsar.broker.web.RestException) KeeperException(org.apache.zookeeper.KeeperException) RestException(com.yahoo.pulsar.broker.web.RestException) WebApplicationException(javax.ws.rs.WebApplicationException) SubscriptionBusyException(com.yahoo.pulsar.broker.service.BrokerServiceException.SubscriptionBusyException) KeeperException(org.apache.zookeeper.KeeperException) PulsarAdminException(com.yahoo.pulsar.client.admin.PulsarAdminException) NoNodeException(org.apache.zookeeper.KeeperException.NoNodeException) PulsarServerException(com.yahoo.pulsar.broker.PulsarServerException) Path(javax.ws.rs.Path) POST(javax.ws.rs.POST) ApiOperation(io.swagger.annotations.ApiOperation) ApiResponses(io.swagger.annotations.ApiResponses)

Example 8 with RetentionPolicies

use of com.yahoo.pulsar.common.policies.data.RetentionPolicies in project pulsar by yahoo.

the class BrokerClientIntegrationTest method testResetCursor.

@Test(timeOut = 10000, dataProvider = "subType")
public void testResetCursor(SubscriptionType subType) throws Exception {
    final RetentionPolicies policy = new RetentionPolicies(60, 52 * 1024);
    final DestinationName destName = DestinationName.get("persistent://my-property/use/my-ns/unacked-topic");
    final int warmup = 20;
    final int testSize = 150;
    final List<Message> received = new ArrayList<Message>();
    final ConsumerConfiguration consConfig = new ConsumerConfiguration();
    final String subsId = "sub";
    final NavigableMap<Long, TimestampEntryCount> publishTimeIdMap = new ConcurrentSkipListMap<>();
    consConfig.setSubscriptionType(subType);
    consConfig.setMessageListener((MessageListener) (Consumer consumer, Message msg) -> {
        try {
            synchronized (received) {
                received.add(msg);
            }
            consumer.acknowledge(msg);
            long publishTime = ((MessageImpl) msg).getPublishTime();
            log.info(" publish time is " + publishTime + "," + msg.getMessageId());
            TimestampEntryCount timestampEntryCount = publishTimeIdMap.computeIfAbsent(publishTime, (k) -> new TimestampEntryCount(publishTime));
            timestampEntryCount.incrementAndGet();
        } catch (final PulsarClientException e) {
            log.warn("Failed to ack!");
        }
    });
    admin.namespaces().setRetention(destName.getNamespace(), policy);
    Consumer consumer = pulsarClient.subscribe(destName.toString(), subsId, consConfig);
    final Producer producer = pulsarClient.createProducer(destName.toString());
    log.info("warm up started for " + destName.toString());
    // send warmup msgs
    byte[] msgBytes = new byte[1000];
    for (Integer i = 0; i < warmup; i++) {
        producer.send(msgBytes);
    }
    log.info("warm up finished.");
    // sleep to ensure receiving of msgs
    for (int n = 0; n < 10 && received.size() < warmup; n++) {
        Thread.sleep(100);
    }
    // validate received msgs
    Assert.assertEquals(received.size(), warmup);
    received.clear();
    // publish testSize num of msgs
    log.info("Sending more messages.");
    for (Integer n = 0; n < testSize; n++) {
        producer.send(msgBytes);
        Thread.sleep(1);
    }
    log.info("Sending more messages done.");
    Thread.sleep(3000);
    long begints = publishTimeIdMap.firstEntry().getKey();
    long endts = publishTimeIdMap.lastEntry().getKey();
    // find reset timestamp
    long timestamp = (endts - begints) / 2 + begints;
    timestamp = publishTimeIdMap.floorKey(timestamp);
    NavigableMap<Long, TimestampEntryCount> expectedMessages = new ConcurrentSkipListMap<>();
    expectedMessages.putAll(publishTimeIdMap.tailMap(timestamp, true));
    received.clear();
    log.info("reset cursor to " + timestamp + " for topic " + destName.toString() + " for subs " + subsId);
    log.info("issuing admin operation on " + admin.getServiceUrl().toString());
    List<String> subList = admin.persistentTopics().getSubscriptions(destName.toString());
    for (String subs : subList) {
        log.info("got sub " + subs);
    }
    publishTimeIdMap.clear();
    // reset the cursor to this timestamp
    Assert.assertTrue(subList.contains(subsId));
    admin.persistentTopics().resetCursor(destName.toString(), subsId, timestamp);
    consumer = pulsarClient.subscribe(destName.toString(), subsId, consConfig);
    Thread.sleep(3000);
    int totalExpected = 0;
    for (TimestampEntryCount tec : expectedMessages.values()) {
        totalExpected += tec.numMessages;
    }
    // validate that replay happens after the timestamp
    Assert.assertTrue(publishTimeIdMap.firstEntry().getKey() >= timestamp);
    consumer.close();
    producer.close();
    // validate that expected and received counts match
    int totalReceived = 0;
    for (TimestampEntryCount tec : publishTimeIdMap.values()) {
        totalReceived += tec.numMessages;
    }
    Assert.assertEquals(totalReceived, totalExpected, "did not receive all messages on replay after reset");
}
Also used : RetentionPolicies(com.yahoo.pulsar.common.policies.data.RetentionPolicies) Assert.assertNull(org.testng.Assert.assertNull) DataProvider(org.testng.annotations.DataProvider) Consumer(com.yahoo.pulsar.client.api.Consumer) LoggerFactory(org.slf4j.LoggerFactory) Test(org.testng.annotations.Test) Mockito.spy(org.mockito.Mockito.spy) AfterMethod(org.testng.annotations.AfterMethod) OwnershipCache(com.yahoo.pulsar.broker.namespace.OwnershipCache) SubscriptionType(com.yahoo.pulsar.client.api.SubscriptionType) ProducerConfiguration(com.yahoo.pulsar.client.api.ProducerConfiguration) ArrayList(java.util.ArrayList) State(com.yahoo.pulsar.client.impl.HandlerBase.State) Assert(org.testng.Assert) ProducerConsumerBase(com.yahoo.pulsar.client.api.ProducerConsumerBase) RetentionPolicies(com.yahoo.pulsar.common.policies.data.RetentionPolicies) Matchers.anyObject(org.mockito.Matchers.anyObject) Mockito.doAnswer(org.mockito.Mockito.doAnswer) MessageListener(com.yahoo.pulsar.client.api.MessageListener) URI(java.net.URI) PulsarClient(com.yahoo.pulsar.client.api.PulsarClient) Assert.assertFalse(org.testng.Assert.assertFalse) ExecutorService(java.util.concurrent.ExecutorService) DestinationName(com.yahoo.pulsar.common.naming.DestinationName) NamespaceBundle(com.yahoo.pulsar.common.naming.NamespaceBundle) Logger(org.slf4j.Logger) Producer(com.yahoo.pulsar.client.api.Producer) Assert.fail(org.testng.Assert.fail) Mockito.atLeastOnce(org.mockito.Mockito.atLeastOnce) BeforeMethod(org.testng.annotations.BeforeMethod) ConsumerConfiguration(com.yahoo.pulsar.client.api.ConsumerConfiguration) Set(java.util.Set) PulsarHandler(com.yahoo.pulsar.common.api.PulsarHandler) Field(java.lang.reflect.Field) NavigableMap(java.util.NavigableMap) Executors(java.util.concurrent.Executors) Sets(com.google.common.collect.Sets) Mockito.verify(org.mockito.Mockito.verify) TimeUnit(java.util.concurrent.TimeUnit) Topic(com.yahoo.pulsar.broker.service.Topic) Mockito.never(org.mockito.Mockito.never) List(java.util.List) ConcurrentSkipListMap(java.util.concurrent.ConcurrentSkipListMap) ClientConfiguration(com.yahoo.pulsar.client.api.ClientConfiguration) ConcurrentLongHashMap(com.yahoo.pulsar.common.util.collections.ConcurrentLongHashMap) Assert.assertTrue(org.testng.Assert.assertTrue) PulsarClientException(com.yahoo.pulsar.client.api.PulsarClientException) Message(com.yahoo.pulsar.client.api.Message) ConcurrentSkipListMap(java.util.concurrent.ConcurrentSkipListMap) Message(com.yahoo.pulsar.client.api.Message) ArrayList(java.util.ArrayList) Consumer(com.yahoo.pulsar.client.api.Consumer) Producer(com.yahoo.pulsar.client.api.Producer) DestinationName(com.yahoo.pulsar.common.naming.DestinationName) ConsumerConfiguration(com.yahoo.pulsar.client.api.ConsumerConfiguration) PulsarClientException(com.yahoo.pulsar.client.api.PulsarClientException) Test(org.testng.annotations.Test)

Example 9 with RetentionPolicies

use of com.yahoo.pulsar.common.policies.data.RetentionPolicies in project pulsar by yahoo.

the class AdminApiTest method persistentTopicsInvalidCursorReset.

@Test
public void persistentTopicsInvalidCursorReset() throws Exception {
    admin.namespaces().setRetention("prop-xyz/use/ns1", new RetentionPolicies(10, 10));
    assertEquals(admin.persistentTopics().getList("prop-xyz/use/ns1"), Lists.newArrayList());
    String topicName = "persistent://prop-xyz/use/ns1/invalidcursorreset";
    // Force to create a destination
    publishMessagesOnPersistentTopic(topicName, 0);
    assertEquals(admin.persistentTopics().getList("prop-xyz/use/ns1"), Lists.newArrayList(topicName));
    // create consumer and subscription
    URL pulsarUrl = new URL("http://127.0.0.1" + ":" + BROKER_WEBSERVICE_PORT);
    ClientConfiguration clientConf = new ClientConfiguration();
    clientConf.setStatsInterval(0, TimeUnit.SECONDS);
    PulsarClient client = PulsarClient.create(pulsarUrl.toString(), clientConf);
    ConsumerConfiguration conf = new ConsumerConfiguration();
    conf.setSubscriptionType(SubscriptionType.Exclusive);
    Consumer consumer = client.subscribe(topicName, "my-sub", conf);
    assertEquals(admin.persistentTopics().getSubscriptions(topicName), Lists.newArrayList("my-sub"));
    publishMessagesOnPersistentTopic(topicName, 10);
    List<Message> messages = admin.persistentTopics().peekMessages(topicName, "my-sub", 10);
    assertEquals(messages.size(), 10);
    for (int i = 0; i < 10; i++) {
        Message message = consumer.receive();
        consumer.acknowledge(message);
    }
    // use invalid timestamp
    try {
        admin.persistentTopics().resetCursor(topicName, "my-sub", System.currentTimeMillis() - 190000);
    } catch (Exception e) {
        // fail the test
        throw e;
    }
    admin.persistentTopics().resetCursor(topicName, "my-sub", System.currentTimeMillis() + 90000);
    consumer = client.subscribe(topicName, "my-sub", conf);
    consumer.close();
    client.close();
    admin.persistentTopics().deleteSubscription(topicName, "my-sub");
    assertEquals(admin.persistentTopics().getSubscriptions(topicName), Lists.newArrayList());
    admin.persistentTopics().delete(topicName);
}
Also used : RetentionPolicies(com.yahoo.pulsar.common.policies.data.RetentionPolicies) Consumer(com.yahoo.pulsar.client.api.Consumer) Message(com.yahoo.pulsar.client.api.Message) ConsumerConfiguration(com.yahoo.pulsar.client.api.ConsumerConfiguration) PulsarClient(com.yahoo.pulsar.client.api.PulsarClient) URL(java.net.URL) ClientConfiguration(com.yahoo.pulsar.client.api.ClientConfiguration) NotAuthorizedException(com.yahoo.pulsar.client.admin.PulsarAdminException.NotAuthorizedException) PreconditionFailedException(com.yahoo.pulsar.client.admin.PulsarAdminException.PreconditionFailedException) NotFoundException(com.yahoo.pulsar.client.admin.PulsarAdminException.NotFoundException) PulsarAdminException(com.yahoo.pulsar.client.admin.PulsarAdminException) ConflictException(com.yahoo.pulsar.client.admin.PulsarAdminException.ConflictException) PulsarServerException(com.yahoo.pulsar.broker.PulsarServerException) Test(org.testng.annotations.Test) MockedPulsarServiceBaseTest(com.yahoo.pulsar.broker.auth.MockedPulsarServiceBaseTest)

Example 10 with RetentionPolicies

use of com.yahoo.pulsar.common.policies.data.RetentionPolicies in project pulsar by yahoo.

the class AdminApiTest method persistentTopicsCursorReset.

@Test(dataProvider = "topicName")
public void persistentTopicsCursorReset(String topicName) throws Exception {
    admin.namespaces().setRetention("prop-xyz/use/ns1", new RetentionPolicies(10, 10));
    assertEquals(admin.persistentTopics().getList("prop-xyz/use/ns1"), Lists.newArrayList());
    topicName = "persistent://prop-xyz/use/ns1/" + topicName;
    // create consumer and subscription
    ConsumerConfiguration conf = new ConsumerConfiguration();
    conf.setSubscriptionType(SubscriptionType.Exclusive);
    Consumer consumer = pulsarClient.subscribe(topicName, "my-sub", conf);
    assertEquals(admin.persistentTopics().getSubscriptions(topicName), Lists.newArrayList("my-sub"));
    publishMessagesOnPersistentTopic(topicName, 5, 0);
    // Allow at least 1ms for messages to have different timestamps
    Thread.sleep(1);
    long messageTimestamp = System.currentTimeMillis();
    publishMessagesOnPersistentTopic(topicName, 5, 5);
    List<Message> messages = admin.persistentTopics().peekMessages(topicName, "my-sub", 10);
    assertEquals(messages.size(), 10);
    for (int i = 0; i < 10; i++) {
        Message message = consumer.receive();
        consumer.acknowledge(message);
    }
    // messages should still be available due to retention
    admin.persistentTopics().resetCursor(topicName, "my-sub", messageTimestamp);
    int receivedAfterReset = 0;
    for (int i = 4; i < 10; i++) {
        Message message = consumer.receive();
        consumer.acknowledge(message);
        ++receivedAfterReset;
        String expected = "message-" + i;
        assertEquals(message.getData(), expected.getBytes());
    }
    assertEquals(receivedAfterReset, 6);
    consumer.close();
    admin.persistentTopics().deleteSubscription(topicName, "my-sub");
    assertEquals(admin.persistentTopics().getSubscriptions(topicName), Lists.newArrayList());
    admin.persistentTopics().delete(topicName);
}
Also used : RetentionPolicies(com.yahoo.pulsar.common.policies.data.RetentionPolicies) Consumer(com.yahoo.pulsar.client.api.Consumer) Message(com.yahoo.pulsar.client.api.Message) ConsumerConfiguration(com.yahoo.pulsar.client.api.ConsumerConfiguration) Test(org.testng.annotations.Test) MockedPulsarServiceBaseTest(com.yahoo.pulsar.broker.auth.MockedPulsarServiceBaseTest)

Aggregations

RetentionPolicies (com.yahoo.pulsar.common.policies.data.RetentionPolicies)11 Test (org.testng.annotations.Test)7 MockedPulsarServiceBaseTest (com.yahoo.pulsar.broker.auth.MockedPulsarServiceBaseTest)5 Consumer (com.yahoo.pulsar.client.api.Consumer)5 ConsumerConfiguration (com.yahoo.pulsar.client.api.ConsumerConfiguration)5 Message (com.yahoo.pulsar.client.api.Message)5 PersistencePolicies (com.yahoo.pulsar.common.policies.data.PersistencePolicies)5 Policies (com.yahoo.pulsar.common.policies.data.Policies)4 PulsarServerException (com.yahoo.pulsar.broker.PulsarServerException)3 RestException (com.yahoo.pulsar.broker.web.RestException)3 PulsarAdminException (com.yahoo.pulsar.client.admin.PulsarAdminException)3 ClientConfiguration (com.yahoo.pulsar.client.api.ClientConfiguration)3 PulsarClient (com.yahoo.pulsar.client.api.PulsarClient)3 NamespaceBundle (com.yahoo.pulsar.common.naming.NamespaceBundle)3 ApiOperation (io.swagger.annotations.ApiOperation)3 ApiResponses (io.swagger.annotations.ApiResponses)3 Field (java.lang.reflect.Field)3 Path (javax.ws.rs.Path)3 KeeperException (org.apache.zookeeper.KeeperException)3 Stat (org.apache.zookeeper.data.Stat)3