I have a couple of Lambdas that were invoked via an API Gateway integration route. In a nutshell, this Lambda will create a session in a dynamodb table and add the first player/connection to the table. When the second player has joined and been added to the table, then the first player should be sent a response indicating that player 2 has joined.
This all worked perfectly fine before I migrated from AWS SDK v2 to v3. In v2, I used the ApiGatewayManagementApi and it was working perfectly. I’ve since then changed to using ApiGatewayManagementApiClient instead, but neither active client receives any response from API Gateway.
There are no errors being thrown whatsoever, making it hard to identify the issue.
import {
DynamoDBClient,
PutItemCommand,
UpdateItemCommand,
} from "@aws-sdk/client-dynamodb";
import { ScanCommand } from "@aws-sdk/lib-dynamodb";
import {
ApiGatewayManagementApiClient,
PostToConnectionCommand,
} from "@aws-sdk/client-apigatewaymanagementapi";
const dynamoClient = new DynamoDBClient({ region: "eu-west-2" });
let send = undefined;
const environmentName = process.env.Environment;
const gameName = process.env.GameName;
const TABLE_NAME = `${environmentName}-${gameName}-GameSessionsTable`;
const PLAYING_OP = "2";
export const handler = (event, context, callback) => {
const connectionId = event.requestContext.connectionId;
console.log("Connect event received: %j", event);
init(event);
addConnectionId(connectionId).then(() => {
callback(null, {
statusCode: 200,
});
});
};
function init(event) {
const apiGatewayClient = new ApiGatewayManagementApiClient({
endpoint:
"https://" +
event.requestContext.domainName +
"/" +
event.requestContext.stage,
});
send = async (connectionId, data) => {
const input = {
Data: data,
ConnectionId: connectionId,
};
try {
await apiGatewayClient.send(new PostToConnectionCommand(input));
} catch (error) {
console.log(error);
}
};
}
const scanParams = {
TableName: TABLE_NAME,
FilterExpression: "#p2 = :empty and #status <> :closed",
ExpressionAttributeNames: {
"#p2": "player2",
"#status": "gameStatus",
},
ExpressionAttributeValues: {
":empty": "empty",
":closed": "closed",
},
};
const scanSessionTable = new ScanCommand(scanParams);
function getAvailableGameSession() {
return dynamoClient.send(scanSessionTable);
}
function addConnectionId(connectionId) {
return getAvailableGameSession().then((data) => {
console.log("Game session data: %j", data);
if (data && data.Count < 1) {
// Create new game session.
console.log("No sessions are available to join, creating a new session.");
const createSessionParams = {
TableName: TABLE_NAME,
Item: {
uuid: { S: Date.now() + "" },
player1: { S: connectionId },
player2: { S: "empty" },
},
};
const createSession = new PutItemCommand(createSessionParams);
return dynamoClient.send(createSession);
} else {
// Join existing game session.
console.log("Available session found, adding user as player 2.");
const joinSessionParams = {
TableName: TABLE_NAME,
Key: {
uuid: { S: data.Items[0].uuid },
},
UpdateExpression: "set player2 = :p2",
ExpressionAttributeValues: {
":p2": { S: connectionId },
},
};
const joinSession = new UpdateItemCommand(joinSessionParams);
return dynamoClient
.send(joinSession)
.then(() => {
console.log(
"Hit the then statement, player 1 ID is: " + data.Items[0].player1
);
console.log(
"message to send:" +
JSON.stringify({ uuid: data.Items[0].uuid, opcode: PLAYING_OP })
);
// Inform player 1 that player 2 has joined to initiate the start of game.
send(
data.Items[0].player1,
JSON.stringify({ uuid: data.Items[0].uuid, opcode: PLAYING_OP })
);
})
.catch((error) => {
console.error(error);
});
}
});
}