0

I have a serverless framework node js function that initializes mysql DB and then runs a query, ES6 is used to return an HTTP response at the end

  1. Is there a way to return the response before waiting for the DB call to finish, for example in node js - res.send will return immediately and the function continues to run after the response is returned

  2. Is there a better way to initialize a new mysql pool (perhaps reuse the pool instead of creating an ending it in each request?)

    a: If for example the answer is to create the pool outside the function, how does it exactly work and how does the lambda function reuse it between requests, when does it get destroyed and how does it know when to recreate the pool

import mysql from "mysql";

export const myFunc = async (event) => {
  try {
    const pool = mysql.createPool({...}); // Creates a new mysql pool

    await new Promise((resolve, reject) => {pool.query(
      "INSERT STATEMENT", [...params], (error, results) => {
      if(error) reject(error)
      resolve(results)
}
    )});

    pool.end();

    return {
      statusCode: 200,
      body: JSON.stringify({message: 'End'}),
    };
  } catch (err) {
    return {
      statusCode: 500,
      body: JSON.stringify({message: 'Error'}),
    };
  }
};

1 Answer 1

1
  1. Is there a way to return the response before waiting for the DB call to finish

Yes, but then the Lambda will finish executing before waiting for DB call finishing. It will not guarantee that the call to DB will reach the DB, so it's not recommended to do so.

If you absolutely need this, drop the await statement in this line:

From:

await new Promise((resolve, reject) => {pool.query(

To:

new Promise((resolve, reject) => {pool.query(
  1. Is there a better way to initialize a new mysql pool (perhaps reuse the pool instead of creating an ending it in each request?)

Yes, you need to initialize your pool outside of Lambda handler.

Check out this article for more details:

https://dashbird.io/blog/leveraging-lambda-cache-for-serverless-cost-efficiency/

Basically, you want to do instead of:

import mysql from "mysql";

export const myFunc = async (event) => {
  try {
    const pool = mysql.createPool({...}); // Creates a new mysql pool

Do this:

import mysql from "MySQL";

const pool = mysql.createPool({...}); // Creates a new mysql pool

export const myFunc = async (event) => {
  try {
Sign up to request clarification or add additional context in comments.

7 Comments

I'd agree with @Vlad Holubiev answer, but I'd also argue that you have a design issue with your app. If you wish to return immediately from the function - I'd argue that you should be considering async processing. e.g. creating a job on a queue - where any failed writes can be DLQd and reprocessed. You need to consider how your Lambda function will scale with concurrent requests too - you could exhaust connections to your DB if you had a large spike in requests. You would have more control over DB connections if you asynchronously process writes via a queue.
@Vlad Holbiev Unfortunately dropping the await statement introduced weird errors, 1. No writes were made to the DB and I assume that's because the lambda exists before it reaches the DB 2. Some of the requests go through successfully (still no writes to the DB) but some others return 502 Invalid gateway, i'm still not sure why if you have an explanation that'd be appreciated
@jeeves Do you suggest an article or an AWS service to handle these writes in queue? Would creating a new SNS event with another lambda specifically for writing to the DB solve it, and instead of writing directly sending a new event to SNS?
@Vlad Holbiev Can you explain why doesn't a similar approach introduced by "context.callbackWaitsForEmptyEventLoop" work here? If im not mistaken this makes the function continue running even after the callback? Another approach is described here but is not well informative I believe medium.com/@piyush.jaware_25441/…
@MarkZu b/c when set callbackWaitsForEmptyEventLoop = true, mysql will keep the connection open as it's default behavior, and the lambda will never return the result and will wait until all open connections are closed. your lambda will always time out
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.