/** * Send a message with an ID and content. * * @param id The ID associated with the message. * @param content The content of the message. * @throws PubSubException if the messaging system throws an error. */ default void send(String id, String content) throws PubSubException { send(new PubSubMessage(id, content)); }
@Override public void execute(Tuple tuple) { String id = tuple.getString(TopologyConstants.ID_POSITION); Metadata metadata = (Metadata) tuple.getValue(TopologyConstants.METADATA_POSITION); log.info("Looping back metadata with signal {} for {}", metadata.getSignal(), id); publish(new PubSubMessage(id, null, metadata), tuple); } }
@Override public void execute(Tuple tuple) { String id = tuple.getString(TopologyConstants.ID_POSITION); Metadata metadata = (Metadata) tuple.getValue(TopologyConstants.METADATA_POSITION); log.info("Looping back metadata with signal {} for {}", metadata.getSignal(), id); publish(new PubSubMessage(id, null, metadata), tuple); } }
private void handleResponse(String id, Response response) { if (response == null || response.getStatusCode() != OK_200) { log.error("Handling error for id {} with response {}", id, response); responses.offer(new PubSubMessage(id, DRPCError.CANNOT_REACH_DRPC.asJSONClip())); return; } log.info("Received for id {}: {} {}", response.getStatusCode(), id, response.getStatusText()); String body = response.getResponseBody(); PubSubMessage message = PubSubMessage.fromJSON(body); log.debug("Received for id {}:\n{}", message.getId(), message.getContent()); responses.offer(message); } }
private void handleResponse(String id, Response response) { if (response == null || response.getStatusCode() != OK_200) { log.error("Handling error for id {} with response {}", id, response); responses.offer(new PubSubMessage(id, DRPCError.CANNOT_REACH_DRPC.asJSONClip())); return; } log.info("Received for id {}: {} {}", response.getStatusCode(), id, response.getStatusText()); String body = response.getResponseBody(); PubSubMessage message = PubSubMessage.fromJSON(body); log.debug("Received for id {}:\n{}", message.getId(), message.getContent()); responses.offer(message); } }
public static String makeMessage(String id, String content, int sequence) { return new PubSubMessage(id, content, sequence).asJSON(); } public static Object makeMessageID(String id, int index) {
@Override public List<PubSubMessage> getMessages() throws PubSubException { // Try and read from DRPC. The DRPCSpout does a sleep for 1 ms if there are no tuples, so we don't have to do it. spout.nextTuple(); if (!collector.haveOutput()) { return null; } // The DRPCSpout only should have emitted one tuple List<List<Object>> tuples = collector.reset(); log.debug("Have a message through DRPC {}", tuples); List<Object> tupleAndID = tuples.get(0); // The first object is the actual DRPCSpout tuple and the second is the DRPC messageID. List<Object> tuple = (List<Object>) tupleAndID.get(0); Object drpcID = tupleAndID.get(1); // The first object in the tuple is our PubSubMessage as JSON String pubSubMessageJSON = (String) tuple.get(0); // The second object in the tuple is the serialized returnInfo added by the DRPCSpout String returnInfo = (String) tuple.get(1); log.debug("Read message\n{}\nfrom DRPC with return information {}", pubSubMessageJSON, returnInfo); PubSubMessage pubSubMessage = PubSubMessage.fromJSON(pubSubMessageJSON); // Add returnInfo as metadata. Cannot add it to pubSubMessage String id = pubSubMessage.getId(); String content = pubSubMessage.getContent(); int sequence = pubSubMessage.getSequence(); PubSubMessage message = new PubSubMessage(id, content, new Metadata(null, returnInfo), sequence); emittedIDs.put(ImmutablePair.of(id, sequence), drpcID); return Collections.singletonList(message); }
@Override public void execute(Tuple tuple) { String id = tuple.getString(TopologyConstants.ID_POSITION); String result = tuple.getString(TopologyConstants.RESULT_POSITION); Metadata metadata = (Metadata) tuple.getValue(TopologyConstants.RESULT_METADATA_POSITION); publish(new PubSubMessage(id, result, metadata), tuple); } }
@Override public void execute(Tuple tuple) { String id = tuple.getString(TopologyConstants.ID_POSITION); String result = tuple.getString(TopologyConstants.RESULT_POSITION); Metadata metadata = (Metadata) tuple.getValue(TopologyConstants.RESULT_METADATA_POSITION); publish(new PubSubMessage(id, result, metadata), tuple); } }
@Override public List<PubSubMessage> getMessages() throws PubSubException { // Try and read from DRPC. The DRPCSpout does a sleep for 1 ms if there are no tuples, so we don't have to do it. spout.nextTuple(); if (!collector.haveOutput()) { return null; } // The DRPCSpout only should have emitted one tuple List<List<Object>> tuples = collector.reset(); log.debug("Have a message through DRPC {}", tuples); List<Object> tupleAndID = tuples.get(0); // The first object is the actual DRPCSpout tuple and the second is the DRPC messageID. List<Object> tuple = (List<Object>) tupleAndID.get(0); Object drpcID = tupleAndID.get(1); // The first object in the tuple is our PubSubMessage as JSON String pubSubMessageJSON = (String) tuple.get(0); // The second object in the tuple is the serialized returnInfo added by the DRPCSpout String returnInfo = (String) tuple.get(1); log.debug("Read message\n{}\nfrom DRPC with return information {}", pubSubMessageJSON, returnInfo); PubSubMessage pubSubMessage = PubSubMessage.fromJSON(pubSubMessageJSON); // Add returnInfo as metadata. Cannot add it to pubSubMessage String id = pubSubMessage.getId(); String content = pubSubMessage.getContent(); int sequence = pubSubMessage.getSequence(); PubSubMessage message = new PubSubMessage(id, content, new Metadata(null, returnInfo), sequence); emittedIDs.put(ImmutablePair.of(id, sequence), drpcID); return Collections.singletonList(message); }
@Test public void testMessagesAreLooped() { List<PubSubMessage> expected = asList(new PubSubMessage("42", Metadata.Signal.KILL), new PubSubMessage("43", Metadata.Signal.COMPLETE), new PubSubMessage("44", (Metadata.Signal) null)); List<Tuple> tuples = new ArrayList<>(); expected.forEach(m -> tuples.add(makeTuple(m.getId(), m.getMetadata()))); for (int i = 0; i < tuples.size(); i++) { bolt.execute(tuples.get(i)); Assert.assertEquals(publisher.getSent().get(i).getId(), expected.get(i).getId()); Assert.assertEquals(publisher.getSent().get(i).getMetadata(), expected.get(i).getMetadata()); Assert.assertTrue(collector.wasNthAcked(tuples.get(i), i + 1)); Assert.assertEquals(collector.getAckedCount(), i + 1); } }
@Test(timeOut = 5000L) public void testException() throws Exception { // This will hit a non-existent url and fail, testing our exceptions. Our connect and retry is low so even if // block the full amount, it's still fast. pubscriber.send(new PubSubMessage("foo", "bar")); PubSubMessage actual = fetchAsync().get(); Assert.assertNotNull(actual); Assert.assertEquals(actual.getId(), "foo"); Assert.assertEquals(actual.getContent(), CANNOT_REACH_DRPC.asJSONClip()); } }
@Test(timeOut = 5000L) public void testReadingNullResponse() throws Exception { CompletableFuture<Response> response = getOkFuture(null); AsyncHttpClient mockClient = mockClientWith(response); pubscriber.setClient(mockClient); pubscriber.send(new PubSubMessage("foo", "bar")); // This is async (but practically still very fast since we mocked the response), so need a timeout. PubSubMessage actual = fetchAsync().get(); Assert.assertNotNull(actual); Assert.assertEquals(actual.getId(), "foo"); Assert.assertEquals(actual.getContent(), CANNOT_REACH_DRPC.asJSONClip()); }
@Test public void testExecuteMessagesAreSent() { List<PubSubMessage> expected = asList(new PubSubMessage("42", "This is a PubSubMessage", new Metadata()), new PubSubMessage("43", "This is also a PubSubMessage", new Metadata()), new PubSubMessage("44", "This is still a PubSubMessage", new Metadata())); List<Tuple> tuples = new ArrayList<>(); expected.forEach(m -> tuples.add(makeTuple(m.getId(), m.getContent(), m.getMetadata()))); for (int i = 0; i < tuples.size(); i++) { bolt.execute(tuples.get(i)); Assert.assertEquals(publisher.getSent().get(i).getId(), expected.get(i).getId()); Assert.assertEquals(publisher.getSent().get(i).getContent(), expected.get(i).getContent()); Assert.assertEquals(publisher.getSent().get(i).getMetadata(), expected.get(i).getMetadata()); Assert.assertTrue(collector.wasNthAcked(tuples.get(i), i + 1)); Assert.assertEquals(collector.getAckedCount(), i + 1); } }
@Test(timeOut = 5000L) public void testReadingOkResponse() throws Exception { PubSubMessage expected = new PubSubMessage("foo", "response"); CompletableFuture<Response> response = getOkFuture(getOkResponse(expected.asJSON())); AsyncHttpClient mockClient = mockClientWith(response); pubscriber.setClient(mockClient); pubscriber.send(new PubSubMessage("foo", "bar")); // This is async (but practically still very fast since we mocked the response), so need a timeout. PubSubMessage actual = fetchAsync().get(); Assert.assertNotNull(actual); Assert.assertEquals(actual.getId(), expected.getId()); Assert.assertEquals(actual.getContent(), expected.getContent()); }
@Test(timeOut = 5000L) public void testReadingNotOkResponse() throws Exception { CompletableFuture<Response> response = getOkFuture(getNotOkResponse(500)); AsyncHttpClient mockClient = mockClientWith(response); pubscriber.setClient(mockClient); pubscriber.send(new PubSubMessage("foo", "bar")); // This is async (but practically still very fast since we mocked the response), so need a timeout. PubSubMessage actual = fetchAsync().get(); Assert.assertNotNull(actual); Assert.assertEquals(actual.getId(), "foo"); Assert.assertEquals(actual.getContent(), CANNOT_REACH_DRPC.asJSONClip()); }
@Test(expectedExceptions = PubSubException.class) public void testFailing() throws Exception { injectedMockBolt.setFailNumber(1); Assert.assertEquals(injectedMockBolt.getCount(), 0); PubSubMessage message = new PubSubMessage("foo", "{}", new Metadata(null, makeReturnInfo("a", "testHost", 80))); publisher.send(message); }
@Test public void testSending() throws Exception { Assert.assertEquals(injectedMockBolt.getCount(), 0); PubSubMessage message = new PubSubMessage("foo", "{}", new Metadata(null, makeReturnInfo("a", "testHost", 80))); publisher.send(message); Assert.assertEquals(injectedMockBolt.getCount(), 1); Assert.assertTrue(collector.isAcked()); Assert.assertFalse(collector.isFailed()); // Output is no longer present Assert.assertFalse(collector.haveOutput()); Assert.assertNull(collector.reset()); message = new PubSubMessage("bar", "{}", new Metadata(null, makeReturnInfo("b", "testHost", 80))); publisher.send(message); Assert.assertEquals(injectedMockBolt.getCount(), 2); Assert.assertTrue(collector.isAcked()); Assert.assertFalse(collector.isFailed()); Assert.assertFalse(collector.haveOutput()); Assert.assertNull(collector.reset()); }
@Test public void testNextTupleMessagesAreReceivedAndTupleIsEmitted() { // Add messages to be received from subscriber PubSubMessage messageA = new PubSubMessage("42", "This is a PubSubMessage", new Metadata()); PubSubMessage messageB = new PubSubMessage("43", "This is also a PubSubMessage", new Metadata()); subscriber.addMessages(messageA, messageB); Assert.assertEquals(subscriber.getReceived().size(), 0); Assert.assertEquals(emitter.getEmitted().size(), 0); // subscriber.receive() -> messageA spout.nextTuple(); Assert.assertEquals(subscriber.getReceived().size(), 1); Assert.assertEquals(subscriber.getReceived().get(0), messageA); Tuple emittedFirst = TupleUtils.makeTuple(TupleClassifier.Type.QUERY_TUPLE, messageA.getId(), messageA.getContent(), messageA.getMetadata()); Assert.assertEquals(emitter.getEmitted().size(), 1); Assert.assertTrue(emitter.wasNthEmitted(emittedFirst, 1)); // subscriber.receive() -> messageB spout.nextTuple(); Assert.assertEquals(subscriber.getReceived().size(), 2); Assert.assertEquals(subscriber.getReceived().get(0), messageA); Assert.assertEquals(subscriber.getReceived().get(1), messageB); Tuple emittedSecond = TupleUtils.makeTuple(TupleClassifier.Type.QUERY_TUPLE, messageB.getId(), messageB.getContent(), messageB.getMetadata()); Assert.assertEquals(emitter.getEmitted().size(), 2); Assert.assertTrue(emitter.wasNthEmitted(emittedFirst, 1)); Assert.assertTrue(emitter.wasNthEmitted(emittedSecond, 2)); }
@Test public void testSignalOnlyMessagesAreSentOnTheMetadataStream() { // Add messages to be received from subscriber PubSubMessage messageA = new PubSubMessage("42", Metadata.Signal.KILL); PubSubMessage messageB = new PubSubMessage("43", Metadata.Signal.COMPLETE); PubSubMessage messageC = new PubSubMessage("44", null, new Metadata()); subscriber.addMessages(messageA, messageB, messageC); Assert.assertEquals(subscriber.getReceived().size(), 0); Assert.assertEquals(emitter.getEmitted().size(), 0); spout.nextTuple(); spout.nextTuple(); spout.nextTuple(); Assert.assertEquals(subscriber.getReceived().size(), 3); Assert.assertEquals(subscriber.getReceived().get(0), messageA); Assert.assertEquals(subscriber.getReceived().get(1), messageB); Assert.assertEquals(subscriber.getReceived().get(2), messageC); Assert.assertEquals(emitter.getEmitted().size(), 3); Tuple emittedFirst = TupleUtils.makeTuple(TupleClassifier.Type.METADATA_TUPLE, messageA.getId(), messageA.getMetadata()); Tuple emittedSecond = TupleUtils.makeTuple(TupleClassifier.Type.METADATA_TUPLE, messageB.getId(), messageB.getMetadata()); Tuple emittedThird = TupleUtils.makeTuple(TupleClassifier.Type.METADATA_TUPLE, messageC.getId(), messageC.getMetadata()); Assert.assertTrue(emitter.wasTupleEmittedTo(emittedFirst, TopologyConstants.METADATA_STREAM)); Assert.assertTrue(emitter.wasTupleEmittedTo(emittedSecond, TopologyConstants.METADATA_STREAM)); Assert.assertTrue(emitter.wasTupleEmittedTo(emittedThird, TopologyConstants.METADATA_STREAM)); Assert.assertTrue(emitter.wasNthEmitted(emittedFirst, 1)); Assert.assertTrue(emitter.wasNthEmitted(emittedSecond, 2)); Assert.assertTrue(emitter.wasNthEmitted(emittedThird, 3)); }