Timeout error awaiting promise in Lambda? - node.js

I am testing a Serverless lambda function and get a timeout error which I believe is due to an await promise().
module.exports.create = async (event) => {
const provider = event.requestContext.identity.cognitoAuthenticationProvider
....//stuff here where I split auth token to get ids...
const cognito = new AWS.CognitoIdentityServiceProvider({
apiVersion: "2016-04-18"
});
const getUserParams = {
UserPoolId: userPoolId,
Username: userPoolUserId
};
const data =JSON.parse(event.body)
const getUser = await cognito.adminGetUser(getUserParams).promise()
const params = {
Item:{
userId: event.requestContext.identity.cognitoIdentityId,
email: getUser, //!timeout issue probably here!
content: data
}
};
try {
const { Listing } = await connectToDatabase()
const listing = await Listing.create({userId: params.Item.userId, email: params.Item.email
In researching a solution, I have come across people splitting up the lambda into two functions so that they collectively pass the timeout. I do not know how to reference a lambda within a lambda, nor am I sure this is the correct approach.

You change the timeout for lambda function
default timeout for lambda function is 3 sec you can override in below the function code basic settings

For anyone googling this: turns out adminGetUser needs a NAT Gateway configured in order for it to be able to retrieve data from Cognito. I was getting a timeout error because it was not executing, period. Read here: https://aws.amazon.com/premiumsupport/knowledge-center/internet-access-lambda-function/.

Related

NodeJS Proactive Messaging in Bot-framework for Skill Bot

I am working on a requirement in NodeJS where I have to invoke proactive messages from Skill Bot. I have a set Interval loop which runs for every 8 seconds where I added adapter.ContinueConversation method. I have added the below code in skill bot on message method initially but I received 401 Unauthorized error.
await context.sendActivity(`Echo (JS) : '${ context.activity.text }'`);
await context.sendActivity('Say "end" or "stop" and I\'ll end the conversation and back to the parent.');
var adapter = context.adapter;
var conversationReference = TurnContext.getConversationReference(context.activity);
var refreshInterval = setInterval(async () => {
try {
await adapter.continueConversation(conversationReference, async turnContext => {
await turnContext.sendActivity('Are you still there?');
});
}
catch (error) {
console.log(error);
}
}, 8000,conversationReference);
After doing some research online, i have added additional parameters like claims identity and Root Bot's App Id as below but now I receive error that adapter.continueConversationAsync is not a function
var conversationReference = TurnContext.getConversationReference(stepContext.context.activity);
var claimsIdentity= stepContext.context.turnState.get(stepContext.context.adapter.BotIdentityKey);
var oAuthScope= stepContext.context.turnState.get(stepContext.context.adapter.OAuthScopeKey);
await adapter.continueConversationAsync(claimsIdentity, convRef, oAuthScope, async context => {
await context.sendActivity("hello");
})
Can anyone please help resolve the issue?
First, you're receiving the error, "adapter.continueConversationAsync is not a function" because your parameters are wrong. Per the docs there are two overloaded versions of the continueConversation method :
function continueConversation(reference: Partial<ConversationReference>, logic: (context: TurnContext) => Promise<void>): Promise<void>
and
function continueConversation(reference: Partial<ConversationReference>, oAuthScope: string, logic: (context: TurnContext) => Promise<void>): Promise<void>
Your initial implementation was fine, the problem isn't the lack of oAuthScope. I can think of three possible reasons why you get a 401 error :
Your appID and appPassword for your bot adapter might not be set correctly.
Verify your appId and appPassword is correct.
const adapter = new BotFrameworkAdapter({
appId: process.env.MicrosoftAppId,
appPassword: process.env.MicrosoftAppPassword
});
Try trusting the service URL of the conversation reference :
var conversationReference = TurnContext.getConversationReference(stepContext.context.activity);
await adapter.continueConversationAsync(conversationReference, async context => {
MicrosoftAppCredentials.trustServiceUrl(conversationReference.serviceUrl);
await context.sendActivity("hello");
})
And finally, try logging your conversationReference and verify the conversationReference itself is correct. Although since you're getting the conversationReference from the turncontext right before sending the proactive message this part shouldn't be the issue.

Why creating a Stripe customer.id fails within AWS Lambda?

I am using the Stripe/NodeJS library to generate a Stripe customer id when a user is created:
const stripe = require('stripe')(process.env.STRIPE_SECRET_KEY);
exports.handler = async (event, context) => {
const newUser = JSON.parse(event.body);
const customer = await stripe.customers.create({
email: newUser.emailAddress,
});
return customer.id;
};
I thought that the code is pretty straightforward and almost a duplicate to the library's README example, however, the lambda execution hits the stripe.customers.create and never completes, the lambda eventually times out (the lambda is NodeJS 12.x).
Thoughts on what I am missing in order to get this to work?

Error trying to set auto back up Firestore, cloud function

I am following this tutorial here: Tutorial
everything seems ok and it allows me to do everything in the tutorial, but when I run the function I get this error.
textPayload: "TypeError: Cannot read property 'charCodeAt' of undefined
at peg$parsetemplate (/workspace/node_modules/google-gax/build/src/pathTemplateParser.js:304:17)
at Object.peg$parse [as parse] (/workspace/node_modules/google-gax/build/src/pathTemplateParser.js:633:18)
at new PathTemplate (/workspace/node_modules/google-gax/build/src/pathTemplate.js:55:54)
at segments.forEach.segment (/workspace/node_modules/google-gax/build/src/pathTemplate.js:120:29)
at Array.forEach (<anonymous>)
at PathTemplate.render (/workspace/node_modules/google-gax/build/src/pathTemplate.js:114:23)
at FirestoreAdminClient.databasePath (/workspace/node_modules/#google-cloud/firestore/build/src/v1/firestore_admin_client.js:904:57)
at exports.scheduledFirestoreExport (/workspace/index.js:13:31)
at Promise.resolve.then (/layers/google.nodejs.functions-framework/functions-framework/node_modules/#google-cloud/functions-framework/build/src/invoker.js:330:28)
at process._tickCallback (internal/process/next_tick.js:68:7)
insertId: "000000-8410c5c7-8304-42b6-b2b6-dd55a54e8cab"
resource: {2}
timestamp: "2020-07-11T18:14:35.981Z"
severity: "ERROR"
labels: {1}
logName: "projects/b-b-b-app/logs/cloudfunctions.googleapis.com%2Fcloud-functions"
trace: "projects/b-b-b-app/traces/d7c07a715d0106225d9963ce2a046489"
receiveTimestamp: "2020-07-11T18:14:44.813410062Z"
}
I can't see what the problem may be.
I changed the buckets and the app ids like asked in the tutorial.
I am on a Blaze plan and can export the database to the bucket manually by using shell command and using
gcloud firestore export gs://bbbdata-backup
I am using the GCP console on the firebase site and using this code.
const firestore = require('#google-cloud/firestore');
const client = new firestore.v1.FirestoreAdminClient();
const bucket = 'gs://bbbdata-backup'
exports.scheduledFirestoreExport = (event, context) => {
const databaseName = client.databasePath(
process.env.GCLOUD_PROJECT,
'(default)'
);
return client
.exportDocuments({
name: databaseName,
outputUriPrefix: bucket,
// Leave collectionIds empty to export all collections
// or define a list of collection IDs:
// collectionIds: ['users', 'posts']
collectionIds: [],
})
.then(responses => {
const response = responses[0];
console.log(`Operation Name: ${response['name']}`);
return response;
})
.catch(err => {
console.error(err);
});
};
Following the tutorial referred by the OP I run into precisely the same error. Runtime used: Node.js 14.
Root cause of the issue: value of process.env.GCLOUD_PROJECT is undefined.
Workaround: Go to GCP console -> Home. Note your Project ID. Replace process.env.GCLOUD_PROJECT with the 'Project ID' string. The Cloud Function will then work as expected
Note: it appears to be a known issue that GCLOUD_PROJECT environment variable was missing in the Node.js 10 runtime. This bug report contains a lot of additional pointers: https://github.com/firebase/firebase-functions/issues/437
I had a similar issue last year, probably you are missing some permission, I would do it this way, hope this works for you:
import * as functions from 'firebase-functions'
import { auth } from 'google-auth-library'
export const generateBackup = async () => {
const client = await auth.getClient({
scopes: [
'https://www.googleapis.com/auth/datastore',
'https://www.googleapis.com/auth/cloud-platform'
]
})
const path = `YOUR_FOLDER_NAME_FOR_THE_BACKUP`
const BUCKET_NAME = `YOUR_BUCKET_NAME_HERE`
const projectId = await auth.getProjectId()
const url = `https://firestore.googleapis.com/v1beta1/projects/${projectId}/databases/(default):exportDocuments`
const backup_route = `gs://${BUCKET_NAME}/${path}`
return client.request({
url,
method: 'POST',
data: {
outputUriPrefix: backup_route,
// collectionsIds: [] // if you want to specify which collections to export, none means all
}
})
.catch(async (e) => {
return Promise.reject({ message: e.message })
})
}
You can then decide that is your trigger for this function and execute it accordingly.
Note: Go to the IAM section of your project and find the App Engine service account, you will need to add the role Cloud Datastore Import Export Admin, otherwise, It will fail.
You can read more about it here It's very detailed.
Cheers.

Using Firebase from AWS Lambda results in Task timed out

I'm using a Lambda function to create users with Firebase Authentication and then save them at my own database.
var firebase = require('firebase-admin')
const serviceAccount = require('./firebase.json')
firebase.initializeApp({
credential: firebase.credential.cert(serviceAccount),
databaseURL: 'https://*****.firebaseio.com'
})
exports.handler = function(event, context, callback) {
const {email, password, name, ...} = event
firebase.auth().createUser({
email,
emailVerified: false,
password,
displayName: name,
disabled: false
})
.then(firebaseResult => {
const {uid} = firebaseResult
return saveUserAtDatabase({email, name, ...})
})
.then(result => {
callback(null, result)
})
}
The user is created at Firebase and at my database as well, but when I run it at AWS Lambda, it throws this error:
{"errorMessage":"2019-01-07T21:25:49.095Z c...e9 Task timed out after 6.01 seconds"}
Doesn't matter how much time I increase the timeout from the function or set higher memory, it still throws the same error.
I solved the problem setting context.callbackWaitsForEmptyEventLoop=false.
This is because callback waits for the event loop to be empty, which doesn't happen using firebase.auth().createUser(). There is the context.callbackWaitsForEmptyEventLoop option documented here http://docs.aws.amazon.com/lambda/latest/dg/nodejs-prog-model-context.html
When this property is set to false, Lambda freezes the container but does not clear the event loop when you call the callback.

#azure/cosmos in Azure Function ConnectionStringSetting Error

I'm attempting to run the #azure/cosmos samples inside a node.js Azure Function. When it connects to the database it throws this error
" Executed 'Functions.store' (Failed,
Id=a6df6cfb-ae78-4a0b-ae83-5d51efa9fc18) [10/7/2018 9:04:18 PM]
System.Private.CoreLib: Exception while executing function:
Functions.store. Microsoft.Azure.WebJobs.Host: Unable to resolve the
value for property 'CosmosDBAttribute.ConnectionStringSetting'. Make
sure the setting exists and has a valid value.
It fails at await client.databases.createIfNotExists
Anyone get #azure/cosmos to connect inside the index.js of an azure function?
Thanks,
Donnie
const client = new CosmosClient({
endpoint: endpoint,
auth: { masterKey: masterKey }
});
async function init() {
const database = await client.databases.createIfNotExists({
id: databaseId
});
const container = await database.containers.createIfNotExists({
id: containerId
});
return container;
}
edited: added connection info
const connection = {
endpoint: "https://pdf-documents.documents.azure.com:443/",
primaryKey:
"Gub9FZeIMXwz6Lakn..."
};
const cosmos = require("#azure/cosmos");
const CosmosClient = cosmos.CosmosClient;
const endpoint = connection.endpoint;
const masterKey = connection.primaryKey;
const databaseId = "pdfDocuments";
const containerId = "pdfdocuments";
const client = new CosmosClient({
endpoint: endpoint,
auth: { masterKey: masterKey }
});
Thanks to Twitter #Ealsur for solving this for me! Even thought the error occurred in the debugger right at the moment it tried to connect to database, the error was actually an error related to another connection in the output binding of my function!
#azure/cosmos is working well inside an Azure Function.
Thanks again #Ealsur!

Resources