lambda task timed out error while using rekognition - amazon-web-services

I'm building a React native app with serverless framework using AWS services.
I created a RESTapi with lambda function (nodeJs8.10 environment) and API gateway to use rekognition services such as indexFaces, listCollection, etc. My lambda is in VPC with RDS( later I'll Aurora) to store faceID and other data.
Everything works fine except rekognition services.
When I call any rekognition services it shows Task timed out after 270.04 seconds.But it works when I call locally using serverless-offline-plugin
I attach all necessary permissions to my lambda like AmazonRekognitionFullAccess
Here is my code
index.js
app.post('/myapi', function (req, res) {
var params = {
MaxResults: 3,
};
const rekognition = aws_config(); <-- rekognition configuration
rekognition.listCollections(params, function(err, data) {
if (err) {
res.json(err.stack);
console.log(err, err.stack);
}
else{
res.json(data);
console.log(data);
}
});
});
function aws_config(){
const $options = {
'region' : 'ap-southeast-2',
'version' : '2016-06-27',
'accessKeyId ' : config.ENV.aws_key,
'secretAccessKey ' : config.ENV.aws_secret,
};
return new AWS.Rekognition($options);
}
How to solve this timeout error as it doesn't show any error on CloudWatch logs?

Related

Problems accessing storage from Lambda function in Amplify

What I want to do?
I want to create REST API that returns data from my DynamoDB table which is being created by GraphQL model.
What I've done
Create GraphQL model
type Public #model {
id: ID!
name: String!
}
Create REST API with Lambda Function with access to my PublicTable
$ amplify add api
? Please select from one of the below mentioned services: REST
? Provide a friendly name for your resource to be used as a label for this category in the project: rest
? Provide a path (e.g., /book/{isbn}): /items
? Choose a Lambda source Create a new Lambda function
? Provide an AWS Lambda function name: listPublic
? Choose the runtime that you want to use: NodeJS
? Choose the function template that you want to use: Hello World
Available advanced settings:
- Resource access permissions
- Scheduled recurring invocation
- Lambda layers configuration
? Do you want to configure advanced settings? Yes
? Do you want to access other resources in this project from your Lambda function? Yes
? Select the category storage
? Storage has 8 resources in this project. Select the one you would like your Lambda to access Public:#model(appsync)
? Select the operations you want to permit for Public:#model(appsync) create, read, update, delete
You can access the following resource attributes as environment variables from your Lambda function
API_MYPROJECT_GRAPHQLAPIIDOUTPUT
API_MYPROJECT_PUBLICTABLE_ARN
API_MYPROJECT_PUBLICTABLE_NAME
ENV
REGION
? Do you want to invoke this function on a recurring schedule? No
? Do you want to configure Lambda layers for this function? No
? Do you want to edit the local lambda function now? No
Successfully added resource listPublic locally.
Next steps:
Check out sample function code generated in <project-dir>/amplify/backend/function/listPublic/src
"amplify function build" builds all of your functions currently in the project
"amplify mock function <functionName>" runs your function locally
"amplify push" builds all of your local backend resources and provisions them in the cloud
"amplify publish" builds all of your local backend and front-end resources (if you added hosting category) and provisions them in the cloud
Succesfully added the Lambda function locally
? Restrict API access No
? Do you want to add another path? No
Successfully added resource rest locally
Edit my Lambda function
/* Amplify Params - DO NOT EDIT
API_MYPROJECT_GRAPHQLAPIIDOUTPUT
API_MYPROJECT_PUBLICTABLE_ARN
API_MYPROJECT_PUBLICTABLE_NAME
ENV
REGION
Amplify Params - DO NOT EDIT */
const AWS = require("aws-sdk");
const region = process.env.REGION
AWS.config.update({ region });
const docClient = new AWS.DynamoDB.DocumentClient();
const params = {
TableName: "PublicTable"
}
async function listItems(){
try {
const data = await docClient.scan(params).promise()
return data
} catch (err) {
return err
}
}
exports.handler = async (event) => {
try {
const data = await listItems()
return { body: JSON.stringify(data) }
} catch (err) {
return { error: err }
}
};
Push my updates
$ amplify push
Open my REST API endpoint /items
{
"message": "User: arn:aws:sts::829736458236:assumed-role/myprojectLambdaRolef4f571b-dev/listPublic-dev is not authorized to perform: dynamodb:Scan on resource: arn:aws:dynamodb:us-east-1:8297345848236:table/Public-ssrh52tnjvcdrp5h7evy3zdldsd-dev",
"code": "AccessDeniedException",
"time": "2021-04-21T21:21:32.778Z",
"requestId": "JOA5KO3GVS3QG7RQ2V824NGFVV4KQNSO5AEMVJF66Q9ASUAAJG",
"statusCode": 400,
"retryable": false,
"retryDelay": 28.689093010346657
}
Problems
What I did wrong?
How do I access my table and why I didn't get it when I created it?
Why API_MYPROJECT_PUBLICTABLE_NAME and other constants are needed?
Decision
The problem turned out to be either the NodeJS version or the amplify-cli version. After updating amplify-cli and installing the node on the 14.16.0 version, everything worked.
I also changed the name of the table to what Amplify creates for us, although this code did not work before. The code became like this:
/* Amplify Params - DO NOT EDIT
API_MYPROJECT_GRAPHQLAPIIDOUTPUT
API_MYPROJECT_PUBLICTABLE_ARN
API_MYPROJECT_PUBLICTABLE_NAME
ENV
REGION
Amplify Params - DO NOT EDIT */
const AWS = require("aws-sdk");
const region = process.env.REGION
const tableName = process.env.API_MYPROJECT_PUBLICTABLE_NAME
AWS.config.update({ region });
const docClient = new AWS.DynamoDB.DocumentClient();
const params = {
TableName: tableName
}
async function listItems(){
try {
const data = await docClient.scan(params).promise()
return data
} catch (err) {
return err
}
}
exports.handler = async (event) => {
try {
const data = await listItems()
return { body: JSON.stringify(data) }
} catch (err) {
return { error: err }
}
};

Not able to connect to AWS documentDb from Lambda

I'm trying to connect to AWS documentDB from Lambda function but, not able to connect.
MongoClient.connect never calls the callback function connected.
TLS is off on documentDB Cluster. I'm able to connect via mongo shell.
Lambda & documentDB are in same VPC & Security group.
'use strict';
module.exports.search = async (event, context, callback) => {
const MongoClient = require('mongodb').MongoClient;
const url = "mongodb://xxx:xxxx#xxx-db.cluster-xxx.us-east-2.docdb.amazonaws.com:27017";
console.log("Starting");
MongoClient.connect(url,
{
useNewUrlParser: true
},
function(err, client) {
if(err)
throw err;
console.log("Connected");
db = client.db('mydb');
col = db.collection('mycollection');
col.find({}).toArray().then(result => {
console.log(result);
return { statusCode: 200, body: result };
}).catch(err => {
console.log('=> an error occurred: ', err);
return { statusCode: 500, body: 'error' };
});
});
};
Output only prints starting which was consoled before calling Mongo.Connect.
How to identify or debug the issue ?
Just from looking at the current code I am pretty sure your function exit before it is able to complete. Therefore, your callback is not executed
Because MongoClient.connect runs asynchronously
Try to take a look at some resource around async/await/promise and Lambda
https://medium.com/tensult/async-await-on-aws-lambda-function-for-nodejs-2783febbccd9
How to wait for async actions inside AWS Lambda?

Cannot find module aws-amplify, lambda function

I'm try to make an API post request in my lambda function but in the aws website, using nodejs I cannot import API ? Here is what I am trying
console.log('Loading function');
const AWS = require('aws-sdk');
const translate = new AWS.Translate({ apiVersion: '2017-07-01' });
var API = require('aws-amplify');
exports.handler = async (event, context) => {
try {
const params = {
SourceLanguageCode: 'en', /* required */
TargetLanguageCode: 'es', /* required */
Text: 'Hello World', /* required */
};
const data = await translate.translateText(params).promise();
createSite(data.TranslatedText);
} catch (err) {
console.log(err, err.stack);
}
function createSite(site) {
return API.post("sites", "/sites", {
body: site
});
}
};
I have also tried import...
I think you may be looking at front-end browser based JavaScript examples, which aren't always going to work in a back-end AWS Lambda NodeJS runtime environment. It appears you are trying to use this library, which states it is "a JavaScript library for frontend and mobile developers", which probably isn't what you want to use on AWS Lambda. It appears you also did not include that library in your AWS Lambda function's deployment.
I suggest using the AWS Amplify client in the AWS SDK for NodeJS which is automatically included in your Lambda function's runtime environment. You would create an Amplify client like so:
var amplify = new AWS.Amplify();

How to use WCF service hosted on IIS in an AWS lambda function?

I have this scenario in which a service hosted on IIS must be used by my AWS lambda function. When I try adding it as a service reference, I'm getting "An error occurred while attempting to discover services in the solution: No services found in the solution.. " error. I don't find any issue with the service, and it is working fine.
Is there any link that I'm missing to make my service available to be used by AWS?
If you are using node.js for Lambda then please do like below,
var soap = require('soap');
var url = 'YouServiceURL.svc?wsdl';
var soapOptions = {
forceSoap12Headers: true
};
var soapHeader = {
'wsa:Action': 'http://tempuri.org/MyBinding/MyOperation',
'wsa:To': 'YouServiceURL.svc'
};
exports.handler = function(event, context, callback) {
var params = {
param1: event.param1,
param2: event.param2
};
soap.createClient(url, soapOptions, function(err, client) {
if (err) callback(err);
client.addSoapHeader(soapHeader, '', 'wsa', 'http://www.w3.org/2005/08/addressing');
client.MyOperation(params, function(err, data) {
if (err) callback(err);
callback(null, data);
});
});
}
Please find sample code here

AWS Lambda function to start multiple instances

I just created this function in AWS Lambda to start multiple instances. However when i run the test, it only starts one of the instances instead all the instances in the array. Is this a problem with how i have my array defined in the function? Lambda did not throw a json error so i assumed all was well. I am using the Node.js 4.3 runtime format.
var AWS = require('aws-sdk');
exports.handler = function(event, context) {
var ec2 = new AWS.EC2({region: 'us-west-1'});
ec2.startInstances({InstanceIds : (['i-a11111'],['i-a22222'],['i-a33333'],['i-a44444']) },function (err, data) {
if (err) console.log(err, err.stack); // an error occurred
else console.log(data); // successful response
context.done(err,data);
});
};
From the AWS JavaScript SDK documentation, the InstanceIds parameter is supposed to be an array of strings:
http://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/EC2.html#startInstances-property
This should be the correct format:
{ InstanceIds : ['i-a11111','i-a22222','i-a33333','i-a44444'] }