@Override public void onTrigger(final ProcessContext context, final ProcessSession session) { FlowFile flowFile = session.get(); if (flowFile == null) { return; } final long startNanos = System.nanoTime(); final AmazonSQSClient client = getClient(); final SendMessageBatchRequest request = new SendMessageBatchRequest(); final String queueUrl = context.getProperty(QUEUE_URL).evaluateAttributeExpressions(flowFile).getValue(); request.setQueueUrl(queueUrl); final Set<SendMessageBatchRequestEntry> entries = new HashSet<>(); final SendMessageBatchRequestEntry entry = new SendMessageBatchRequestEntry(); entry.setId(flowFile.getAttribute("uuid")); final ByteArrayOutputStream baos = new ByteArrayOutputStream(); session.exportTo(flowFile, baos); final String flowFileContent = baos.toString(); entry.setMessageBody(flowFileContent); final Map<String, MessageAttributeValue> messageAttributes = new HashMap<>(); for (final PropertyDescriptor descriptor : userDefinedProperties) { final MessageAttributeValue mav = new MessageAttributeValue(); mav.setDataType("String"); mav.setStringValue( context.getProperty(descriptor).evaluateAttributeExpressions(flowFile).getValue()); messageAttributes.put(descriptor.getName(), mav); } entry.setMessageAttributes(messageAttributes); entry.setDelaySeconds(context.getProperty(DELAY).asTimePeriod(TimeUnit.SECONDS).intValue()); entries.add(entry); request.setEntries(entries); try { client.sendMessageBatch(request); } catch (final Exception e) { getLogger() .error( "Failed to send messages to Amazon SQS due to {}; routing to failure", new Object[] {e}); flowFile = session.penalize(flowFile); session.transfer(flowFile, REL_FAILURE); return; } getLogger() .info("Successfully published message to Amazon SQS for {}", new Object[] {flowFile}); session.transfer(flowFile, REL_SUCCESS); final long transmissionMillis = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - startNanos); session.getProvenanceReporter().send(flowFile, queueUrl, transmissionMillis); }
public AmazonSQSClient getSQSClient(String region) throws AmazonClientException { AmazonSQSClient sqsClient = null; try { AWSCredentials credentials = getAwsCredentials(); sqsClient = new AmazonSQSClient(credentials); sqsClient.setEndpoint("https://sqs." + region + ".amazonaws.com"); } catch (IOException e) { throw new AmazonClientException(e.getMessage()); } catch (IllegalArgumentException e) { throw new AmazonClientException(e.getMessage()); } return sqsClient; }
@Test public void shouldReceiveMessages() { String body = "A message"; when(sqsClient.receiveMessage(any(ReceiveMessageRequest.class)).getMessages()) .thenReturn(Arrays.asList(new Message().withBody(body))); List<String> messages = provider.receive(); assertThat(messages.size(), is(1)); assertThat(messages, hasItem(body)); }
public void run() { logger.debug("started GridManager"); System.out.println("started GridManager"); AmazonSQSClient sqsClient = new AmazonSQSClient(papa.getCredentials()); AmazonEC2Client ec2Client = new AmazonEC2Client(papa.getCredentials()); // Get current imageID from the metadata table String imageID = Constants.imageID; // get the default imageID from Constants try { Connection conn = PooledConnectionFactory.INSTANCE.getCumulusConnection(); Statement stmt = conn.createStatement(); String imageQuery = "SELECT mvalue FROM cumulus.metadata WHERE mkey='imageID';"; ResultSet results = stmt.executeQuery(imageQuery); results.next(); // move the cursor into the results imageID = results.getString(1); } catch (SQLException e) { logger.warn(e); } if (imageID == null || imageID.equals("")) { // if we get an empty imageID revert to the hardcoded one imageID = Constants.imageID; } logger.debug(imageID); System.out.println(imageID); while (true) { // loop from startup to shutdown // check the number of messages in the queue. GetQueueAttributesRequest sqsRequest = new GetQueueAttributesRequest(papa.getDispatchQueue()) .withAttributeNames("ApproximateNumberOfMessages"); Integer sqsResult = null; try { sqsResult = Integer.valueOf( sqsClient .getQueueAttributes(sqsRequest) .getAttributes() .get("ApproximateNumberOfMessages")); } catch (AmazonServiceException e) { // Write out any exceptions that may have occurred. System.err.println("Error getting list of instances"); System.err.println("Caught Exception: " + e.getMessage()); System.err.println("Reponse Status Code: " + e.getStatusCode()); System.err.println("Error Code: " + e.getErrorCode()); System.err.println("Request ID: " + e.getRequestId()); } catch (AmazonClientException e) { logger.warn(e); continue; // if the error is due to being unable to connect to sqs it is likely transient, // and we should keep going until SQS comes back } catch (Exception e) { // caught another exception System.err.println(e); System.err.println("Did not exit cleanly"); // System.exit(1); } if (sqsResult == null) { System.err.println( "Couldn't get the number of items in the queue reverting to static functioning"); logger.error( "Couldn't get the number of items in the queue reverting to static functioning"); break; } System.out.println("Queue size=" + sqsResult); // check the number of running instances. DescribeInstancesRequest describeInstancesRequest = new DescribeInstancesRequest(); // get the number of running instances with our image ID describeInstancesRequest.withFilters( new Filter("image-id").withValues(imageID), new Filter("instance-state-name").withValues("running")); logger.debug("Getting list of active cumulus drones"); Integer numInstances = null; Integer numSpotRequests = null; Initializer.serialize("/tmp/dump.obj", papa.unitsOnServer); // TODO test this. // check number of open spot requests DescribeSpotInstanceRequestsRequest describeSpotInstancesRequest = new DescribeSpotInstanceRequestsRequest(); describeSpotInstancesRequest.withFilters(new Filter("state").withValues("open")); try { // Parse returned instances DescribeInstancesResult describeInstancesResult = ec2Client.describeInstances(describeInstancesRequest); if (describeInstancesResult.getReservations().size() == 0) { numInstances = 0; } else { Integer totalInstances = 0; for (Reservation i : describeInstancesResult.getReservations()) { totalInstances += i.getInstances().size(); } numInstances = totalInstances; } // Parse returned open spot requests DescribeSpotInstanceRequestsResult describeSpotReservationsResult = ec2Client.describeSpotInstanceRequests(describeSpotInstancesRequest); if (describeSpotReservationsResult.getSpotInstanceRequests().size() == 0) { numSpotRequests = 0; } else { Integer totalInstances = 0; for (SpotInstanceRequest i : describeSpotReservationsResult.getSpotInstanceRequests()) { totalInstances++; } numSpotRequests = totalInstances; } // System.out.println("num instances="+numInstances); } catch (AmazonServiceException e) { // Write out any exceptions that may have occurred. System.err.println("Error getting list of instances"); System.err.println("Caught Exception: " + e.getMessage()); System.err.println("Reponse Status Code: " + e.getStatusCode()); System.err.println("Error Code: " + e.getErrorCode()); System.err.println("Request ID: " + e.getRequestId()); // System.exit(1); } catch (Exception e) { // caught another exception System.err.println(e); System.err.println("Did not exit cleanly"); // System.exit(1); } if (numInstances == null || numSpotRequests == null) { logger.error( "Couldn't get the number of machines or requests reverting to static functioning"); break; } System.out.println("num instances=" + (numInstances + numSpotRequests)); // if queue is longer than the number of instances * idealMaxUnitsPerInstance Integer idealMaxUnitsPerInstance = Integer.valueOf(Constants.idealMaxUnitsPerInstance); if (sqsResult > (numInstances + numSpotRequests) * idealMaxUnitsPerInstance) { // we count pending spot instances too. Integer numToCreate = (sqsResult / idealMaxUnitsPerInstance) - numInstances + 1; // check current pricing of spot instances DescribeSpotPriceHistoryRequest historyRequest = new DescribeSpotPriceHistoryRequest() .withAvailabilityZone("us-east-1c") .withInstanceTypes(Constants.instanceType) .withProductDescriptions("Linux/UNIX (Amazon VPC)") .withStartTime(new Date(System.currentTimeMillis())); DescribeSpotPriceHistoryResult result = ec2Client.describeSpotPriceHistory(historyRequest); Double nowPrice = Double.valueOf(result.getSpotPriceHistory().get(0).getSpotPrice()); // If spot price is < constants.spotPrice launch numToCreate*Constants.percentSpot spot // instances Integer spotToCreate = 0; if (nowPrice < Double.valueOf(Constants.spotPrice)) { Double percentSpot = Double.valueOf(Constants.percentSpot); spotToCreate = (int) (numToCreate * percentSpot); numToCreate = (int) (numToCreate * (1 - percentSpot)); } try { System.out.println("regular instances: " + numToCreate); System.out.println("spot instances: " + spotToCreate); // Create regular and spot instances if (numToCreate > 0) { papa.createInstances(ec2Client, numToCreate, imageID); } if (spotToCreate > 0) { papa.createSpotInstances(ec2Client, spotToCreate, Constants.imageID); // FIXME } System.out.println("created instances"); } catch (Exception e) { // Report ec2 exceptions logger.error(e); e.printStackTrace(); continue; } } try { Thread.sleep(60000); // we wait for any new servers to start up } catch (InterruptedException e) { logger.error("Sqslistener was interrupted"); if (papa.getShuttingDown()) { break; } else { continue; } } } }