1
1
package software .amazon .lambda .powertools .sqs ;
2
2
3
3
import java .io .IOException ;
4
+ import java .util .Collection ;
4
5
import java .util .HashMap ;
5
6
import java .util .List ;
6
7
import java .util .function .Consumer ;
7
-
8
+ import java . util . function . Function ;
8
9
import com .amazonaws .services .lambda .runtime .events .SQSEvent ;
9
10
import com .fasterxml .jackson .databind .ObjectMapper ;
10
11
import org .assertj .core .api .Assertions ;
18
19
import software .amazon .awssdk .services .sqs .model .GetQueueAttributesRequest ;
19
20
import software .amazon .awssdk .services .sqs .model .GetQueueAttributesResponse ;
20
21
import software .amazon .awssdk .services .sqs .model .QueueAttributeName ;
22
+ import software .amazon .awssdk .services .sqs .model .SendMessageBatchRequest ;
23
+ import software .amazon .awssdk .services .sqs .model .SendMessageBatchRequestEntry ;
21
24
22
25
import static com .amazonaws .services .lambda .runtime .events .SQSEvent .SQSMessage ;
26
+ import static org .assertj .core .api .Assertions .*;
23
27
import static org .assertj .core .api .Assertions .assertThat ;
24
28
import static org .assertj .core .api .Assertions .assertThatExceptionOfType ;
25
29
import static org .mockito .ArgumentMatchers .any ;
@@ -236,10 +240,10 @@ void shouldBatchProcessAndMoveNonRetryableExceptionToDlq() {
236
240
return "Success" ;
237
241
}, IllegalStateException .class , IllegalArgumentException .class );
238
242
239
- Assertions . assertThat (batchProcessor )
243
+ assertThat (batchProcessor )
240
244
.hasSize (1 );
241
245
242
- verify (sqsClient ).sendMessageBatch (any (Consumer .class ));
246
+ verify (sqsClient ).sendMessageBatch (any (SendMessageBatchRequest .class ));
243
247
}
244
248
245
249
@ Test
@@ -265,13 +269,84 @@ void shouldBatchProcessAndDeleteNonRetryableException() {
265
269
return "Success" ;
266
270
}, true , IllegalStateException .class , IllegalArgumentException .class );
267
271
268
- Assertions . assertThat (batchProcessor )
272
+ assertThat (batchProcessor )
269
273
.hasSize (1 );
270
274
271
- verify (sqsClient , times (0 )).sendMessageBatch (any (Consumer .class ));
275
+ verify (sqsClient , times (0 )).sendMessageBatch (any (SendMessageBatchRequest .class ));
272
276
verify (sqsClient ).deleteMessageBatch (any (DeleteMessageBatchRequest .class ));
273
277
}
274
278
279
+ @ Test
280
+ void shouldDeleteSuccessfulMessageInBatchesOfT10orLess () throws IOException {
281
+ SQSEvent batch25Message = MAPPER .readValue (this .getClass ().getResource ("/sampleSqsBatchEventBatchSize25.json" ), SQSEvent .class );
282
+
283
+ assertThatExceptionOfType (SQSBatchProcessingException .class )
284
+ .isThrownBy (() -> batchProcessor (batch25Message , FailureSampleInnerSqsHandler .class ))
285
+ .satisfies (e -> {
286
+
287
+ assertThat (e .successMessageReturnValues ())
288
+ .hasSize (24 )
289
+ .contains ("Success" );
290
+
291
+ assertThat (e .getFailures ())
292
+ .hasSize (1 )
293
+ .extracting ("messageId" )
294
+ .contains ("2e1424d4-f796-459a-8184-9c92662be6da" );
295
+
296
+ assertThat (e .getExceptions ())
297
+ .hasSize (1 )
298
+ .extracting ("detailMessage" )
299
+ .contains ("Failed processing" );
300
+ });
301
+
302
+ ArgumentCaptor <DeleteMessageBatchRequest > captor = ArgumentCaptor .forClass (DeleteMessageBatchRequest .class );
303
+
304
+ verify (sqsClient , times (3 )).deleteMessageBatch (captor .capture ());
305
+
306
+ assertThat (captor .getAllValues ())
307
+ .hasSize (3 )
308
+ .flatMap (DeleteMessageBatchRequest ::entries )
309
+ .hasSize (24 );
310
+ }
311
+
312
+ @ Test
313
+ void shouldBatchProcessAndMoveNonRetryableExceptionToDlqInBatchesOfT10orLess () throws IOException {
314
+ SQSEvent batch25Message = MAPPER .readValue (this .getClass ().getResource ("/sampleSqsBatchEventBatchSize25.json" ), SQSEvent .class );
315
+
316
+ HashMap <QueueAttributeName , String > attributes = new HashMap <>();
317
+
318
+ attributes .put (QueueAttributeName .REDRIVE_POLICY , "{\n " +
319
+ " \" deadLetterTargetArn\" : \" arn:aws:sqs:us-east-2:123456789012:retry-queue\" ,\n " +
320
+ " \" maxReceiveCount\" : 2\n " +
321
+ "}" );
322
+
323
+ when (sqsClient .getQueueAttributes (any (GetQueueAttributesRequest .class ))).thenReturn (GetQueueAttributesResponse .builder ()
324
+ .attributes (attributes )
325
+ .build ());
326
+
327
+ List <String > batchProcessor = batchProcessor (batch25Message , (message ) -> {
328
+ if ("2e1424d4-f796-459a-8184-9c92662be6da" .equals (message .getMessageId ())) {
329
+ interactionClient .listQueues ();
330
+ return "Success" ;
331
+ }
332
+
333
+ throw new IllegalStateException ("Failed processing" );
334
+ }, IllegalStateException .class , IllegalArgumentException .class );
335
+
336
+ assertThat (batchProcessor )
337
+ .hasSize (1 );
338
+
339
+ ArgumentCaptor <SendMessageBatchRequest > captor = ArgumentCaptor .forClass (SendMessageBatchRequest .class );
340
+
341
+
342
+ verify (sqsClient , times (3 )).sendMessageBatch (captor .capture ());
343
+
344
+ assertThat (captor .getAllValues ())
345
+ .hasSize (3 )
346
+ .flatMap (SendMessageBatchRequest ::entries )
347
+ .hasSize (24 );
348
+ }
349
+
275
350
public class FailureSampleInnerSqsHandler implements SqsMessageHandler <String > {
276
351
@ Override
277
352
public String process (SQSEvent .SQSMessage message ) {
0 commit comments