Search in sources :

Example 46 with Message

use of com.yahoo.pulsar.client.api.Message in project pulsar by yahoo.

the class MessageIdTest method testCorruptMessageRemove.

/**
     * Verifies: if message is corrupted before sending to broker and if broker gives checksum error: then
     * 1. Client-Producer recomputes checksum with modified data
     * 2. Retry message-send again
     * 3. Broker verifies checksum 
     * 4. client receives send-ack success
     * 
     * @throws Exception
     */
@Test
public void testCorruptMessageRemove() throws Exception {
    final String topicName = "persistent://prop/use/ns-abc/retry-topic";
    ProducerConfiguration config = new ProducerConfiguration();
    config.setSendTimeout(10, TimeUnit.MINUTES);
    // 1. producer connect
    Producer prod = pulsarClient.createProducer(topicName, config);
    ProducerImpl producer = spy((ProducerImpl) prod);
    Field producerIdField = ProducerImpl.class.getDeclaredField("producerId");
    producerIdField.setAccessible(true);
    long producerId = (long) producerIdField.get(producer);
    // registered spy ProducerImpl
    producer.cnx().registerProducer(producerId, producer);
    Consumer consumer = pulsarClient.subscribe(topicName, "my-sub");
    // 2. Stop the broker, and publishes messages. Messages are accumulated in the producer queue and they're
    // checksums
    // would have already been computed. If we change the message content at that point, it should result in a
    // checksum validation error
    // enable checksum at producer
    stopBroker();
    Message msg = MessageBuilder.create().setContent("message-1".getBytes()).build();
    CompletableFuture<MessageId> future = producer.sendAsync(msg);
    // 3. corrupt the message
    // new content would be 'message-3'
    msg.getData()[msg.getData().length - 1] = '2';
    // 4. Restart the broker to have the messages published
    startBroker();
    try {
        future.get();
        fail("send message should have failed with checksum excetion");
    } catch (Exception e) {
        if (e.getCause() instanceof PulsarClientException.ChecksumException) {
        //ok (callback should get checksum exception as message was modified and corrupt)
        } else {
            fail("Callback should have only failed with ChecksumException", e);
        }
    }
    // 5. Verify
    // (5.1) Verify: producer's recoverChecksumError and updateChecksum invoked
    verify(producer, times(1)).recoverChecksumError(any(), anyLong());
    verify(producer, times(1)).verifyLocalBufferIsNotCorrupted(any());
    /**
         * (5.3) verify: ProducerImpl.verifyLocalBufferIsNotCorrupted() => validates if message
         * is corrupt
         */
    MessageImpl msg2 = (MessageImpl) MessageBuilder.create().setContent("message-1".getBytes()).build();
    ByteBuf payload = msg2.getDataBuffer();
    Builder metadataBuilder = ((MessageImpl) msg).getMessageBuilder();
    MessageMetadata msgMetadata = metadataBuilder.setProducerName("test").setSequenceId(1).setPublishTime(10L).build();
    ByteBuf cmd = Commands.newSend(producerId, 1, 1, ChecksumType.Crc32c, msgMetadata, payload);
    // (a) create OpSendMsg with message-data : "message-1"
    OpSendMsg op = OpSendMsg.create(((MessageImpl) msg), cmd, 1, null);
    // a.verify: as message is not corrupt: no need to update checksum
    assertTrue(producer.verifyLocalBufferIsNotCorrupted(op));
    // (b) corrupt message
    // new content would be 'message-2'
    msg2.getData()[msg2.getData().length - 1] = '2';
    // b. verify: as message is corrupt: update checksum
    assertFalse(producer.verifyLocalBufferIsNotCorrupted(op));
    assertEquals(producer.getPendingQueueSize(), 0);
    // [2] test-recoverChecksumError functionality
    stopBroker();
    MessageImpl msg1 = (MessageImpl) MessageBuilder.create().setContent("message-1".getBytes()).build();
    future = producer.sendAsync(msg1);
    ClientCnx cnx = spy(new ClientCnx((PulsarClientImpl) pulsarClient) {
    });
    String exc = "broker is already stopped";
    // when client-try to recover checksum by resending to broker: throw exception as broker is stopped
    doThrow(new IllegalStateException(exc)).when(cnx).ctx();
    try {
        producer.recoverChecksumError(cnx, 1);
        fail("it should call : resendMessages() => which should throw above mocked exception");
    } catch (IllegalStateException e) {
        assertEquals(exc, e.getMessage());
    }
    producer.close();
    consumer.close();
    // clean reference of mocked producer
    producer = null;
}
Also used : Message(com.yahoo.pulsar.client.api.Message) OpSendMsg(com.yahoo.pulsar.client.impl.ProducerImpl.OpSendMsg) MessageBuilder(com.yahoo.pulsar.client.api.MessageBuilder) Builder(com.yahoo.pulsar.common.api.proto.PulsarApi.MessageMetadata.Builder) ProducerConfiguration(com.yahoo.pulsar.client.api.ProducerConfiguration) DoubleByteBuf(com.yahoo.pulsar.common.api.DoubleByteBuf) ByteBuf(io.netty.buffer.ByteBuf) PulsarAdminException(com.yahoo.pulsar.client.admin.PulsarAdminException) PulsarClientException(com.yahoo.pulsar.client.api.PulsarClientException) Field(java.lang.reflect.Field) MessageMetadata(com.yahoo.pulsar.common.api.proto.PulsarApi.MessageMetadata) Producer(com.yahoo.pulsar.client.api.Producer) Consumer(com.yahoo.pulsar.client.api.Consumer) PulsarClientException(com.yahoo.pulsar.client.api.PulsarClientException) MessageId(com.yahoo.pulsar.client.api.MessageId) Test(org.testng.annotations.Test)

Example 47 with Message

use of com.yahoo.pulsar.client.api.Message in project pulsar by yahoo.

the class PersistentTopicsImpl method peekNthMessage.

private CompletableFuture<Message> peekNthMessage(String destination, String subName, int messagePosition) {
    DestinationName ds = validateTopic(destination);
    String encodedSubName = Codec.encode(subName);
    final CompletableFuture<Message> future = new CompletableFuture<Message>();
    asyncGetRequest(persistentTopics.path(ds.getNamespace()).path(ds.getEncodedLocalName()).path("subscription").path(encodedSubName).path("position").path(String.valueOf(messagePosition)), new InvocationCallback<Response>() {

        @Override
        public void completed(Response response) {
            try {
                Message msg = getMessageFromHttpResponse(response);
                future.complete(msg);
            } catch (Exception e) {
                future.completeExceptionally(getApiException(e));
            }
        }

        @Override
        public void failed(Throwable throwable) {
            future.completeExceptionally(getApiException(throwable.getCause()));
        }
    });
    return future;
}
Also used : Response(javax.ws.rs.core.Response) CompletableFuture(java.util.concurrent.CompletableFuture) Message(com.yahoo.pulsar.client.api.Message) DestinationName(com.yahoo.pulsar.common.naming.DestinationName) ClientErrorException(javax.ws.rs.ClientErrorException) NotFoundException(com.yahoo.pulsar.client.admin.PulsarAdminException.NotFoundException) PulsarAdminException(com.yahoo.pulsar.client.admin.PulsarAdminException) ExecutionException(java.util.concurrent.ExecutionException) ServerErrorException(javax.ws.rs.ServerErrorException) WebApplicationException(javax.ws.rs.WebApplicationException)

Example 48 with Message

use of com.yahoo.pulsar.client.api.Message in project pulsar by yahoo.

the class CmdConsume method run.

/**
     * Run the consume command.
     *
     * @return 0 for success, < 0 otherwise
     */
public int run() throws PulsarClientException, IOException {
    if (mainOptions.size() != 1)
        throw (new ParameterException("Please provide one and only one topic name."));
    if (this.serviceURL == null || this.serviceURL.isEmpty())
        throw (new ParameterException("Broker URL is not provided."));
    if (this.subscriptionName == null || this.subscriptionName.isEmpty())
        throw (new ParameterException("Subscription name is not provided."));
    if (this.numMessagesToConsume < 0)
        throw (new ParameterException("Number of messages should be zero or positive."));
    String topic = this.mainOptions.get(0);
    int numMessagesConsumed = 0;
    int returnCode = 0;
    try {
        ConsumerConfiguration consumerConf = new ConsumerConfiguration();
        consumerConf.setSubscriptionType(this.subscriptionType);
        PulsarClient client = PulsarClient.create(this.serviceURL, this.clientConfig);
        Consumer consumer = client.subscribe(topic, this.subscriptionName, consumerConf);
        RateLimiter limiter = (this.consumeRate > 0) ? RateLimiter.create(this.consumeRate) : null;
        while (this.numMessagesToConsume == 0 || numMessagesConsumed < this.numMessagesToConsume) {
            if (limiter != null) {
                limiter.acquire();
            }
            Message msg = consumer.receive(5, TimeUnit.SECONDS);
            if (msg == null) {
                LOG.warn("No message to consume after waiting for 20 seconds.");
            } else {
                numMessagesConsumed += 1;
                System.out.println(MESSAGE_BOUNDARY);
                String output = this.interpretMessage(msg, displayHex);
                System.out.println(output);
                consumer.acknowledge(msg);
            }
        }
        client.close();
    } catch (Exception e) {
        LOG.error("Error while consuming messages");
        LOG.error(e.getMessage(), e);
        returnCode = -1;
    } finally {
        LOG.info("{} messages successfully consumed", numMessagesConsumed);
    }
    return returnCode;
}
Also used : Consumer(com.yahoo.pulsar.client.api.Consumer) Message(com.yahoo.pulsar.client.api.Message) ConsumerConfiguration(com.yahoo.pulsar.client.api.ConsumerConfiguration) ParameterException(com.beust.jcommander.ParameterException) PulsarClient(com.yahoo.pulsar.client.api.PulsarClient) RateLimiter(com.google.common.util.concurrent.RateLimiter) ParameterException(com.beust.jcommander.ParameterException) IOException(java.io.IOException) PulsarClientException(com.yahoo.pulsar.client.api.PulsarClientException)

Example 49 with Message

use of com.yahoo.pulsar.client.api.Message in project pulsar by yahoo.

the class CmdProduce method run.

/**
     * Run the producer.
     *
     * @return 0 for success, < 0 otherwise
     * @throws Exception
     */
public int run() throws PulsarClientException {
    if (mainOptions.size() != 1)
        throw (new ParameterException("Please provide one and only one topic name."));
    if (this.serviceURL == null || this.serviceURL.isEmpty())
        throw (new ParameterException("Broker URL is not provided."));
    if (this.numTimesProduce <= 0)
        throw (new ParameterException("Number of times need to be positive number."));
    if (messages.size() == 0 && messageFileNames.size() == 0)
        throw (new ParameterException("Please supply message content with either --messages or --files"));
    int totalMessages = (messages.size() + messageFileNames.size()) * numTimesProduce;
    if (totalMessages > MAX_MESSAGES) {
        String msg = "Attempting to send " + totalMessages + " messages. Please do not send more than " + MAX_MESSAGES + " messages";
        throw new ParameterException(msg);
    }
    String topic = this.mainOptions.get(0);
    int numMessagesSent = 0;
    int returnCode = 0;
    try {
        PulsarClient client = PulsarClient.create(this.serviceURL, this.clientConfig);
        Producer producer = client.createProducer(topic);
        List<byte[]> messageBodies = generateMessageBodies(this.messages, this.messageFileNames);
        RateLimiter limiter = (this.publishRate > 0) ? RateLimiter.create(this.publishRate) : null;
        for (int i = 0; i < this.numTimesProduce; i++) {
            List<Message> messages = generateMessages(messageBodies);
            for (Message msg : messages) {
                if (limiter != null)
                    limiter.acquire();
                producer.send(msg);
                numMessagesSent++;
            }
        }
        client.close();
    } catch (Exception e) {
        LOG.error("Error while producing messages");
        LOG.error(e.getMessage(), e);
        returnCode = -1;
    } finally {
        LOG.info("{} messages successfully produced", numMessagesSent);
    }
    return returnCode;
}
Also used : Producer(com.yahoo.pulsar.client.api.Producer) Message(com.yahoo.pulsar.client.api.Message) ParameterException(com.beust.jcommander.ParameterException) PulsarClient(com.yahoo.pulsar.client.api.PulsarClient) RateLimiter(com.google.common.util.concurrent.RateLimiter) ParameterException(com.beust.jcommander.ParameterException) PulsarClientException(com.yahoo.pulsar.client.api.PulsarClientException)

Example 50 with Message

use of com.yahoo.pulsar.client.api.Message in project pulsar by yahoo.

the class CmdProduce method generateMessages.

/*
     * Generates a list of messages that can be produced
     *
     * @param stringMessages List of strings to send as messages
     * 
     * @param messageFileNames List of file names to read and send as messages
     * 
     * @return list of messages to send
     */
private List<Message> generateMessages(List<byte[]> messageBodies) {
    List<Message> messagesToSend = new ArrayList<Message>();
    try {
        for (byte[] msgBody : messageBodies) {
            MessageBuilder msgBuilder = MessageBuilder.create();
            msgBuilder.setContent(msgBody);
            messagesToSend.add(msgBuilder.build());
        }
    } catch (Exception e) {
        LOG.error(e.getMessage(), e);
    }
    return messagesToSend;
}
Also used : Message(com.yahoo.pulsar.client.api.Message) MessageBuilder(com.yahoo.pulsar.client.api.MessageBuilder) ArrayList(java.util.ArrayList) ParameterException(com.beust.jcommander.ParameterException) PulsarClientException(com.yahoo.pulsar.client.api.PulsarClientException)

Aggregations

Message (com.yahoo.pulsar.client.api.Message)90 Test (org.testng.annotations.Test)66 Consumer (com.yahoo.pulsar.client.api.Consumer)61 Producer (com.yahoo.pulsar.client.api.Producer)57 ConsumerConfiguration (com.yahoo.pulsar.client.api.ConsumerConfiguration)47 PersistentTopic (com.yahoo.pulsar.broker.service.persistent.PersistentTopic)31 PulsarClientException (com.yahoo.pulsar.client.api.PulsarClientException)25 ProducerConfiguration (com.yahoo.pulsar.client.api.ProducerConfiguration)22 CompletableFuture (java.util.concurrent.CompletableFuture)17 PulsarClient (com.yahoo.pulsar.client.api.PulsarClient)10 PulsarAdminException (com.yahoo.pulsar.client.admin.PulsarAdminException)9 MessageId (com.yahoo.pulsar.client.api.MessageId)9 PersistentSubscription (com.yahoo.pulsar.broker.service.persistent.PersistentSubscription)8 ClientConfiguration (com.yahoo.pulsar.client.api.ClientConfiguration)6 Field (java.lang.reflect.Field)6 HashSet (java.util.HashSet)6 MockedPulsarServiceBaseTest (com.yahoo.pulsar.broker.auth.MockedPulsarServiceBaseTest)5 RetentionPolicies (com.yahoo.pulsar.common.policies.data.RetentionPolicies)5 Tuple (backtype.storm.tuple.Tuple)4 ParameterException (com.beust.jcommander.ParameterException)4