I am using AWS CDK for defining AWS infrastructure.
I have database-stack
that defines RDS(MySQL) instance and have set up AWSCustomResource like below to run table-creation.sql
when the Database instance is deployed for the first time.
Everytime, the instance is launched, the table is not created in the instance showing error:
2023-06-11T14:23:19.813Z 8155569d-cd7e-4fc4-833c-db7da6afbf3d INFO Error: Connection lost: The server closed the connection.
at Protocol.end (/var/task/index.js:9350:17)
at Socket.<anonymous> (/var/task/index.js:9907:32)
at Socket.<anonymous> (/var/task/index.js:10233:14)
at Socket.emit (node:events:525:35)
at Socket.emit (node:domain:489:12)
at endReadableNT (node:internal/streams/readable:1358:12)
at processTicksAndRejections (node:internal/process/task_queues:83:21)
--------------------
at Protocol._enqueue (/var/task/index.js:9374:52)
at Protocol.handshake (/var/task/index.js:9304:27)
at PoolConnection.connect (/var/task/index.js:9925:22)
at Pool.getConnection (/var/task/index.js:10330:20)
at Pool.query (/var/task/index.js:10447:12)
at /var/task/index.js:10997:22
at new Promise (<anonymous>)
at Runtime.handler (/var/task/index.js:10996:18)
at processTicksAndRejections (node:internal/process/task_queues:96:5) {
fatal: true,
code: 'PROTOCOL_CONNECTION_LOST'
}
To solve this, I tried looking into this post which seemed relevant: nodejs mysql Error: Connection lost The server closed the connection But the solution didn't work for me and other posts as well.
Also I noticed the solutions were mostly with NodeJS without AWS Lambda functions. I tried many things and I am wondering what could be the possible problems and how to solve this issue. Any advice would be thankful.
Here are the AWS CDK defined database-stack.ts
with AWSCustomResource to run a lambda function at its creation and rds-init.ts
which is lambda function code for creating tables.
database-stack.ts
// Create Lambda Function to initialize the DB with tables and data.
const rdsLambdaFunction = new NodejsFunction(this, "rdsLambdaFN", {
entry: "./src/lambda_functions/rds-init.ts",
runtime: Runtime.NODEJS_16_X,
timeout: Duration.minutes(3), // Preventing coldstart time
functionName: "rds-init-function",
environment: {
DB_ENDPOINT_ADDRESS: dbProxy.endpoint,
DB_NAME: "vegafoliodb",
DB_SECRET_ARN: instance.secret?.secretFullArn || "", // Not Fetching Password directly but via SecretARN for security :)
},
vpc,
vpcSubnets: vpc.selectSubnets({
subnetType: ec2.SubnetType.PRIVATE_WITH_EGRESS,
}),
bundling: {
// Use Command Hooks to include table-creation.sql file in the bundle
commandHooks: {
beforeBundling(inputDir: string, outputDir: string) {
return [
`cp ${inputDir}/src/lambda_functions/table-creation.sql ${outputDir}`,
];
},
afterBundling(inputDir: string, outputDir: string) {
return [];
},
beforeInstall(inputDir: string, outputDir: string) {
return [];
},
},
externalModules: [
"aws-sdk", // No Need to include AWS SDK as we are using native aws-sdk.
],
},
securityGroups: [dbSG],
});
// Custom Resource to invoke Lambda Function on db stack creation creation
new AwsCustomResource(this, "rdsInitCustomResource", {
onCreate: {
service: "Lambda",
action: "invoke",
parameters: {
FunctionName: rdsLambdaFunction.functionArn,
InvocationType: "RequestResponse",
},
physicalResourceId: PhysicalResourceId.of(
"rdsInitCustomResource"
),
},
policy: AwsCustomResourcePolicy.fromSdkCalls({
resources: [rdsLambdaFunction.functionArn],
}),
role: customResourcerole,
});
rds-init.ts
// Custom Resource to invoke Lambda Function on db stack creation creation
new AwsCustomResource(this, "rdsInitCustomResource", {
onCreate: {
service: "Lambda",
action: "invoke",
parameters: {
FunctionName: rdsLambdaFunction.functionArn,
InvocationType: "RequestResponse",
},
physicalResourceId: PhysicalResourceId.of(
"rdsInitCustomResource"
),
},
policy: AwsCustomResourcePolicy.fromSdkCalls({
resources: [rdsLambdaFunction.functionArn],
}),
role: customResourcerole,
});