-
Notifications
You must be signed in to change notification settings - Fork 98
Description
Use case
When a lambda is trigger by an SQS Queue, and that Queue itself is given messages from a subscription with an SNS topic, it results in multiple layers of serialization that need to be unwrapped to get to the real message body. The current implementation of Batch will only deserialize the SQS Message body, which leaves you with an SNS Message, that itself has a String body
that needt o be deserialized again.
This results in code like
public HandlerSqs() {
handler = new BatchMessageHandlerBuilder()
.withSqsBatchHandler()
.buildWithMessageHandler(this::processSNSMessage, SNSMessage.class);
}
private String processSNSMessage(SNSMessage snsMessage) {
MyInput myInput = extractDataFrom(snsMessage.getMessage()).as(MyInput.class);
return processMessage(myInput);
}
public SQSBatchResponse handleRequest(SQSEvent input, Context context) {
return handler.processBatch(input, context);
}
As well as the SNSMessage class I had to make myself due to case sensitivity that isn't accounted for in the Lambda Events classes
public class SNSMessage {
@JsonProperty("Type")
private String type;
@JsonProperty("MessageId")
private String messageId;
@JsonProperty("TopicArn")
private String topicArn;
@JsonProperty("Subject")
private String subject;
@JsonProperty("Message")
private String message;
...
}
Example of the input event from hooking up SNS->SQS->Lambda as json
{
"Records": [
{
"messageId": "dummy-message-id",
"receiptHandle": "dummy-receipt-handle",
"eventSourceARN": "arn:aws:sqs:region:account-id:dummy-queue",
"eventSource": "aws:sqs",
"awsRegion": "dummy-region",
"body": "{\"Type\": \"Notification\",\"MessageId\": \"dummy-sns-message-id\",\"TopicArn\": \"arn:aws:sns:region:account-id:dummy-topic\",\"Message\": \"{\\\"field\\\": \\\"dummy\\\", \\\"name\\\": \\\"dummy-name\\\"}\",\"Timestamp\": \"2000-01-01T00:00:00.000Z\",\"SignatureVersion\": \"1\",\"Signature\": \"dummy-signature\",\"SigningCertURL\": \"https://sns.region.amazonaws.com/dummy-cert.pem\",\"UnsubscribeURL\": \"https://sns.region.amazonaws.com/?Action=Unsubscribe&SubscriptionArn=arn:aws:sns:region:account-id:dummy-topic:dummy-subscription\"}",
"md5OfBody": "dummy-md5",
"attributes": {
"ApproximateReceiveCount": "1",
"SentTimestamp": "0000000000000",
"SenderId": "dummy-sender-id",
"ApproximateFirstReceiveTimestamp": "0000000000000"
},
"messageAttributes": {}
}
]
}
Solution/User Experience
It would be great if this was a 1 step process like the rest, maybe like:
public HandlerSqs() {
handler = new BatchMessageHandlerBuilder()
.withSnsToSqsBatchHandler()
.buildWithMessageHandler(this::processMessage, MyInput.class);
}
public SQSBatchResponse handleRequest(SQSEvent input, Context context) {
return handler.processBatch(input, context);
}
Alternative solutions
Alternatively, if the Events library included an `SNSMessage` or such, that actually could deserialize it directly, instead of maintaining a custom class for it.
Acknowledgment
- This feature request meets Powertools for AWS Lambda (Java) Tenets
- Should this be considered in other Powertools for AWS Lambda languages? i.e. Python, TypeScript, and .NET
Future readers
Please react with 👍 and your use case to help us understand customer demand.
Metadata
Metadata
Assignees
Labels
Type
Projects
Status