Skip to content

Commit 6851776

Browse files
committed
Increase coverage
1 parent fa497ed commit 6851776

File tree

2 files changed

+61
-8
lines changed

2 files changed

+61
-8
lines changed

powertools-sqs/src/main/java/software/amazon/lambda/powertools/sqs/SqsUtils.java

+17-8
Original file line numberDiff line numberDiff line change
@@ -496,9 +496,14 @@ public static <R> List<R> batchProcessor(final SQSEvent event,
496496
}
497497

498498
BatchContext batchContext = new BatchContext(client);
499-
Queue<SQSMessage> messagesToProcess = new LinkedList<>(event.getRecords());
500-
while (!messagesToProcess.isEmpty()) {
501-
SQSMessage message = messagesToProcess.remove();
499+
int offset = 0;
500+
while (offset < event.getRecords().size()) {
501+
// Get the current message and advance to the next. Doing this here
502+
// makes it easier for us to know where we are up to if we have to
503+
// break out of here early.
504+
SQSMessage message = event.getRecords().get(offset);
505+
offset++;
506+
502507
// If the batch hasn't failed, try process the message
503508
try {
504509
handlerReturn.add(handler.process(message));
@@ -525,11 +530,15 @@ public static <R> List<R> batchProcessor(final SQSEvent event,
525530

526531
// If we have a FIFO batch failure, unprocessed messages will remain on the queue
527532
// past the failed message. We have to add these to the errors
528-
messagesToProcess.forEach(message -> {
529-
LOG.info("Skipping message {} as another message with a message group failed in this batch",
530-
message.getMessageId());
531-
batchContext.addFailure(message, new SkippedMessageDueToFailedBatchException());
532-
});
533+
if (offset < event.getRecords().size()) {
534+
event.getRecords()
535+
.subList(offset, event.getRecords().size())
536+
.forEach(message -> {
537+
LOG.info("Skipping message {} as another message with a message group failed in this batch",
538+
message.getMessageId());
539+
batchContext.addFailure(message, new SkippedMessageDueToFailedBatchException());
540+
});
541+
}
533542

534543
batchContext.processSuccessAndHandleFailed(handlerReturn, suppressException, deleteNonRetryableMessageFromQueue, nonRetryableExceptions);
535544
return handlerReturn;

powertools-sqs/src/test/java/software/amazon/lambda/powertools/sqs/SqsUtilsFifoBatchProcessorTest.java

+44
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,50 @@ public void processWholeBatch() {
7171
assertThat(results.size()).isEqualTo(3);
7272
}
7373

74+
/**
75+
* Check that a failure in the middle of the batch:
76+
* - deletes the successful message explicitly from SQS
77+
* - marks the failed and subsequent message as failed
78+
* - does not delete the failed or subsequent message
79+
*/
80+
@Test
81+
public void singleFailureInMiddleOfBatch() {
82+
// Arrange
83+
Mockito.when(sqsClient.deleteMessageBatch(deleteMessageBatchCaptor.capture())).thenReturn(DeleteMessageBatchResponse
84+
.builder().build());
85+
86+
// Act
87+
AtomicInteger processedCount = new AtomicInteger();
88+
assertThatExceptionOfType(SQSBatchProcessingException.class)
89+
.isThrownBy(() -> batchProcessor(sqsBatchEvent, false, (message) -> {
90+
int value = processedCount.getAndIncrement();
91+
if (value == 1) {
92+
throw new RuntimeException("Whoops");
93+
}
94+
return true;
95+
}))
96+
97+
// Assert
98+
.isInstanceOf(SQSBatchProcessingException.class)
99+
.satisfies(e -> {
100+
List<SQSEvent.SQSMessage> failures = ((SQSBatchProcessingException)e).getFailures();
101+
assertThat(failures.size()).isEqualTo(2);
102+
List<String> failureIds = failures.stream()
103+
.map(SQSEvent.SQSMessage::getMessageId)
104+
.collect(Collectors.toList());
105+
assertThat(failureIds).contains(sqsBatchEvent.getRecords().get(1).getMessageId());
106+
assertThat(failureIds).contains(sqsBatchEvent.getRecords().get(2).getMessageId());
107+
});
108+
109+
DeleteMessageBatchRequest deleteRequest = deleteMessageBatchCaptor.getValue();
110+
List<String> messageIds = deleteRequest.entries().stream()
111+
.map(DeleteMessageBatchRequestEntry::id)
112+
.collect(Collectors.toList());
113+
assertThat(deleteRequest.entries().size()).isEqualTo(1);
114+
assertThat(messageIds.contains(sqsBatchEvent.getRecords().get(0).getMessageId())).isTrue();
115+
116+
}
117+
74118
@Test
75119
public void singleFailureAtEndOfBatch() {
76120

0 commit comments

Comments
 (0)