Search in sources :

Example 1 with StoreRequest

use of co.cask.cdap.messaging.StoreRequest in project cdap by caskdata.

the class ConcurrentMessageWriterTest method testMultiMaxSequence.

@Test
public void testMultiMaxSequence() throws IOException, InterruptedException {
    TopicId topicId = new NamespaceId("ns1").topic("t1");
    final TopicMetadata metadata = new TopicMetadata(topicId, new HashMap<String, String>(), 1);
    // This test the case when multiple StoreRequests combined exceeding the 65536 payload.
    // See testMaxSequence() for more details when it matters
    // Generate 3 StoreRequests, each with 43690 messages
    int msgCount = StoreRequestWriter.SEQUENCE_ID_LIMIT / 3 * 2;
    int requestCount = 3;
    List<StoreRequest> requests = new ArrayList<>();
    for (int i = 0; i < requestCount; i++) {
        List<String> payloads = new ArrayList<>(msgCount);
        for (int j = 0; j < msgCount; j++) {
            payloads.add(Integer.toString(j));
        }
        requests.add(new TestStoreRequest(topicId, payloads));
    }
    TestStoreRequestWriter testWriter = new TestStoreRequestWriter(new TimeProvider.IncrementalTimeProvider());
    // We use a custom metrics collector here to make all the persist calls reached the same latch,
    // since we know that the ConcurrentMessageWriter will emit a metrics "persist.requested" after enqueued but
    // before flushing.
    // This will make all requests batched together
    final CountDownLatch latch = new CountDownLatch(requestCount);
    final ConcurrentMessageWriter writer = new ConcurrentMessageWriter(testWriter, new MetricsCollector() {

        @Override
        public void increment(String metricName, long value) {
            if ("persist.requested".equals(metricName)) {
                latch.countDown();
                Uninterruptibles.awaitUninterruptibly(latch);
            }
        }

        @Override
        public void gauge(String metricName, long value) {
            LOG.info("MetricsContext.gauge: {} = {}", metricName, value);
        }
    });
    ExecutorService executor = Executors.newFixedThreadPool(3);
    for (final StoreRequest request : requests) {
        executor.submit(new Runnable() {

            @Override
            public void run() {
                try {
                    writer.persist(request, metadata);
                } catch (IOException e) {
                    LOG.error("Failed to persist", e);
                }
            }
        });
    }
    executor.shutdown();
    Assert.assertTrue(executor.awaitTermination(1, TimeUnit.MINUTES));
    // Validates all messages are being written
    List<RawMessage> messages = testWriter.getMessages().get(topicId);
    Assert.assertEquals(requestCount * msgCount, messages.size());
    // We expect the payload is in repeated sequence of [0..msgCount-1]
    int expectedPayload = 0;
    // The sequenceId should be (i % SEQUENCE_ID_LIMIT)
    for (int i = 0; i < messages.size(); i++) {
        RawMessage message = messages.get(i);
        MessageId messageId = new MessageId(message.getId());
        Assert.assertEquals(i / StoreRequestWriter.SEQUENCE_ID_LIMIT, messageId.getPublishTimestamp());
        Assert.assertEquals((short) (i % StoreRequestWriter.SEQUENCE_ID_LIMIT), messageId.getSequenceId());
        Assert.assertEquals(expectedPayload, Integer.parseInt(Bytes.toString(message.getPayload())));
        expectedPayload = (expectedPayload + 1) % msgCount;
    }
}
Also used : ArrayList(java.util.ArrayList) TopicId(co.cask.cdap.proto.id.TopicId) RawMessage(co.cask.cdap.messaging.data.RawMessage) MetricsCollector(co.cask.cdap.api.metrics.MetricsCollector) TimeProvider(co.cask.cdap.common.utils.TimeProvider) StoreRequest(co.cask.cdap.messaging.StoreRequest) IOException(java.io.IOException) CountDownLatch(java.util.concurrent.CountDownLatch) TopicMetadata(co.cask.cdap.messaging.TopicMetadata) ExecutorService(java.util.concurrent.ExecutorService) NamespaceId(co.cask.cdap.proto.id.NamespaceId) MessageId(co.cask.cdap.messaging.data.MessageId) Test(org.junit.Test)

Example 2 with StoreRequest

use of co.cask.cdap.messaging.StoreRequest in project cdap by caskdata.

the class StoreHandler method store.

@POST
@Path("/store")
public void store(HttpRequest request, HttpResponder responder, @PathParam("namespace") String namespace, @PathParam("topic") String topic) throws Exception {
    TopicId topicId = new NamespaceId(namespace).topic(topic);
    StoreRequest storeRequest = createStoreRequest(topicId, request);
    // It must be transactional with payload for store request
    if (!storeRequest.isTransactional() || !storeRequest.hasNext()) {
        throw new BadRequestException("Store request must be transactional with payload. Topic: " + topicId);
    }
    messagingService.storePayload(storeRequest);
    responder.sendStatus(HttpResponseStatus.OK);
}
Also used : StoreRequest(co.cask.cdap.messaging.StoreRequest) BadRequestException(co.cask.cdap.common.BadRequestException) TopicId(co.cask.cdap.proto.id.TopicId) NamespaceId(co.cask.cdap.proto.id.NamespaceId) Path(javax.ws.rs.Path) POST(javax.ws.rs.POST)

Example 3 with StoreRequest

use of co.cask.cdap.messaging.StoreRequest in project cdap by caskdata.

the class StoreHandler method publish.

@POST
@Path("/publish")
public void publish(HttpRequest request, HttpResponder responder, @PathParam("namespace") String namespace, @PathParam("topic") String topic) throws Exception {
    TopicId topicId = new NamespaceId(namespace).topic(topic);
    StoreRequest storeRequest = createStoreRequest(topicId, request);
    // Empty payload is only allowed for transactional publish
    if (!storeRequest.isTransactional() && !storeRequest.hasNext()) {
        throw new BadRequestException("Empty payload is only allowed for publishing transactional message. Topic: " + topicId);
    }
    // Publish the message and response with the rollback information
    RollbackDetail rollbackInfo = messagingService.publish(storeRequest);
    if (rollbackInfo == null) {
        // Non-tx publish doesn't have rollback info.
        responder.sendStatus(HttpResponseStatus.OK);
        return;
    }
    ChannelBuffer response = encodeRollbackDetail(rollbackInfo);
    responder.sendContent(HttpResponseStatus.OK, response, "avro/binary", null);
}
Also used : RollbackDetail(co.cask.cdap.messaging.RollbackDetail) StoreRequest(co.cask.cdap.messaging.StoreRequest) BadRequestException(co.cask.cdap.common.BadRequestException) TopicId(co.cask.cdap.proto.id.TopicId) NamespaceId(co.cask.cdap.proto.id.NamespaceId) ChannelBuffer(org.jboss.netty.buffer.ChannelBuffer) Path(javax.ws.rs.Path) POST(javax.ws.rs.POST)

Aggregations

StoreRequest (co.cask.cdap.messaging.StoreRequest)3 NamespaceId (co.cask.cdap.proto.id.NamespaceId)3 TopicId (co.cask.cdap.proto.id.TopicId)3 BadRequestException (co.cask.cdap.common.BadRequestException)2 POST (javax.ws.rs.POST)2 Path (javax.ws.rs.Path)2 MetricsCollector (co.cask.cdap.api.metrics.MetricsCollector)1 TimeProvider (co.cask.cdap.common.utils.TimeProvider)1 RollbackDetail (co.cask.cdap.messaging.RollbackDetail)1 TopicMetadata (co.cask.cdap.messaging.TopicMetadata)1 MessageId (co.cask.cdap.messaging.data.MessageId)1 RawMessage (co.cask.cdap.messaging.data.RawMessage)1 IOException (java.io.IOException)1 ArrayList (java.util.ArrayList)1 CountDownLatch (java.util.concurrent.CountDownLatch)1 ExecutorService (java.util.concurrent.ExecutorService)1 ChannelBuffer (org.jboss.netty.buffer.ChannelBuffer)1 Test (org.junit.Test)1