thank you in advance for stopping by 🙂
Something weird is going on with my API Gateway – Lambda – DynamoDB combo: I am inserting items using a PutCommand
try {
return await documentClient.send(new PutCommand({
TableName: process.env.TABLE_NAME,
Item: {
'PK': '#LEADERBOARDS',
'SK': `LEADERBOARD#${requestBody.leaderboard_id}`,
'leaderboard_display_name': requestBody.leaderboard_display_name,
'participant_type': requestBody.participant_type,
'active_leaderboard': requestBody.active_leaderboard,
'tournaments': requestBody.tournaments,
'associated_tournaments': new Set(requestBody.associated_tournaments)
},
ConditionExpression: 'attribute_not_exists(PK) AND attribute_not_exists(SK)',
ReturnConsumedCapacity: 'TOTAL'
}))
} catch (error) {
return error
}
Everything works as expected, except for the number set ‘associated_tournaments’, which when I try to retrieve via a GetCommand:
try {
return await documentClient.send(new GetCommand({
TableName: process.env.TABLE_NAME,
Key: {
'PK': '#LEADERBOARDS',
'SK': `LEADERBOARD#${leaderboardName}`
},
ReturnConsumedCapacity: 'TOTAL'
}))
} catch (error) {
return error
}
it returns an empty object ‘{}’ to the caller (using curl, or postman), however from the Dynamo UI and by querying via the CLI I can see the data is actually present in the attribute and item.
This is the CLI command I’m using:
aws dynamodb get-item --table-name STGLeaderboards --key '{"PK": {"S": "#LEADERBOARDS"}, "SK": {"S": "LEADERBOARD#LeaderboardPM"}}' --return-consumed-capacity TOTAL --profile qlash --region eu-central-1
which returns the numbers in the set.
The curl command hitting the API Gateway endpoint:
curl 'https://api.stg.tournaments.qlash.gg/admin/leaderboard/LeaderboardPM'
which triggers the GetCommand I shared above via this handler:
export const handler = async (event) => {
switch (event.routeKey) {
case 'POST /admin/leaderboard':
return await createLeaderboard(JSON.parse(event.body))
case 'GET /admin/leaderboards':
return await getLeaderboards()
case 'GET /admin/leaderboard/{leaderboard_name}':
return await getLeaderboard(event.pathParameters.leaderboard_name)
case 'PATCH /admin/leaderboard/{leaderboard_name}':
return await updateLeaderboard(event.pathParameters.leaderboard_name, JSON.parse(event.body))
case 'DELETE /admin/leaderboard/{leaderboard_name}':
return await deleteLeaderboard(event.pathParameters.leaderboard_name)
default:
return {
statusCode: 404,
body: JSON.stringify({'message': 'No matching path'}),
}
}
}
Here is the output of the curl command:
{
"$metadata": {
"httpStatusCode": 200,
"requestId": "CDDA7KIQSDR7JE4PA06S6AB3HNVV4KQNSO5AEMVJF66Q9ASUAAJG",
"attempts": 1,
"totalRetryDelay": 0
},
"ConsumedCapacity": {
"CapacityUnits": 0.5,
"TableName": "STGLeaderboards"
},
"Item": {
"SK": "LEADERBOARD#LeaderboardPM",
"associated_tournaments": {},
"active_leaderboard": true,
"leaderboard_display_name": "This Leaderboards is AWESOME",
"participant_type": "SOLO"
}
}
as you can see it returns an empty set, but from the dynamodb dashboard I can see two associated tournaments in the form {7121, 7224}
What is going on here? :/ Am I missing something about converting back the Set in some way?
Thank you in advance, and have a nice day!
Ettore
2
Answers
From the information you provided, it seems as though you are using a response mapping template in API Gateway. I suggest either you don’t map the response and let the client retrieve all of the item, or you return the entire item payload, and drop the metadata.
I bumped into the same issue recently. I solved it manipulating the response, converting the set back into an array in the response, and now it is working as expected.
Here is how you’d do it:
(for a single item)
(and for a scan/query)
I know it cloud be a hit in terms of performance for a response with many items, but I don’t know what to say… I think there’s something funky going on with the API Gateway… AWS FIX YOUR **** LMAO
Jokes aside, hope this helps 🙂