From 2cf73171768ab3d937abfbab6b0c278e12cb3a12 Mon Sep 17 00:00:00 2001 From: Pankaj Agrawal Date: Tue, 21 Dec 2021 17:36:11 +0100 Subject: [PATCH] fix: support batch size greater than 10 processing --- .../powertools/sqs/internal/BatchContext.java | 51 ++- .../sqs/SqsUtilsBatchProcessorTest.java | 85 +++- .../SqsMessageBatchProcessorAspectTest.java | 11 +- .../sampleSqsBatchEventBatchSize25.json | 404 ++++++++++++++++++ 4 files changed, 527 insertions(+), 24 deletions(-) create mode 100644 powertools-sqs/src/test/resources/sampleSqsBatchEventBatchSize25.json diff --git a/powertools-sqs/src/main/java/software/amazon/lambda/powertools/sqs/internal/BatchContext.java b/powertools-sqs/src/main/java/software/amazon/lambda/powertools/sqs/internal/BatchContext.java index 04903da6c..ff9add984 100644 --- a/powertools-sqs/src/main/java/software/amazon/lambda/powertools/sqs/internal/BatchContext.java +++ b/powertools-sqs/src/main/java/software/amazon/lambda/powertools/sqs/internal/BatchContext.java @@ -6,7 +6,8 @@ import java.util.List; import java.util.Map; import java.util.Optional; - +import java.util.function.Consumer; +import java.util.stream.IntStream; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JsonNode; import org.slf4j.Logger; @@ -20,6 +21,7 @@ import software.amazon.awssdk.services.sqs.model.GetQueueAttributesResponse; import software.amazon.awssdk.services.sqs.model.MessageAttributeValue; import software.amazon.awssdk.services.sqs.model.QueueAttributeName; +import software.amazon.awssdk.services.sqs.model.SendMessageBatchRequest; import software.amazon.awssdk.services.sqs.model.SendMessageBatchRequestEntry; import software.amazon.awssdk.services.sqs.model.SendMessageBatchResponse; import software.amazon.lambda.powertools.sqs.SQSBatchProcessingException; @@ -156,14 +158,20 @@ private boolean moveNonRetryableMessagesToDlqIfConfigured(Map builder.queueUrl(dlqUrl.get()) - .entries(dlqMessages)); + batchRequest(dlqMessages, 10, entriesToSend -> { + + SendMessageBatchResponse sendMessageBatchResponse = client.sendMessageBatch(SendMessageBatchRequest.builder() + .entries(entriesToSend) + .queueUrl(dlqUrl.get()) + .build()); - LOG.debug("Response from send batch message to DLQ request {}", sendMessageBatchResponse); + LOG.debug("Response from send batch message to DLQ request {}", sendMessageBatchResponse); + }); return true; } + private Optional fetchDlqUrl(Map nonRetryableMessageToException) { return nonRetryableMessageToException.keySet().stream() .findFirst() @@ -197,19 +205,34 @@ private boolean hasFailures() { private void deleteMessagesFromQueue(final List messages) { if (!messages.isEmpty()) { - DeleteMessageBatchRequest request = DeleteMessageBatchRequest.builder() - .queueUrl(url(messages.get(0).getEventSourceArn())) - .entries(messages.stream().map(m -> DeleteMessageBatchRequestEntry.builder() - .id(m.getMessageId()) - .receiptHandle(m.getReceiptHandle()) - .build()).collect(toList())) - .build(); - - DeleteMessageBatchResponse deleteMessageBatchResponse = client.deleteMessageBatch(request); - LOG.debug("Response from delete request {}", deleteMessageBatchResponse); + + List entries = messages.stream().map(m -> DeleteMessageBatchRequestEntry.builder() + .id(m.getMessageId()) + .receiptHandle(m.getReceiptHandle()) + .build()).collect(toList()); + + batchRequest(entries, 10, entriesToDelete -> { + DeleteMessageBatchRequest request = DeleteMessageBatchRequest.builder() + .queueUrl(url(messages.get(0).getEventSourceArn())) + .entries(entriesToDelete) + .build(); + + DeleteMessageBatchResponse deleteMessageBatchResponse = client.deleteMessageBatch(request); + + LOG.debug("Response from delete request {}", deleteMessageBatchResponse); + }); } } + private void batchRequest(final List listOFEntries, + final int size, + final Consumer> batchLogic) { + IntStream.range(0, listOFEntries.size()) + .filter(index -> index % size == 0) + .mapToObj(index -> listOFEntries.subList(index, Math.min(index + size, listOFEntries.size()))) + .forEach(batchLogic); + } + private String url(String queueArn) { String[] arnArray = queueArn.split(":"); return String.format("https://sqs.%s.amazonaws.com/%s/%s", arnArray[3], arnArray[4], arnArray[5]); diff --git a/powertools-sqs/src/test/java/software/amazon/lambda/powertools/sqs/SqsUtilsBatchProcessorTest.java b/powertools-sqs/src/test/java/software/amazon/lambda/powertools/sqs/SqsUtilsBatchProcessorTest.java index eb1128320..0d1c9c35a 100644 --- a/powertools-sqs/src/test/java/software/amazon/lambda/powertools/sqs/SqsUtilsBatchProcessorTest.java +++ b/powertools-sqs/src/test/java/software/amazon/lambda/powertools/sqs/SqsUtilsBatchProcessorTest.java @@ -1,10 +1,11 @@ package software.amazon.lambda.powertools.sqs; import java.io.IOException; +import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.function.Consumer; - +import java.util.function.Function; import com.amazonaws.services.lambda.runtime.events.SQSEvent; import com.fasterxml.jackson.databind.ObjectMapper; import org.assertj.core.api.Assertions; @@ -18,8 +19,11 @@ import software.amazon.awssdk.services.sqs.model.GetQueueAttributesRequest; import software.amazon.awssdk.services.sqs.model.GetQueueAttributesResponse; import software.amazon.awssdk.services.sqs.model.QueueAttributeName; +import software.amazon.awssdk.services.sqs.model.SendMessageBatchRequest; +import software.amazon.awssdk.services.sqs.model.SendMessageBatchRequestEntry; import static com.amazonaws.services.lambda.runtime.events.SQSEvent.SQSMessage; +import static org.assertj.core.api.Assertions.*; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatExceptionOfType; import static org.mockito.ArgumentMatchers.any; @@ -236,10 +240,10 @@ void shouldBatchProcessAndMoveNonRetryableExceptionToDlq() { return "Success"; }, IllegalStateException.class, IllegalArgumentException.class); - Assertions.assertThat(batchProcessor) + assertThat(batchProcessor) .hasSize(1); - verify(sqsClient).sendMessageBatch(any(Consumer.class)); + verify(sqsClient).sendMessageBatch(any(SendMessageBatchRequest.class)); } @Test @@ -265,13 +269,84 @@ void shouldBatchProcessAndDeleteNonRetryableException() { return "Success"; }, true, IllegalStateException.class, IllegalArgumentException.class); - Assertions.assertThat(batchProcessor) + assertThat(batchProcessor) .hasSize(1); - verify(sqsClient, times(0)).sendMessageBatch(any(Consumer.class)); + verify(sqsClient, times(0)).sendMessageBatch(any(SendMessageBatchRequest.class)); verify(sqsClient).deleteMessageBatch(any(DeleteMessageBatchRequest.class)); } + @Test + void shouldDeleteSuccessfulMessageInBatchesOfT10orLess() throws IOException { + SQSEvent batch25Message = MAPPER.readValue(this.getClass().getResource("/sampleSqsBatchEventBatchSize25.json"), SQSEvent.class); + + assertThatExceptionOfType(SQSBatchProcessingException.class) + .isThrownBy(() -> batchProcessor(batch25Message, FailureSampleInnerSqsHandler.class)) + .satisfies(e -> { + + assertThat(e.successMessageReturnValues()) + .hasSize(24) + .contains("Success"); + + assertThat(e.getFailures()) + .hasSize(1) + .extracting("messageId") + .contains("2e1424d4-f796-459a-8184-9c92662be6da"); + + assertThat(e.getExceptions()) + .hasSize(1) + .extracting("detailMessage") + .contains("Failed processing"); + }); + + ArgumentCaptor captor = ArgumentCaptor.forClass(DeleteMessageBatchRequest.class); + + verify(sqsClient, times(3)).deleteMessageBatch(captor.capture()); + + assertThat(captor.getAllValues()) + .hasSize(3) + .flatMap(DeleteMessageBatchRequest::entries) + .hasSize(24); + } + + @Test + void shouldBatchProcessAndMoveNonRetryableExceptionToDlqInBatchesOfT10orLess() throws IOException { + SQSEvent batch25Message = MAPPER.readValue(this.getClass().getResource("/sampleSqsBatchEventBatchSize25.json"), SQSEvent.class); + + HashMap attributes = new HashMap<>(); + + attributes.put(QueueAttributeName.REDRIVE_POLICY, "{\n" + + " \"deadLetterTargetArn\": \"arn:aws:sqs:us-east-2:123456789012:retry-queue\",\n" + + " \"maxReceiveCount\": 2\n" + + "}"); + + when(sqsClient.getQueueAttributes(any(GetQueueAttributesRequest.class))).thenReturn(GetQueueAttributesResponse.builder() + .attributes(attributes) + .build()); + + List batchProcessor = batchProcessor(batch25Message, (message) -> { + if ("2e1424d4-f796-459a-8184-9c92662be6da".equals(message.getMessageId())) { + interactionClient.listQueues(); + return "Success"; + } + + throw new IllegalStateException("Failed processing"); + }, IllegalStateException.class, IllegalArgumentException.class); + + assertThat(batchProcessor) + .hasSize(1); + + ArgumentCaptor captor = ArgumentCaptor.forClass(SendMessageBatchRequest.class); + + + verify(sqsClient, times(3)).sendMessageBatch(captor.capture()); + + assertThat(captor.getAllValues()) + .hasSize(3) + .flatMap(SendMessageBatchRequest::entries) + .hasSize(24); + } + public class FailureSampleInnerSqsHandler implements SqsMessageHandler { @Override public String process(SQSEvent.SQSMessage message) { diff --git a/powertools-sqs/src/test/java/software/amazon/lambda/powertools/sqs/internal/SqsMessageBatchProcessorAspectTest.java b/powertools-sqs/src/test/java/software/amazon/lambda/powertools/sqs/internal/SqsMessageBatchProcessorAspectTest.java index 5d25b8ffa..dd10ec1df 100644 --- a/powertools-sqs/src/test/java/software/amazon/lambda/powertools/sqs/internal/SqsMessageBatchProcessorAspectTest.java +++ b/powertools-sqs/src/test/java/software/amazon/lambda/powertools/sqs/internal/SqsMessageBatchProcessorAspectTest.java @@ -19,6 +19,7 @@ import software.amazon.awssdk.services.sqs.model.GetQueueAttributesRequest; import software.amazon.awssdk.services.sqs.model.GetQueueAttributesResponse; import software.amazon.awssdk.services.sqs.model.QueueAttributeName; +import software.amazon.awssdk.services.sqs.model.SendMessageBatchRequest; import software.amazon.lambda.powertools.sqs.SQSBatchProcessingException; import software.amazon.lambda.powertools.sqs.handlers.LambdaHandlerApiGateway; import software.amazon.lambda.powertools.sqs.handlers.PartialBatchFailureSuppressedHandler; @@ -133,7 +134,7 @@ void shouldBatchProcessAndMoveNonRetryableExceptionToDlq() { verify(interactionClient).listQueues(); verify(sqsClient).deleteMessageBatch(any(DeleteMessageBatchRequest.class)); - verify(sqsClient).sendMessageBatch(any(Consumer.class)); + verify(sqsClient).sendMessageBatch(any(SendMessageBatchRequest.class)); } @Test @@ -146,7 +147,7 @@ void shouldBatchProcessAndDeleteNonRetryableExceptionMessage() { verify(interactionClient).listQueues(); ArgumentCaptor captor = ArgumentCaptor.forClass(DeleteMessageBatchRequest.class); verify(sqsClient).deleteMessageBatch(captor.capture()); - verify(sqsClient, never()).sendMessageBatch(any(Consumer.class)); + verify(sqsClient, never()).sendMessageBatch(any(SendMessageBatchRequest.class)); verify(sqsClient, never()).getQueueAttributes(any(GetQueueAttributesRequest.class)); assertThat(captor.getValue()) @@ -186,7 +187,7 @@ void shouldBatchProcessAndFailWithExceptionForNonRetryableExceptionAndNoDlq() { verify(interactionClient).listQueues(); verify(sqsClient).deleteMessageBatch(any(DeleteMessageBatchRequest.class)); - verify(sqsClient, never()).sendMessageBatch(any(Consumer.class)); + verify(sqsClient, never()).sendMessageBatch(any(SendMessageBatchRequest.class)); } @Test @@ -223,7 +224,7 @@ void shouldBatchProcessAndFailWithExceptionForNonRetryableExceptionWhenFailedPar verify(interactionClient).listQueues(); verify(sqsClient).deleteMessageBatch(any(DeleteMessageBatchRequest.class)); - verify(sqsClient, never()).sendMessageBatch(any(Consumer.class)); + verify(sqsClient, never()).sendMessageBatch(any(SendMessageBatchRequest.class)); } @Test @@ -264,7 +265,7 @@ void shouldBatchProcessAndMoveNonRetryableExceptionToDlqAndThrowException() thro verify(interactionClient).listQueues(); verify(sqsClient).deleteMessageBatch(any(DeleteMessageBatchRequest.class)); - verify(sqsClient).sendMessageBatch(any(Consumer.class)); + verify(sqsClient).sendMessageBatch(any(SendMessageBatchRequest.class)); } private void setupContext() { diff --git a/powertools-sqs/src/test/resources/sampleSqsBatchEventBatchSize25.json b/powertools-sqs/src/test/resources/sampleSqsBatchEventBatchSize25.json new file mode 100644 index 000000000..31b8862ad --- /dev/null +++ b/powertools-sqs/src/test/resources/sampleSqsBatchEventBatchSize25.json @@ -0,0 +1,404 @@ +{ + "records": [ + { + "messageId": "059f36b4-87a3-44ab-83d2-661975830a7d", + "receiptHandle": "AQEBwJnKyrHigUMZj6rYigCgxlaS3SLy0a...", + "body": "Test message.", + "attributes": { + "ApproximateReceiveCount": "1", + "SentTimestamp": "1545082649183", + "SenderId": "AIDAIENQZJOLO23YVJ4VO", + "ApproximateFirstReceiveTimestamp": "1545082649185" + }, + "messageAttributes": {}, + "md5OfBody": "e4e68fb7bd0e697a0ae8f1bb342846b3", + "eventSource": "aws:sqs", + "eventSourceArn": "arn:aws:sqs:us-east-2:123456789012:my-queue", + "awsRegion": "us-east-2" + }, + { + "messageId": "2e1424d4-f796-459a-8184-9c92662be6da", + "receiptHandle": "AQEBzWwaftRI0KuVm4tP+/7q1rGgNqicHq...", + "body": "Test message.", + "attributes": { + "ApproximateReceiveCount": "1", + "SentTimestamp": "1545082650636", + "SenderId": "AIDAIENQZJOLO23YVJ4VO", + "ApproximateFirstReceiveTimestamp": "1545082650649" + }, + "messageAttributes": {}, + "md5OfBody": "e4e68fb7bd0e697a0ae8f1bb342846b3", + "eventSource": "aws:sqs", + "eventSourceArn": "arn:aws:sqs:us-east-2:123456789012:my-queue", + "awsRegion": "us-east-2" + }, + { + "messageId": "2e1424d4-f796-459a-8184-9c92662be6d3", + "receiptHandle": "AQEBzWwaftRI0KuVm4tP+/7q1rGgNqicHq...", + "body": "Test message.", + "attributes": { + "ApproximateReceiveCount": "1", + "SentTimestamp": "1545082650636", + "SenderId": "AIDAIENQZJOLO23YVJ4VO", + "ApproximateFirstReceiveTimestamp": "1545082650649" + }, + "messageAttributes": {}, + "md5OfBody": "e4e68fb7bd0e697a0ae8f1bb342846b3", + "eventSource": "aws:sqs", + "eventSourceArn": "arn:aws:sqs:us-east-2:123456789012:my-queue", + "awsRegion": "us-east-2" + }, + { + "messageId": "2e1424d4-f796-459a-8184-9c92662be6d4", + "receiptHandle": "AQEBzWwaftRI0KuVm4tP+/7q1rGgNqicHq...", + "body": "Test message.", + "attributes": { + "ApproximateReceiveCount": "1", + "SentTimestamp": "1545082650636", + "SenderId": "AIDAIENQZJOLO23YVJ4VO", + "ApproximateFirstReceiveTimestamp": "1545082650649" + }, + "messageAttributes": {}, + "md5OfBody": "e4e68fb7bd0e697a0ae8f1bb342846b5", + "eventSource": "aws:sqs", + "eventSourceArn": "arn:aws:sqs:us-east-2:123456789012:my-queue", + "awsRegion": "us-east-2" + }, + { + "messageId": "2e1424d4-f796-459a-8184-9c92662be6d6", + "receiptHandle": "AQEBzWwaftRI0KuVm4tP+/7q1rGgNqicHq...", + "body": "Test message.", + "attributes": { + "ApproximateReceiveCount": "1", + "SentTimestamp": "1545082650636", + "SenderId": "AIDAIENQZJOLO23YVJ4VO", + "ApproximateFirstReceiveTimestamp": "1545082650649" + }, + "messageAttributes": {}, + "md5OfBody": "e4e68fb7bd0e697a0ae8f1bb342846b7", + "eventSource": "aws:sqs", + "eventSourceArn": "arn:aws:sqs:us-east-2:123456789012:my-queue", + "awsRegion": "us-east-2" + }, + { + "messageId": "2e1424d4-f796-459a-8184-9c92662be6d8", + "receiptHandle": "AQEBzWwaftRI0KuVm4tP+/7q1rGgNqicHq...", + "body": "Test message.", + "attributes": { + "ApproximateReceiveCount": "1", + "SentTimestamp": "1545082650636", + "SenderId": "AIDAIENQZJOLO23YVJ4VO", + "ApproximateFirstReceiveTimestamp": "1545082650649" + }, + "messageAttributes": {}, + "md5OfBody": "e4e68fb7bd0e697a0ae8f1bb342846b3", + "eventSource": "aws:sqs", + "eventSourceArn": "arn:aws:sqs:us-east-2:123456789012:my-queue", + "awsRegion": "us-east-2" + }, + { + "messageId": "2e1424d4-f796-459a-8184-9c92662be6d9", + "receiptHandle": "AQEBzWwaftRI0KuVm4tP+/7q1rGgNqicHq...", + "body": "Test message.", + "attributes": { + "ApproximateReceiveCount": "1", + "SentTimestamp": "1545082650636", + "SenderId": "AIDAIENQZJOLO23YVJ4VO", + "ApproximateFirstReceiveTimestamp": "1545082650649" + }, + "messageAttributes": {}, + "md5OfBody": "e4e68fb7bd0e697a0ae8f1bb342846b3", + "eventSource": "aws:sqs", + "eventSourceArn": "arn:aws:sqs:us-east-2:123456789012:my-queue", + "awsRegion": "us-east-2" + }, + { + "messageId": "2e1424d4-f796-459a-8184-9c92662be6d10", + "receiptHandle": "AQEBzWwaftRI0KuVm4tP+/7q1rGgNqicHq...", + "body": "Test message.", + "attributes": { + "ApproximateReceiveCount": "1", + "SentTimestamp": "1545082650636", + "SenderId": "AIDAIENQZJOLO23YVJ4VO", + "ApproximateFirstReceiveTimestamp": "1545082650649" + }, + "messageAttributes": {}, + "md5OfBody": "e4e68fb7bd0e697a0ae8f1bb342846b3", + "eventSource": "aws:sqs", + "eventSourceArn": "arn:aws:sqs:us-east-2:123456789012:my-queue", + "awsRegion": "us-east-2" + }, + { + "messageId": "2e1424d4-f796-459a-8184-9c92662be6d11", + "receiptHandle": "AQEBzWwaftRI0KuVm4tP+/7q1rGgNqicHq...", + "body": "Test message.", + "attributes": { + "ApproximateReceiveCount": "1", + "SentTimestamp": "1545082650636", + "SenderId": "AIDAIENQZJOLO23YVJ4VO", + "ApproximateFirstReceiveTimestamp": "1545082650649" + }, + "messageAttributes": {}, + "md5OfBody": "e4e68fb7bd0e697a0ae8f1bb342846b3", + "eventSource": "aws:sqs", + "eventSourceArn": "arn:aws:sqs:us-east-2:123456789012:my-queue", + "awsRegion": "us-east-2" + }, + { + "messageId": "2e1424d4-f796-459a-8184-9c92662be6d12", + "receiptHandle": "AQEBzWwaftRI0KuVm4tP+/7q1rGgNqicHq...", + "body": "Test message.", + "attributes": { + "ApproximateReceiveCount": "1", + "SentTimestamp": "1545082650636", + "SenderId": "AIDAIENQZJOLO23YVJ4VO", + "ApproximateFirstReceiveTimestamp": "1545082650649" + }, + "messageAttributes": {}, + "md5OfBody": "e4e68fb7bd0e697a0ae8f1bb342846b3", + "eventSource": "aws:sqs", + "eventSourceArn": "arn:aws:sqs:us-east-2:123456789012:my-queue", + "awsRegion": "us-east-2" + }, + { + "messageId": "2e1424d4-f796-459a-8184-9c92662be6d13", + "receiptHandle": "AQEBzWwaftRI0KuVm4tP+/7q1rGgNqicHq...", + "body": "Test message.", + "attributes": { + "ApproximateReceiveCount": "1", + "SentTimestamp": "1545082650636", + "SenderId": "AIDAIENQZJOLO23YVJ4VO", + "ApproximateFirstReceiveTimestamp": "1545082650649" + }, + "messageAttributes": {}, + "md5OfBody": "e4e68fb7bd0e697a0ae8f1bb342846b3", + "eventSource": "aws:sqs", + "eventSourceArn": "arn:aws:sqs:us-east-2:123456789012:my-queue", + "awsRegion": "us-east-2" + }, + { + "messageId": "2e1424d4-f796-459a-8184-9c92662be6d14", + "receiptHandle": "AQEBzWwaftRI0KuVm4tP+/7q1rGgNqicHq...", + "body": "Test message.", + "attributes": { + "ApproximateReceiveCount": "1", + "SentTimestamp": "1545082650636", + "SenderId": "AIDAIENQZJOLO23YVJ4VO", + "ApproximateFirstReceiveTimestamp": "1545082650649" + }, + "messageAttributes": {}, + "md5OfBody": "e4e68fb7bd0e697a0ae8f1bb342846b3", + "eventSource": "aws:sqs", + "eventSourceArn": "arn:aws:sqs:us-east-2:123456789012:my-queue", + "awsRegion": "us-east-2" + }, + { + "messageId": "2e1424d4-f796-459a-8184-9c92662be6d15", + "receiptHandle": "AQEBzWwaftRI0KuVm4tP+/7q1rGgNqicHq...", + "body": "Test message.", + "attributes": { + "ApproximateReceiveCount": "1", + "SentTimestamp": "1545082650636", + "SenderId": "AIDAIENQZJOLO23YVJ4VO", + "ApproximateFirstReceiveTimestamp": "1545082650649" + }, + "messageAttributes": {}, + "md5OfBody": "e4e68fb7bd0e697a0ae8f1bb342846b3", + "eventSource": "aws:sqs", + "eventSourceArn": "arn:aws:sqs:us-east-2:123456789012:my-queue", + "awsRegion": "us-east-2" + }, + { + "messageId": "2e1424d4-f796-459a-8184-9c92662be6d16", + "receiptHandle": "AQEBzWwaftRI0KuVm4tP+/7q1rGgNqicHq...", + "body": "Test message.", + "attributes": { + "ApproximateReceiveCount": "1", + "SentTimestamp": "1545082650636", + "SenderId": "AIDAIENQZJOLO23YVJ4VO", + "ApproximateFirstReceiveTimestamp": "1545082650649" + }, + "messageAttributes": {}, + "md5OfBody": "e4e68fb7bd0e697a0ae8f1bb342846b3", + "eventSource": "aws:sqs", + "eventSourceArn": "arn:aws:sqs:us-east-2:123456789012:my-queue", + "awsRegion": "us-east-2" + }, + { + "messageId": "2e1424d4-f796-459a-8184-9c92662be6d17", + "receiptHandle": "AQEBzWwaftRI0KuVm4tP+/7q1rGgNqicHq...", + "body": "Test message.", + "attributes": { + "ApproximateReceiveCount": "1", + "SentTimestamp": "1545082650636", + "SenderId": "AIDAIENQZJOLO23YVJ4VO", + "ApproximateFirstReceiveTimestamp": "1545082650649" + }, + "messageAttributes": {}, + "md5OfBody": "e4e68fb7bd0e697a0ae8f1bb342846b3", + "eventSource": "aws:sqs", + "eventSourceArn": "arn:aws:sqs:us-east-2:123456789012:my-queue", + "awsRegion": "us-east-2" + }, + { + "messageId": "2e1424d4-f796-459a-8184-9c92662be6d18", + "receiptHandle": "AQEBzWwaftRI0KuVm4tP+/7q1rGgNqicHq...", + "body": "Test message.", + "attributes": { + "ApproximateReceiveCount": "1", + "SentTimestamp": "1545082650636", + "SenderId": "AIDAIENQZJOLO23YVJ4VO", + "ApproximateFirstReceiveTimestamp": "1545082650649" + }, + "messageAttributes": {}, + "md5OfBody": "e4e68fb7bd0e697a0ae8f1bb342846b3", + "eventSource": "aws:sqs", + "eventSourceArn": "arn:aws:sqs:us-east-2:123456789012:my-queue", + "awsRegion": "us-east-2" + }, + { + "messageId": "2e1424d4-f796-459a-8184-9c92662be6d19", + "receiptHandle": "AQEBzWwaftRI0KuVm4tP+/7q1rGgNqicHq...", + "body": "Test message.", + "attributes": { + "ApproximateReceiveCount": "1", + "SentTimestamp": "1545082650636", + "SenderId": "AIDAIENQZJOLO23YVJ4VO", + "ApproximateFirstReceiveTimestamp": "1545082650649" + }, + "messageAttributes": {}, + "md5OfBody": "e4e68fb7bd0e697a0ae8f1bb342846b3", + "eventSource": "aws:sqs", + "eventSourceArn": "arn:aws:sqs:us-east-2:123456789012:my-queue", + "awsRegion": "us-east-2" + }, + { + "messageId": "2e1424d4-f796-459a-8184-9c92662be6d20", + "receiptHandle": "AQEBzWwaftRI0KuVm4tP+/7q1rGgNqicHq...", + "body": "Test message.", + "attributes": { + "ApproximateReceiveCount": "1", + "SentTimestamp": "1545082650636", + "SenderId": "AIDAIENQZJOLO23YVJ4VO", + "ApproximateFirstReceiveTimestamp": "1545082650649" + }, + "messageAttributes": {}, + "md5OfBody": "e4e68fb7bd0e697a0ae8f1bb342846b3", + "eventSource": "aws:sqs", + "eventSourceArn": "arn:aws:sqs:us-east-2:123456789012:my-queue", + "awsRegion": "us-east-2" + }, + { + "messageId": "2e1424d4-f796-459a-8184-9c92662be6d21", + "receiptHandle": "AQEBzWwaftRI0KuVm4tP+/7q1rGgNqicHq...", + "body": "Test message.", + "attributes": { + "ApproximateReceiveCount": "1", + "SentTimestamp": "1545082650636", + "SenderId": "AIDAIENQZJOLO23YVJ4VO", + "ApproximateFirstReceiveTimestamp": "1545082650649" + }, + "messageAttributes": {}, + "md5OfBody": "e4e68fb7bd0e697a0ae8f1bb342846b3", + "eventSource": "aws:sqs", + "eventSourceArn": "arn:aws:sqs:us-east-2:123456789012:my-queue", + "awsRegion": "us-east-2" + }, + { + "messageId": "2e1424d4-f796-459a-8184-9c92662be6d22", + "receiptHandle": "AQEBzWwaftRI0KuVm4tP+/7q1rGgNqicHq...", + "body": "Test message.", + "attributes": { + "ApproximateReceiveCount": "1", + "SentTimestamp": "1545082650636", + "SenderId": "AIDAIENQZJOLO23YVJ4VO", + "ApproximateFirstReceiveTimestamp": "1545082650649" + }, + "messageAttributes": {}, + "md5OfBody": "e4e68fb7bd0e697a0ae8f1bb342846b3", + "eventSource": "aws:sqs", + "eventSourceArn": "arn:aws:sqs:us-east-2:123456789012:my-queue", + "awsRegion": "us-east-2" + }, + { + "messageId": "2e1424d4-f796-459a-8184-9c92662be6d23", + "receiptHandle": "AQEBzWwaftRI0KuVm4tP+/7q1rGgNqicHq...", + "body": "Test message.", + "attributes": { + "ApproximateReceiveCount": "1", + "SentTimestamp": "1545082650636", + "SenderId": "AIDAIENQZJOLO23YVJ4VO", + "ApproximateFirstReceiveTimestamp": "1545082650649" + }, + "messageAttributes": {}, + "md5OfBody": "e4e68fb7bd0e697a0ae8f1bb342846b3", + "eventSource": "aws:sqs", + "eventSourceArn": "arn:aws:sqs:us-east-2:123456789012:my-queue", + "awsRegion": "us-east-2" + }, + { + "messageId": "2e1424d4-f796-459a-8184-9c92662be6d24", + "receiptHandle": "AQEBzWwaftRI0KuVm4tP+/7q1rGgNqicHq...", + "body": "Test message.", + "attributes": { + "ApproximateReceiveCount": "1", + "SentTimestamp": "1545082650636", + "SenderId": "AIDAIENQZJOLO23YVJ4VO", + "ApproximateFirstReceiveTimestamp": "1545082650649" + }, + "messageAttributes": {}, + "md5OfBody": "e4e68fb7bd0e697a0ae8f1bb342846b3", + "eventSource": "aws:sqs", + "eventSourceArn": "arn:aws:sqs:us-east-2:123456789012:my-queue", + "awsRegion": "us-east-2" + }, + { + "messageId": "2e1424d4-f796-459a-8184-9c92662be6d25", + "receiptHandle": "AQEBzWwaftRI0KuVm4tP+/7q1rGgNqicHq...", + "body": "Test message.", + "attributes": { + "ApproximateReceiveCount": "1", + "SentTimestamp": "1545082650636", + "SenderId": "AIDAIENQZJOLO23YVJ4VO", + "ApproximateFirstReceiveTimestamp": "1545082650649" + }, + "messageAttributes": {}, + "md5OfBody": "e4e68fb7bd0e697a0ae8f1bb342846b3", + "eventSource": "aws:sqs", + "eventSourceArn": "arn:aws:sqs:us-east-2:123456789012:my-queue", + "awsRegion": "us-east-2" + }, + { + "messageId": "2e1424d4-f796-459a-8184-9c92662be6d26", + "receiptHandle": "AQEBzWwaftRI0KuVm4tP+/7q1rGgNqicHq...", + "body": "Test message.", + "attributes": { + "ApproximateReceiveCount": "1", + "SentTimestamp": "1545082650636", + "SenderId": "AIDAIENQZJOLO23YVJ4VO", + "ApproximateFirstReceiveTimestamp": "1545082650649" + }, + "messageAttributes": {}, + "md5OfBody": "e4e68fb7bd0e697a0ae8f1bb342846b3", + "eventSource": "aws:sqs", + "eventSourceArn": "arn:aws:sqs:us-east-2:123456789012:my-queue", + "awsRegion": "us-east-2" + }, + { + "messageId": "2e1424d4-f796-459a-8184-9c92662be6d27", + "receiptHandle": "AQEBzWwaftRI0KuVm4tP+/7q1rGgNqicHq...", + "body": "Test message.", + "attributes": { + "ApproximateReceiveCount": "1", + "SentTimestamp": "1545082650636", + "SenderId": "AIDAIENQZJOLO23YVJ4VO", + "ApproximateFirstReceiveTimestamp": "1545082650649" + }, + "messageAttributes": {}, + "md5OfBody": "e4e68fb7bd0e697a0ae8f1bb342846b3", + "eventSource": "aws:sqs", + "eventSourceArn": "arn:aws:sqs:us-east-2:123456789012:my-queue", + "awsRegion": "us-east-2" + } + ] +} \ No newline at end of file