lambda function outputted an error "e is not a function" - amazon-web-services

created two lambda functions by serverless-framework. first function "record-song-vote" writes DynamoDB, it works fine. second function "get-vote-counts" reads all records from DynamoDB, but it continually return error:
{
"errorType": "TypeError",
"errorMessage": "e is not a function",
"trace": [
"TypeError: e is not a function",
" at Runtime.handler (/var/task/serverless_sdk/index.js:9:131872)",
" at Runtime.handleOnce (/var/runtime/Runtime.js:66:25)"
]
}
function get-vote-counts:
'use strict';
const AWS = require("aws-sdk");
const dynamodb = new AWS.DynamoDB.DocumentClient();
module.exports.handler = async event => {
const params = {
TableName: process.env.DYNAMODB_TABLE
};
const result = await dynamodb.scan(params, (error, data) => {
if (error) {
console.error("Unable to update item. Error JSON:", JSON.stringify(error, null, 2));
} else {
console.log("UpdateItem succeeded:", JSON.stringify(data, null, 2));
}
}).promise();
const outputData = result["Items"].map((item) => {
return {
songName: item['songName'],
votes: item['votes']
}
});
return {
"statusCode": 200,
"headers": {
"Access-Control-Allow-Origin": "*"
},
"body": JSON.stringify(outputData)
}
};
I have tried to comment all line in this file. but I still got same error. does anybody have idea?

Related

finding user on aws cognito throws error cognitoidentityserviceprovider is not defined

I am new to AWS services and I am trying out various services provided by AWS. I have this lambda function on which I am trying to find a user with the phone number on AWS Cognito -
const AWS = require('aws-sdk');
async function findCognitoUser(userId) {
console.log('CognitoUser-FindCognitoUser');
var params = {
UserPoolId: 'poolId',
AttributesToGet: [
'phone_number','displayName'
],
Filter: `phone_number = \"${userId}\"`,
};
cognitoidentityserviceprovider.listUsers(params, function(err, data) {
if (err) {
return 'ERROR OCCURED';
}
else {
return data.Users[0].displayName;
}
});
}
module.exports = findCognitoUser;
I do get an error saying cognitoidentityserviceprovider is not defined
Here is the error on CloudWatch -
"errorType": "ReferenceError",
"errorMessage": "cognitoidentityserviceprovider is not defined",
"stack": [
"ReferenceError: cognitoidentityserviceprovider is not defined",
" at findCognitoUser (/var/task/user-queries/findCognitoUser.js:13:5)",
" at Runtime.exports.handler (/var/task/index.js:14:19)",
" at Runtime.handleOnce (/var/runtime/Runtime.js:66:25)"
]
CODE UPDATED -
const AWS = require('aws-sdk');
async function findCognitoUser(userId) {
console.log(userId);
var csp = new AWS.CognitoIdentityServiceProvider({apiVersion: '2016-04-18'});
var params = {
UserPoolId: 'poolid',
AttributesToGet: [
'phone_number','given_name'
],
Filter: `phone_number = \"${userId}\"`,
};
csp.listUsers(params, function(err, data) {
console.log(data);
if (err) {
return 'ERROR OCCURED';
}
else {
return data.Users[0].given_name;
}
});
}
module.exports = findCognitoUser;

Using sequelize with AWS Lambda

So I'm having some issues trying to use sequelize with AWS Lambda, when querying a table where id = 1 it sometimes returns me data and sometimes it doesn't. I read that Sequelize connections and AWS Lambda service don't get well each other because of the how Lambda executes a function.
My question is, is it not enough to open a connection at the top of a function and then close it at the bottom (before returning something)? If not, what else can I do?
Update:
const findCityByPk = async (pathParameters) => {
const { Postgresql: ps } = require('../libs/utils/potsgresql');
console.log(ps.connection.connectionManager);
const { id } = pathParameters;
try {
const city = await City.findByPk(id);
if (city) {
ps.connection.close();
return {
statusCode: 200,
body: JSON.stringify(city)
};
}
ps.connection.close();
return {
statusCode: 500,
body: JSON.stringify({ message: 'City not found`' })
};
} catch (err) {
console.log(err);
await ps.connection.close();
return {
statusCode: 500,
body: JSON.stringify(err)
};
}
}
This is the code I'm testing it sometimes returns me the correct object from my table
{"id":"1","city_name":"Lima2","zip_code":"12312","time_zone_utc":-5} -> this is what is supposed to be returning, and instead I'm getting this object
{
"requestTime": "06/Dec/2021:18:07:24 +0000",
"requestId": "8b5bf017-c180-41cc-9de6-b07599f0e9b8",
"apiId": "xx",
"resourceId": "xx",
"resourcePath": "/city/{id}",
"path": "/dev/city/1",
"httpMethod": "GET",
"status": "500",
"authLatency": "-",
"integrationLatency": "48",
"integrationStatus": "200",
"responseLatency": "50",
"responseLength": "2",
"errorMessage": "-",
"format": "SLS_ACCESS_LOG",
"version": "1.0.0"
}
And also, this is how it's being made the connection
const createConnection = () => {
console.info("[Postgresql] createConnection: start")
console.info("[Postgresql] createConnection: creating conection start")
let conn;
let string_connection;
try {
string_connection = `postgres://${config.DB_USER}:${config.DB_PASSWORD}#${config.DB_HOST}:5432/${config.DB_NAME}`
//console.debug(`[Postgresql] string_connection: ${string_connection}`)
conn = new Sequelize(string_connection, { logging: false, pool: { max: 1, min: 0, idle: 1000 } });
} catch (e) {
console.debug(`[Postgresql] createConnection: creating conection error ${string_connection}`)
throw e;
}
console.info("[Postgresql] createConnection:creating conection end")
return conn;
}

AWS Dynamo DB Query

Hi I am trying to query Dynamo DB using lambda below is the code.
exports.handler = function index(event, context, callback) {
var AWS = require("aws-sdk");
AWS.config.update({
region: "us-west-1"
});
var docClient = new AWS.DynamoDB.DocumentClient();
console.log("Querying ");
var params = {
TableName : "BankApp",
KeyConditionExpression: "#yr = :Value",
ExpressionAttributeValues: {
"#yr": "Test"
},
ExpressionAttributeNames : {
":Value" : {"S" : "TEST" }
}
};
docClient.query(params, function(err, data) {
if (err) {
console.error("Unable to query. Error:", JSON.stringify(err, null, 2));
} else {
console.log("Query succeeded.");
data.Items.forEach(function(item) {
console.log(" -", item.Account_NUM + ": " + item.ACCOUNT_BAL);
});
}
});
}
But i am getting Error Saying :
Unable to query. Error: {
"message": "ExpressionAttributeNames contains invalid key: Syntax error; key: \":Value\"",
"code": "ValidationException",
"time": "2018-07-17T15:20:40.308Z",
It was my mistake, I was using wrong region.

Getting AWS Dynamodb query result as internel server error code : 502

This is my table "odo":
I want to retrive data where deviceId == 'A233' Between two timestamps. I run query inside Lamda Function and testing with API Gateway.
This is query I ran to get the result:
var params = {
TableName: "odo",
KeyConditionExpression: "#deviceId = :deviceIdVal AND #timestamp BETWEEN :sdate AND :edate",
ExpressionAttributeNames: {
"#deviceId": "deviceId",
"#timestamp": "timestamp"
},
ExpressionAttributeValues: {
":deviceIdVal": 'A233',
":sdate": 1110601808,
":edate": 1522902606
}
};
But I get a error as "Internal Server Error" and Error Code : 502
Why this query won't work? What am I missing?
When I ran another query using id field,it work.
module.exports.handler = function (event, context, callback) {
console.log(event);
let _response = "";
let invalid_path_err = {
"Error": "Invalid path request " + event.resource + ', ' +
event.httpMethod
};
if(event.resource === '/odos' && event.httpMethod === "GET"){
var params = {
TableName: "odo",
KeyConditionExpression: "#id = :id",
ExpressionAttributeNames: {
"#id": "id"
},
ExpressionAttributeValues: {
":id": 7
}
};
docClient.query(params, function(err, data) {
if (err) {
console.error("Unable to query. Error:", JSON.stringify(err, null, 2));
} else {
console.log("Query succeeded.",data);
_response = buildOutput(200, data);
return callback(null, _response);
}
});
}
else {
_response = buildOutput(500, {"error 500" : "invalid_path_err"});
return callback(_response, null);
}
};
/* Utility function to build HTTP response for the microservices output */
function buildOutput(statusCode, data) {
let _response = {
statusCode: statusCode,
headers: {
"Access-Control-Allow-Origin": "*"
},
body: JSON.stringify(data)
};
return _response;
};
This is the success result in test method execution in API Gateway:
The problem is that your query is trying to use a table partition key of deviceid and a range key of timestamp. In fact you have a parition key called id and no range key.
You can only use KeyConditionExpression on attributes that are a key, which in your case is the attribute id.
To do your 'query' you need to change KeyConditionExpression to FilterExpression and change query to scan
EDIT:
module.exports.handler = function (event, context, callback) {
console.log(event);
let _response = "";
let invalid_path_err = {
"Error": "Invalid path request " + event.resource + ', ' +
event.httpMethod
};
if(event.resource === '/odos' && event.httpMethod === "GET"){
var params = {
TableName: "odo",
FilterExpression: "#deviceId = :deviceIdVal AND #timestamp BETWEEN :sdate AND :edate",
ExpressionAttributeNames: {
"#deviceId": "deviceId",
"#timestamp": "timestamp"
},
ExpressionAttributeValues: {
":deviceIdVal": 'A233',
":sdate": 1110601808,
":edate": 1522902606
}
};
docClient.scan(params, function(err, data) {
if (err) {
console.error("Unable to query. Error:", JSON.stringify(err, null, 2));
} else {
console.log("Query succeeded.",data);
_response = buildOutput(200, data);
return callback(null, _response);
}
});
}
else {
_response = buildOutput(500, {"error 500" : "invalid_path_err"});
return callback(_response, null);
}
};
/* Utility function to build HTTP response for the microservices output */
function buildOutput(statusCode, data) {
let _response = {
statusCode: statusCode,
headers: {
"Access-Control-Allow-Origin": "*"
},
body: JSON.stringify(data)
};
return _response;
};

Searching DynamoDB for non primary keys and integrating into Alexa Skills

I am trying to search a non primary key using AWS Lambda and integrating it into the Alexa Skills Kit. I am very new to using DynamoDB and Alexa Skills Kit and I'm struggling to find any solutions to this online. The basic premise for what I am trying to do is querying the table yesno with two columns, id and message. Only looking through the message column to find a match with the text i specify in params.
Here is the Lambda code I am working with:
const AWSregion = 'eu-west-1';
const Alexa = require('alexa-sdk');
const AWS = require('aws-sdk');
//params for searching table
const params = {
TableName: 'yesno',
Key:{ "message": 'Ben Davies' }
};
AWS.config.update({
region: AWSregion
});
exports.handler = function(event, context, callback) {
var alexa = Alexa.handler(event, context);
// alexa.appId = 'amzn1.echo-sdk-ams.app.1234';
// alexa.dynamoDBTableName = 'YourTableName'; // creates new table for session.attributes
alexa.registerHandlers(handlers);
alexa.execute();
};
const handlers = {
'LaunchRequest': function () {
this.response.speak('welcome to magic answers. ask me a yes or no question.').listen('try again');
this.emit(':responseReady');
},
'MyIntent': function () {
var MyQuestion = this.event.request.intent.slots.MyQuestion.value;
console.log('MyQuestion : ' + MyQuestion);
readDynamoItem(params, myResult=>{
var say = MyQuestion;
say = myResult;
say = 'you asked, ' + MyQuestion + '. I found a reckord for: ' + myResult;
this.response.speak(say).listen('try again');
this.emit(':responseReady');
});
},
'AMAZON.HelpIntent': function () {
this.response.speak('ask me a yes or no question.').listen('try again');
this.emit(':responseReady');
},
'AMAZON.CancelIntent': function () {
this.response.speak('Goodbye!');
this.emit(':responseReady');
},
'AMAZON.StopIntent': function () {
this.response.speak('Goodbye!');
this.emit(':responseReady');
}
};
// END of Intent Handlers {} ========================================================================================
// Helper Function =================================================================================================
function readDynamoItem(params, callback) {
var AWS = require('aws-sdk');
AWS.config.update({region: AWSregion});
var dynamodb = new AWS.DynamoDB();
console.log('reading item from DynamoDB table');
dynamodb.query(params, function (err, data) {
if (err) console.log(err, err.stack); // an error occurred
else{
console.log(data); // successful response
callback(data.Item.message);
}
});
}
I know I am probably doing this completely wrong but there isn't much online for integrating DynamoDB with an Alexa Skill and the only thing i was able to find was searching by ID. This doesn't work for what i want to do without pulling all the items from the table into a map or a list, and seeing as I want to create a big database it seems quite inefficient.
On the Alexa side of things I am receiving the following service request when testing the code:
{
"session": {
"new": true,
"sessionId": "SessionId.f9558462-6db8-4bf5-84aa-22ee0920ae95",
"application": {
"applicationId": "amzn1.ask.skill.9f280bf7-d506-4d58-95e8-b9e93a66a420"
},
"attributes": {},
"user": {
"userId": "amzn1.ask.account.AF5IJBMLKNE32GEFQ5VFGVK2P4YQOLVUSA5YPY7RNEMDPKSVCBRCPWC3OBHXEXAHROBTT7FGIYA7HJW2PMEGXWHF6SQHRX3VA372OHPZZJ33K7S4K7D6V3PXYB6I72YFIQBHMJ4QGJW3NS3E2ZFY5YFSBOEFW6V2E75YAZMRQCU7MNYPJUMJSUISSUA2WF2RA3CIIDCSEY35TWI"
}
},
"request": {
"type": "IntentRequest",
"requestId": "EdwRequestId.7310073b-981a-41f8-9fa5-03d1b28c5aba",
"intent": {
"name": "MyIntent",
"slots": {
"MyQuestion": {
"name": "MyQuestion",
"value": "erere"
}
}
},
"locale": "en-US",
"timestamp": "2018-01-25T14:18:40Z"
},
"context": {
"AudioPlayer": {
"playerActivity": "IDLE"
},
"System": {
"application": {
"applicationId": "amzn1.ask.skill.9f280bf7-d506-4d58-95e8-b9e93a66a420"
},
"user": {
"userId": "amzn1.ask.account.AF5IJBMLKNE32GEFQ5VFGVK2P4YQOLVUSA5YPY7RNEMDPKSVCBRCPWC3OBHXEXAHROBTT7FGIYA7HJW2PMEGXWHF6SQHRX3VA372OHPZZJ33K7S4K7D6V3PXYB6I72YFIQBHMJ4QGJW3NS3E2ZFY5YFSBOEFW6V2E75YAZMRQCU7MNYPJUMJSUISSUA2WF2RA3CIIDCSEY35TWI"
},
"device": {
"supportedInterfaces": {}
}
}
},
"version": "1.0"
}
And I am receiving a service response error simply saying 'The response is invalid'
Any help with this would be greatly appreciated
I would like to help you in dynamo db part.
In order to access non primary key columns in dynamodb you should perform scan operation.
For your table (yesno), id is a primary key and message is an additional column.
Snippet to access non primary key column [Message]
var dynamodb = new AWS.DynamoDB();
var params = {
TableName: 'yesno',
FilterExpression: 'message = :value',
ExpressionAttributeValues: {
':value': {"S": "Ben Davies"}
}
};
dynamodb.scan(params, function(err, data) {
if (err) // an error occurred
else console.log(data); // successful response
});
Snippet to access primary key column [Id]
var docClient = new AWS.DynamoDB.DocumentClient();
//Get item by key
var params = {
TableName: 'sis_org_template',
Key: { "id": "1"}
};
docClient.get(params, function(err, data) {
if (err) // an error occurred
else console.log(data); // successful response
});