I am writing a SAM template for a business application that, among other things, processes device status updates.
Users post status updates to the API Gateway that, in turn, suitably sets the destSQS
message attribute and publishes such requests to an SNS topic.
Several SQS queues are subscribed to the topic and messages are routed depending on the value of destSQS
. The following is the AWS::SNS::Subscription
resource definition for the SQS queue of interest for this question.
StatusUpdatesQueueSubscription: # accept msg iff destSQS is "StatusUpdates"
Type: AWS::SNS::Subscription
Properties:
Endpoint: !Join [ "-", [ !Sub "arn:aws:sqs:${AWS::Region}:${AWS::AccountId}:${AWS::StackName}", !Ref StatusUpdatesQueueName ] ]
Protocol: sqs
FilterPolicy:
destSQS:
- "StatusUpdate"
RawMessageDelivery: True
TopicArn: !Ref DispatcherSNSTopic
So far everything works with "simple" (i.e., non-FIFO) SNS/SQS. The following is the relevant section of the current OpenAPI (3.0.0) configuration embedded in the SAM template.
/devices/{device_id}/status:
post:
parameters:
- in: path
name: device_id
description: String ID of a device
required: true
schema:
type: string
description: Device unique identifier
security:
- ApiKeyAuth: [ ]
requestBody:
description: A status update for a device
required: true
content:
application/json:
schema:
type: object
responses:
"202":
description: Accepted
x-amazon-apigateway-integration:
type: "aws"
httpMethod: "POST"
uri: !Sub "arn:aws:apigateway:${AWS::Region}:sns:action/Publish"
credentials: !GetAtt DispatcherSNSTopicAPIRole.Arn
requestParameters:
integration.request.querystring.Message: "method.request.body"
integration.request.querystring.TopicArn: !Sub "'${DispatcherSNSTopic}'"
integration.request.querystring.MessageAttributes.entry.1.Name: "'destSQS'"
integration.request.querystring.MessageAttributes.entry.1.Value.DataType: "'String'"
integration.request.querystring.MessageAttributes.entry.1.Value.StringValue: "'StatusUpdate'"
responses:
default:
statusCode: 202
Now, I want to enrich this configuration to group messages by device_id (so that status updates for the same device will be processed in order).
I've already modified the template Resources
section so that SQS queues and the topic are FIFO and tried to add the following mapping:
integration.request.querystring.MessageAttributes.entry.2.Name: "MessageGroupId"
integration.request.querystring.MessageAttributes.entry.2.Value.DataType: "'String'"
integration.request.querystring.MessageAttributes.entry.2.Value.StringValue: method.request.path.device_id
but I get the following error:
Resource handler returned message: "Errors found during import:
Unable to put integration on 'POST' for resource at path '/devices/{device_id}/status': Invalid mapping expression specified: Validation Result: warnings : [], errors : [Invalid mapping expression specified: MessageGroupId]
What am I missing?
After lots of searches and attempts, I've found the solution. Perhaps sharing is useful for someone in the future.
MessageGroupId
has to be set as a child of querystring
and not as a MessageAttribute
, as follows:integration.request.querystring.MessageGroupId: "method.request.path.device_id"
integration.request.querystring.MessageAttributes.entry.2.Name: "'MyAttributeName'"