I am have Node.js script where in the beginning of it I connect to my MongoDB database and get a specific collection and use that within the script. I set this script up in an AWS Lambda function with a timeout of 10 seconds. When I test the AWS Lambda with a configured test event, I get a "Task timed out after 10.00 seconds". My script is still suppose to run after it connects and finish the rest of the script. However, it stops and I get a timeout error from AWS Lambda. If I set a timeout higher, such as 15 minutes, I get the timeout error 15 minutes after I connect to the MongoDB database within the script (I got this my looking at the CloudWatch logs for the AWS Lambda function). I experimented with different timeout timings and found that for x seconds I set the timeout, my script will give the timeout error x seconds after I connect to the MongoDB database. I followed all best practices mentioned in this article about connecting to MongoDB from AWS Lambda and they are are: defining the MongoDB client connection outside the handler function and setting the context property callbackWaitsForEmptyEventLoop
to false
. I am not sure how to fix this. Below is some relevant code I used in my script:
main.ts
:
import { connectToDatabase } from './mongodb'
import mongodb from 'mongodb'
export const handler = async (event: any, context: any, callback: any) => {
context.callbackWaitsForEmptyEventLoop = false
const db = await connectToDatabase().then((db: mongodb.Db) => db).catch(error => error)
var collection: mongodb.Collection = db.collection("{collection-name}")
// Rest of the script
}
mongodb.ts
:
import mongodb, { MongoClient } from "mongodb"
let uri: undefined | string = process.env.MONGODB_URI
let dbName: undefined | string = process.env.MONGODB_DB
let cachedClient: null | mongodb.MongoClient = null
let cachedDb: null | mongodb.Db = null
export async function connectToDatabase() {
if (cachedClient && cachedDb) {
return cachedDb
}
if (!uri) {
throw new Error(
"Please define the MONGODB_URI environment variable inside .env.local"
)
}
if (!dbName) {
throw new Error(
"Please define the MONGODB_DB environment variable inside .env.local"
)
}
const client = await MongoClient.connect(uri, {
useNewUrlParser: true,
useUnifiedTopology: true,
})
const db = client.db(dbName)
cachedClient = client
cachedDb = db
return db
}
Other info: I use serverless to push the script to AWS Lambda and also using serverless plugin "serverless-webpack" for TypeScript files.
The best practice linked in your article says Define the MongoDB client connection outside of your handler function
. In your case you should change const db =...
to db =...
and declare db
outside of your handler function and change it to let db = null
like in the example in the article, so you can reuse the connections in different Lambda invocations. For example:
let db = null;
export const handler = async (event, context, callback) => {
if (!db) {
db = connectToDatabase();
}
// do something with your db
callback();
};
Besides that, take @hoangdv 's advice and call the callback
function to signal AWS Lambda that you're done with handling the event. That should do the trick.
I found that AWS Lambda functions can only run for a maximum of 15 minutes (even if the code is still running after that amount of time). If I wanted to run the script for more than 15 minutes, I guess I would have to use an AWS EC2 instance.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.