Skip to content

Commit ee12e97

Browse files
pankajagrawal16Pankaj Agrawal
and
Pankaj Agrawal
authored
docs(batch-processing): Support for moving non retryable msg to DLQ (#531)
Co-authored-by: Pankaj Agrawal <[email protected]>
1 parent 34edd49 commit ee12e97

File tree

1 file changed

+129
-6
lines changed

1 file changed

+129
-6
lines changed

docs/utilities/batch.md

Lines changed: 129 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -78,9 +78,14 @@ To install this utility, add the following dependency to your project.
7878
}
7979
```
8080

81-
**IAM Permissions**
81+
## IAM Permissions
8282

83-
This utility requires additional permissions to work as expected. Lambda functions using this utility require the `sqs:GetQueueUrl` and `sqs:DeleteMessageBatch` permission.
83+
This utility requires additional permissions to work as expected. Lambda functions using this utility require the `sqs:DeleteMessageBatch` permission.
84+
85+
If you are also using [nonRetryableExceptions](#move-non-retryable-messages-to-a-dead-letter-queue) attribute, utility will need additional permission of `sqs:GetQueueAttributes` on source SQS.
86+
It also needs `sqs:SendMessage` and `sqs:SendMessageBatch` on configured dead letter queue.
87+
88+
Refer [example project](https://github.com/aws-samples/aws-lambda-powertools-examples/blob/main/java/SqsBatchProcessing/template.yaml#L67) for policy details example.
8489

8590
## Processing messages from SQS
8691

@@ -91,7 +96,8 @@ Both have nearly the same behaviour when it comes to processing messages from th
9196
* **Entire batch has been successfully processed**, where your Lambda handler returned successfully, we will let SQS delete the batch to optimize your cost
9297
* **Entire Batch has been partially processed successfully**, where exceptions were raised within your `SqsMessageHandler` interface implementation, we will:
9398
- **1)** Delete successfully processed messages from the queue by directly calling `sqs:DeleteMessageBatch`
94-
- **2)** Raise `SQSBatchProcessingException` to ensure failed messages return to your SQS queue
99+
- **2)** if, non retryable exceptions occur, messages resulting in configured exceptions during processing will be immediately moved to the dead letter queue associated to the source SQS queue or deleted from the source SQS queue if `deleteNonRetryableMessageFromQueue` is set to `true`.
100+
- **3)** Raise `SQSBatchProcessingException` to ensure failed messages return to your SQS queue
95101

96102
The only difference is that **SqsUtils Utility API** will give you access to return from the processed messages if you need. Exception `SQSBatchProcessingException` thrown from the
97103
utility will have access to both successful and failed messaged along with failure exceptions.
@@ -110,15 +116,20 @@ When using this annotation, you need provide a class implementation of `SqsMessa
110116

111117
All records in the batch will be passed to this handler for processing, even if exceptions are thrown - Here's the behaviour after completing the batch:
112118

113-
* **Any successfully processed messages**, we will delete them from the queue via `sqs:DeleteMessageBatch`
114-
* **Any unprocessed messages detected**, we will raise `SQSBatchProcessingException` to ensure failed messages return to your SQS queue
119+
* **Any successfully processed messages**, we will delete them from the queue via `sqs:DeleteMessageBatch`.
120+
* **if, nonRetryableExceptions attribute is used**, messages resulting in configured exceptions during processing will be immediately moved to the dead letter queue associated to the source SQS queue or deleted from the source SQS queue if `deleteNonRetryableMessageFromQueue` is set to `true`.
121+
* **Any unprocessed messages detected**, we will raise `SQSBatchProcessingException` to ensure failed messages return to your SQS queue.
115122

116123
!!! warning
117124
You will not have access to the **processed messages** within the Lambda Handler - all processing logic will and should be performed by the implemented `#!java SqsMessageHandler#process()` function.
118125

119126
=== "AppSqsEvent.java"
120127

121-
```java hl_lines="3"
128+
```java hl_lines="7"
129+
import software.amazon.lambda.powertools.sqs.SqsBatch;
130+
import software.amazon.lambda.powertools.sqs.SqsMessageHandler;
131+
import software.amazon.lambda.powertools.sqs.SqsUtils;
132+
122133
public class AppSqsEvent implements RequestHandler<SQSEvent, String> {
123134
@Override
124135
@SqsBatch(SampleMessageHandler.class)
@@ -139,6 +150,39 @@ All records in the batch will be passed to this handler for processing, even if
139150
}
140151
```
141152

153+
=== "AppSqsEventWithNonRetryableExceptions.java"
154+
155+
```java hl_lines="7 21"
156+
import software.amazon.lambda.powertools.sqs.SqsBatch;
157+
import software.amazon.lambda.powertools.sqs.SqsMessageHandler;
158+
import software.amazon.lambda.powertools.sqs.SqsUtils;
159+
160+
public class AppSqsEvent implements RequestHandler<SQSEvent, String> {
161+
@Override
162+
@SqsBatch(value = SampleMessageHandler.class, nonRetryableExceptions = {IllegalArgumentException.class})
163+
public String handleRequest(SQSEvent input, Context context) {
164+
return "{\"statusCode\": 200}";
165+
}
166+
167+
public class SampleMessageHandler implements SqsMessageHandler<Object> {
168+
169+
@Override
170+
public String process(SQSMessage message) {
171+
// This will be called for each individual message from a batch
172+
// It should raise an exception if the message was not processed successfully
173+
String returnVal = doSomething(message.getBody());
174+
175+
if(/**Business validation failure**/) {
176+
throw new IllegalArgumentException("Failed business validation. No point of retrying. Move me to DLQ." + message.getMessageId());
177+
}
178+
179+
return returnVal;
180+
}
181+
}
182+
}
183+
```
184+
185+
142186
### SqsUtils Utility API
143187

144188
If you require access to the result of processed messages, you can use this utility. The result from calling **`#!java SqsUtils#batchProcessor()`** on the context manager will be a list of all the return values
@@ -248,3 +292,82 @@ If you want to disable the default behavior where `SQSBatchProcessingException`
248292
return returnValues;
249293
}
250294
```
295+
296+
## Move non retryable messages to a dead letter queue
297+
298+
If you want certain exceptions to be treated as permanent failures during batch processing, i.e. exceptions where the result of retrying will
299+
always be a failure and want these can be immediately moved to the dead letter queue associated to the source SQS queue, you can use `SqsBatch#nonRetryableExceptions()`
300+
to configure such exceptions.
301+
302+
If you want such messages to be deleted instead, set `SqsBatch#deleteNonRetryableMessageFromQueue()` to `true`. By default, its value is `false`.
303+
304+
Same capability is also provided by [SqsUtils Utility API](#sqsutils-utility-api).
305+
306+
!!! info
307+
Make sure the lambda function has required permissions needed by utility. Refer [this section](#iam-permissions).
308+
309+
=== "SqsBatch annotation"
310+
311+
```java hl_lines="7 21"
312+
import software.amazon.lambda.powertools.sqs.SqsBatch;
313+
import software.amazon.lambda.powertools.sqs.SqsMessageHandler;
314+
import software.amazon.lambda.powertools.sqs.SqsUtils;
315+
316+
public class AppSqsEvent implements RequestHandler<SQSEvent, String> {
317+
@Override
318+
@SqsBatch(value = SampleMessageHandler.class, nonRetryableExceptions = {IllegalArgumentException.class})
319+
public String handleRequest(SQSEvent input, Context context) {
320+
return "{\"statusCode\": 200}";
321+
}
322+
323+
public class SampleMessageHandler implements SqsMessageHandler<Object> {
324+
325+
@Override
326+
public String process(SQSMessage message) {
327+
// This will be called for each individual message from a batch
328+
// It should raise an exception if the message was not processed successfully
329+
String returnVal = doSomething(message.getBody());
330+
331+
if(/**Business validation failure**/) {
332+
throw new IllegalArgumentException("Failed business validation. No point of retrying. Move me to DLQ." + message.getMessageId());
333+
}
334+
335+
return returnVal;
336+
}
337+
}
338+
}
339+
```
340+
341+
=== "SqsBatch API"
342+
343+
```java hl_lines="9 23"
344+
import software.amazon.lambda.powertools.sqs.SqsBatch;
345+
import software.amazon.lambda.powertools.sqs.SqsMessageHandler;
346+
import software.amazon.lambda.powertools.sqs.SqsUtils;
347+
348+
public class AppSqsEvent implements RequestHandler<SQSEvent, String> {
349+
@Override
350+
public String handleRequest(SQSEvent input, Context context) {
351+
352+
SqsUtils.batchProcessor(input, BatchProcessor.class, IllegalArgumentException.class);
353+
354+
return "{\"statusCode\": 200}";
355+
}
356+
357+
public class SampleMessageHandler implements SqsMessageHandler<Object> {
358+
359+
@Override
360+
public String process(SQSMessage message) {
361+
// This will be called for each individual message from a batch
362+
// It should raise an exception if the message was not processed successfully
363+
String returnVal = doSomething(message.getBody());
364+
365+
if(/**Business validation failure**/) {
366+
throw new IllegalArgumentException("Failed business validation. No point of retrying. Move me to DLQ." + message.getMessageId());
367+
}
368+
369+
return returnVal;
370+
}
371+
}
372+
}
373+
```

0 commit comments

Comments
 (0)