Search in sources :

Example 1 with TopicNotFoundException

use of co.cask.cdap.api.messaging.TopicNotFoundException in project cdap by caskdata.

the class LevelDBMetadataTable method getMetadata.

@Override
public TopicMetadata getMetadata(TopicId topicId) throws IOException, TopicNotFoundException {
    try {
        byte[] value = levelDB.get(MessagingUtils.toMetadataRowKey(topicId));
        if (value == null) {
            throw new TopicNotFoundException(topicId.getNamespace(), topicId.getTopic());
        }
        Map<String, String> properties = GSON.fromJson(Bytes.toString(value), MAP_TYPE);
        TopicMetadata topicMetadata = new TopicMetadata(topicId, properties);
        if (!topicMetadata.exists()) {
            throw new TopicNotFoundException(topicId.getNamespace(), topicId.getTopic());
        }
        return topicMetadata;
    } catch (DBException e) {
        // DBException is a RuntimeException. Turn it to IOException so that it forces caller to handle it.
        throw new IOException(e);
    }
}
Also used : DBException(org.iq80.leveldb.DBException) TopicNotFoundException(co.cask.cdap.api.messaging.TopicNotFoundException) IOException(java.io.IOException) TopicMetadata(co.cask.cdap.messaging.TopicMetadata)

Example 2 with TopicNotFoundException

use of co.cask.cdap.api.messaging.TopicNotFoundException in project cdap by caskdata.

the class LevelDBMetadataTable method updateTopic.

@Override
public void updateTopic(TopicMetadata topicMetadata) throws TopicNotFoundException, IOException {
    try {
        TopicId topicId = topicMetadata.getTopicId();
        byte[] key = MessagingUtils.toMetadataRowKey(topicId);
        synchronized (this) {
            byte[] tableValue = levelDB.get(key);
            if (tableValue == null) {
                throw new TopicNotFoundException(topicId.getNamespace(), topicId.getTopic());
            }
            Map<String, String> oldProperties = GSON.fromJson(Bytes.toString(tableValue), MAP_TYPE);
            TopicMetadata oldMetadata = new TopicMetadata(topicId, oldProperties);
            if (!oldMetadata.exists()) {
                throw new TopicNotFoundException(topicId.getNamespace(), topicId.getTopic());
            }
            TreeMap<String, String> newProperties = new TreeMap<>(topicMetadata.getProperties());
            newProperties.put(TopicMetadata.GENERATION_KEY, Integer.toString(oldMetadata.getGeneration()));
            levelDB.put(key, Bytes.toBytes(GSON.toJson(newProperties, MAP_TYPE)), WRITE_OPTIONS);
        }
    } catch (DBException e) {
        throw new IOException(e);
    }
}
Also used : DBException(org.iq80.leveldb.DBException) TopicNotFoundException(co.cask.cdap.api.messaging.TopicNotFoundException) TopicId(co.cask.cdap.proto.id.TopicId) IOException(java.io.IOException) TreeMap(java.util.TreeMap) TopicMetadata(co.cask.cdap.messaging.TopicMetadata)

Example 3 with TopicNotFoundException

use of co.cask.cdap.api.messaging.TopicNotFoundException in project cdap by caskdata.

the class MessagingHttpServiceTest method testBasicPubSub.

@Test
public void testBasicPubSub() throws Exception {
    TopicId topicId = new NamespaceId("ns1").topic("testBasicPubSub");
    // Publish to a non-existing topic should get not found exception
    try {
        client.publish(StoreRequestBuilder.of(topicId).addPayloads("a").build());
        Assert.fail("Expected TopicNotFoundException");
    } catch (TopicNotFoundException e) {
    // Expected
    }
    // Consume from a non-existing topic should get not found exception
    try {
        client.prepareFetch(topicId).fetch();
        Assert.fail("Expected TopicNotFoundException");
    } catch (TopicNotFoundException e) {
    // Expected
    }
    client.createTopic(new TopicMetadata(topicId));
    // Publish a non-transactional message with empty payload should result in failure
    try {
        client.publish(StoreRequestBuilder.of(topicId).build());
        Assert.fail("Expected IllegalArgumentException");
    } catch (IllegalArgumentException e) {
    // Expected
    }
    // Publish a non-tx message, no RollbackDetail is returned
    Assert.assertNull(client.publish(StoreRequestBuilder.of(topicId).addPayloads("m0", "m1").build()));
    // Publish a transactional message, a RollbackDetail should be returned
    RollbackDetail rollbackDetail = client.publish(StoreRequestBuilder.of(topicId).addPayloads("m2").setTransaction(1L).build());
    Assert.assertNotNull(rollbackDetail);
    // Rollback the published message
    client.rollback(topicId, rollbackDetail);
    // Fetch messages non-transactionally (should be able to read all the messages since rolled back messages
    // are still visible until ttl kicks in)
    List<RawMessage> messages = new ArrayList<>();
    try (CloseableIterator<RawMessage> iterator = client.prepareFetch(topicId).fetch()) {
        Iterators.addAll(messages, iterator);
    }
    Assert.assertEquals(3, messages.size());
    for (int i = 0; i < 3; i++) {
        Assert.assertEquals("m" + i, Bytes.toString(messages.get(i).getPayload()));
    }
    // Consume transactionally. It should get only m0 and m1 since m2 has been rolled back
    List<RawMessage> txMessages = new ArrayList<>();
    Transaction transaction = new Transaction(3L, 3L, new long[0], new long[] { 2L }, 2L);
    try (CloseableIterator<RawMessage> iterator = client.prepareFetch(topicId).setStartTime(0).setTransaction(transaction).fetch()) {
        Iterators.addAll(txMessages, iterator);
    }
    Assert.assertEquals(2, txMessages.size());
    for (int i = 0; i < 2; i++) {
        Assert.assertEquals("m" + i, Bytes.toString(messages.get(i).getPayload()));
    }
    // Fetch again from a given message offset exclusively.
    // Expects one message to be fetched
    byte[] startMessageId = messages.get(1).getId();
    try (CloseableIterator<RawMessage> iterator = client.prepareFetch(topicId).setStartMessage(startMessageId, false).fetch()) {
        // It should have only one message (m2)
        Assert.assertTrue(iterator.hasNext());
        RawMessage msg = iterator.next();
        Assert.assertEquals("m2", Bytes.toString(msg.getPayload()));
    }
    // Fetch again from the last message offset exclusively
    // Expects no message to be fetched
    startMessageId = messages.get(2).getId();
    try (CloseableIterator<RawMessage> iterator = client.prepareFetch(topicId).setStartMessage(startMessageId, false).fetch()) {
        Assert.assertFalse(iterator.hasNext());
    }
    // Fetch with start time. It should get both m0 and m1 since they are published in the same request, hence
    // having the same publish time
    startMessageId = messages.get(1).getId();
    try (CloseableIterator<RawMessage> iterator = client.prepareFetch(topicId).setStartTime(new MessageId(startMessageId).getPublishTimestamp()).setLimit(2).fetch()) {
        messages.clear();
        Iterators.addAll(messages, iterator);
    }
    Assert.assertEquals(2, messages.size());
    for (int i = 0; i < 2; i++) {
        Assert.assertEquals("m" + i, Bytes.toString(messages.get(i).getPayload()));
    }
    // Publish 2 messages, one transactionally, one without transaction
    client.publish(StoreRequestBuilder.of(topicId).addPayloads("m3").setTransaction(2L).build());
    client.publish(StoreRequestBuilder.of(topicId).addPayloads("m4").build());
    // Consume without transactional, it should see m2, m3 and m4
    startMessageId = messages.get(1).getId();
    try (CloseableIterator<RawMessage> iterator = client.prepareFetch(topicId).setStartMessage(startMessageId, false).fetch()) {
        messages.clear();
        Iterators.addAll(messages, iterator);
    }
    Assert.assertEquals(3, messages.size());
    for (int i = 0; i < 3; i++) {
        Assert.assertEquals("m" + (i + 2), Bytes.toString(messages.get(i).getPayload()));
    }
    // Consume using a transaction that doesn't have tx = 2L visible. It should get no message as it should block on m3
    transaction = new Transaction(3L, 3L, new long[0], new long[] { 2L }, 2L);
    try (CloseableIterator<RawMessage> iterator = client.prepareFetch(topicId).setStartMessage(startMessageId, false).setTransaction(transaction).fetch()) {
        Assert.assertFalse(iterator.hasNext());
    }
    // Consume using a transaction that has tx = 2L in the invalid list. It should skip m3 and got m4
    transaction = new Transaction(3L, 3L, new long[] { 2L }, new long[0], 0L);
    try (CloseableIterator<RawMessage> iterator = client.prepareFetch(topicId).setStartMessage(startMessageId, false).setTransaction(transaction).fetch()) {
        messages.clear();
        Iterators.addAll(messages, iterator);
    }
    Assert.assertEquals(1, messages.size());
    Assert.assertEquals("m4", Bytes.toString(messages.get(0).getPayload()));
    // Consume using a transaction that has tx = 2L committed. It should get m3 and m4
    transaction = new Transaction(3L, 3L, new long[0], new long[0], 0L);
    try (CloseableIterator<RawMessage> iterator = client.prepareFetch(topicId).setStartMessage(startMessageId, false).setTransaction(transaction).fetch()) {
        messages.clear();
        Iterators.addAll(messages, iterator);
    }
    Assert.assertEquals(2, messages.size());
    for (int i = 0; i < 2; i++) {
        Assert.assertEquals("m" + (i + 3), Bytes.toString(messages.get(i).getPayload()));
    }
    client.deleteTopic(topicId);
}
Also used : RollbackDetail(co.cask.cdap.messaging.RollbackDetail) TopicNotFoundException(co.cask.cdap.api.messaging.TopicNotFoundException) ArrayList(java.util.ArrayList) TopicMetadata(co.cask.cdap.messaging.TopicMetadata) Transaction(org.apache.tephra.Transaction) TopicId(co.cask.cdap.proto.id.TopicId) NamespaceId(co.cask.cdap.proto.id.NamespaceId) RawMessage(co.cask.cdap.messaging.data.RawMessage) MessageId(co.cask.cdap.messaging.data.MessageId) Test(org.junit.Test)

Example 4 with TopicNotFoundException

use of co.cask.cdap.api.messaging.TopicNotFoundException in project cdap by caskdata.

the class MessagingHttpServiceTest method testMetadataEndpoints.

@Test
public void testMetadataEndpoints() throws Exception {
    NamespaceId nsId = new NamespaceId("metadata");
    TopicId topic1 = nsId.topic("t1");
    TopicId topic2 = nsId.topic("t2");
    // Get a non exist topic should fail
    try {
        client.getTopic(topic1);
        Assert.fail("Expected TopicNotFoundException");
    } catch (TopicNotFoundException e) {
    // Expected
    }
    // Create the topic t1
    client.createTopic(new TopicMetadata(topic1));
    // Create an existing topic should fail
    try {
        client.createTopic(new TopicMetadata(topic1));
        Assert.fail("Expect TopicAlreadyExistsException");
    } catch (TopicAlreadyExistsException e) {
    // Expected
    }
    // Get the topic properties. Verify TTL is the same as the default one
    Assert.assertEquals(cConf.getInt(Constants.MessagingSystem.TOPIC_DEFAULT_TTL_SECONDS), client.getTopic(topic1).getTTL());
    // Update the topic t1 with new TTL
    client.updateTopic(new TopicMetadata(topic1, "ttl", "5"));
    // Get the topic t1 properties. Verify TTL is updated
    Assert.assertEquals(5, client.getTopic(topic1).getTTL());
    // Try to add another topic t2 with invalid ttl, it should fail
    try {
        client.createTopic(new TopicMetadata(topic2, "ttl", "xyz"));
        Assert.fail("Expect BadRequestException");
    } catch (IllegalArgumentException e) {
    // Expected
    }
    // Add topic t2 with valid ttl
    client.createTopic(new TopicMetadata(topic2, "ttl", "5"));
    // Get the topic t2 properties. It should have TTL set based on what provided
    Assert.assertEquals(5, client.getTopic(topic2).getTTL());
    // Listing topics under namespace ns1
    List<TopicId> topics = client.listTopics(nsId);
    Assert.assertEquals(Arrays.asList(topic1, topic2), topics);
    // Delete both topics
    client.deleteTopic(topic1);
    client.deleteTopic(topic2);
    // Delete a non exist topic should fail
    try {
        client.deleteTopic(topic1);
        Assert.fail("Expect TopicNotFoundException");
    } catch (TopicNotFoundException e) {
    // Expected
    }
    // Update a non exist topic should fail
    try {
        client.updateTopic(new TopicMetadata(topic1));
        Assert.fail("Expect TopicNotFoundException");
    } catch (TopicNotFoundException e) {
    // Expected
    }
    // Listing topics under namespace ns1 again, it should be empty
    Assert.assertTrue(client.listTopics(nsId).isEmpty());
}
Also used : TopicNotFoundException(co.cask.cdap.api.messaging.TopicNotFoundException) TopicId(co.cask.cdap.proto.id.TopicId) NamespaceId(co.cask.cdap.proto.id.NamespaceId) TopicAlreadyExistsException(co.cask.cdap.api.messaging.TopicAlreadyExistsException) TopicMetadata(co.cask.cdap.messaging.TopicMetadata) Test(org.junit.Test)

Example 5 with TopicNotFoundException

use of co.cask.cdap.api.messaging.TopicNotFoundException in project cdap by caskdata.

the class ClientMessagingService method rollback.

@Override
public void rollback(TopicId topicId, RollbackDetail rollbackDetail) throws TopicNotFoundException, IOException {
    ByteBuffer requestBody = (rollbackDetail instanceof ClientRollbackDetail) ? ByteBuffer.wrap(((ClientRollbackDetail) rollbackDetail).getEncoded()) : encodeRollbackDetail(rollbackDetail);
    HttpRequest httpRequest = remoteClient.requestBuilder(HttpMethod.POST, createTopicPath(topicId) + "/rollback").addHeader(HttpHeaders.CONTENT_TYPE, "avro/binary").withBody(requestBody).build();
    HttpResponse response = remoteClient.execute(httpRequest);
    if (response.getResponseCode() == HttpURLConnection.HTTP_NOT_FOUND) {
        throw new TopicNotFoundException(topicId.getNamespace(), topicId.getTopic());
    }
    handleError(response, "Failed to rollback message in topic " + topicId + " with rollback detail " + rollbackDetail);
}
Also used : HttpRequest(co.cask.common.http.HttpRequest) TopicNotFoundException(co.cask.cdap.api.messaging.TopicNotFoundException) HttpResponse(co.cask.common.http.HttpResponse) ByteBuffer(java.nio.ByteBuffer)

Aggregations

TopicNotFoundException (co.cask.cdap.api.messaging.TopicNotFoundException)22 TopicMetadata (co.cask.cdap.messaging.TopicMetadata)12 TopicId (co.cask.cdap.proto.id.TopicId)8 IOException (java.io.IOException)8 Test (org.junit.Test)8 HttpRequest (co.cask.common.http.HttpRequest)5 HttpResponse (co.cask.common.http.HttpResponse)5 CloseableIterator (co.cask.cdap.api.dataset.lib.CloseableIterator)3 Message (co.cask.cdap.api.messaging.Message)3 MessageFetcher (co.cask.cdap.api.messaging.MessageFetcher)3 TopicAlreadyExistsException (co.cask.cdap.api.messaging.TopicAlreadyExistsException)3 ApplicationManager (co.cask.cdap.test.ApplicationManager)3 TimeoutException (java.util.concurrent.TimeoutException)3 DBException (org.iq80.leveldb.DBException)3 MessagePublisher (co.cask.cdap.api.messaging.MessagePublisher)2 MessagingAdmin (co.cask.cdap.api.messaging.MessagingAdmin)2 NamespaceId (co.cask.cdap.proto.id.NamespaceId)2 SparkManager (co.cask.cdap.test.SparkManager)2 TreeMap (java.util.TreeMap)2 ExecutionException (java.util.concurrent.ExecutionException)2