Hi there, I’m new to serverless and not too hot on AWS VPCs either so forgive me!!!
I’m trying to create a system that is triggered by an image landing in an S3 bucket, this fires a Lambda function that requests image labels from Rekognition and sends those labels in an SNS message. The SNS message then triggers a separate Lambda function that will insert the image details into a Postgres DB. However, my db function is just timing out - perhaps due to security groups? Here’s my code:
serverless.yml
service: client-image
frameworkVersion: ">=1.10.0"
provider:
name: aws
runtime: nodejs6.10
memorySize: 512
timeout: 10
stage: dev
region: eu-west-1
iamRoleStatements:
- Effect: Allow
Action:
- s3:*
Resource: "*"
- Effect: "Allow"
Action:
- "rekognition:*"
Resource: "*"
- Effect: "Allow"
Resource: "*"
Action:
- "sns:*"
functions:
imageAnalysis:
handler: handler.imageAnalysis
events:
- s3:
bucket: client
dbInsert:
handler: handler.dbInsertImage
events:
- sns: imageDispatcher
vpc:
securityGroupIds:
- "sg-********"
subnetIds:
- "subnet-********"
- "subnet-********"
- "subnet-********"
I set the securityGroupIds and subnetIds to match those of my RDS instance.
handler.json
'use strict';
const AWS = require('aws-sdk');
const ImageAnalyser = require('./lib/imageAnalyser');
const Pool = require('pg-pool')
const pool = new Pool({
host: '********',
database: '*****',
user: '*****',
password: '********',
port: 5432,
max: 1,
min: 0,
idleTimeoutMillis: 300000,
connectionTimeoutMillis: 1000
});
/**
Analyse an image on S3 using bucket and image name
*/
module.exports.imageAnalysis = (event, context, callback) => {
console.log(JSON.stringify(event));
console.log("Region:" + event.Records[0].awsRegion);
console.log("Bucket name:" + event.Records[0].s3.bucket.name);
console.log("Image name:" + event.Records[0].s3.object.key);
console.log(event.Records[0].s3.object);
const region = event.Records[0].awsRegion;
const bucket = event.Records[0].s3.bucket.name;
const image = event.Records[0].s3.object.key;
const s3Config = {
bucket: event.Records[0].s3.bucket.name,
imageName: event.Records[0].s3.object.key,
};
const sns = new AWS.SNS();
const accountId = '248221388880';
return ImageAnalyser
.getImageLabels(s3Config)
.then((labels) => {
const labelsJson = JSON.stringify(labels);
const params = {
Subject: 'image|new',
Message: '{' +
'"region" : "'+ region +'", ' +
'"bucket" : "'+ bucket +'", ' +
'"image" : "'+ image +'", ' +
'"labels" : ' + labelsJson +
'}',
TopicArn: `arn:aws:sns:eu-west-1:${accountId}:imageDispatcher`
};
sns.publish(params, (error, data) => {
if (error) {
callback(error);
}
callback(null, { message: 'Message successfully published to SNS topic "dispatcher"', event });
});
const response = {
statusCode: 200,
body: JSON.stringify({ Labels: labels }),
};
callback(null, response);
})
.catch((error) => {
callback(null, {
statusCode: error.statusCode || 501,
headers: { 'Content-Type': 'text/plain' },
body: error.message || 'Internal server error',
});
});
};
module.exports.dbInsertImage = (event, context, callback) => {
console.log(JSON.stringify(event, null, 2));
console.log(event.Records[0].Sns.Subject);
console.log(event.Records[0].Sns.Message);
context.callbackWaitsForEmptyEventLoop = false;
let client;
pool.connect().then(c => {
client = c;
return client.query("select 'stuff'");
}).then(res => {
client.release();
const response = {
"isBase64Encoded": false,
"statusCode": 200,
"body": JSON.stringify(res.rows)
}
callback(null, response);
}).catch(error => {
console.log("ERROR", error);
const response = {
"isBase64Encoded": false,
"statusCode": 500,
"body": JSON.stringify(error)
}
callback(null, response);
});
};
Cloudwatch gives this error:
2017-10-25T16:56:54.104Z 7b626e7e-b9a5-11e7-b485-5d8728ce0c70 ERROR Error: Connection terminiated due to connection timeout
at Connection.con.once (/var/task/node_modules/pg/lib/client.js:179:21)
at Connection.g (events.js:292:16)
at emitNone (events.js:86:13)
at Connection.emit (events.js:185:7)
at Socket. (/var/task/node_modules/pg/lib/connection.js:75:10)
at emitOne (events.js:96:13)
at Socket.emit (events.js:188:7)
at TCP._handle.close [as _onclose] (net.js:497:12)
Any ideas? Thank you