Middy: Middy cause a timeout with async lambda (but only on AWS, not on my machine)

Created on 28 Apr 2020  路  6Comments  路  Source: middyjs/middy

I had a problem with Middy 1.0.0 and NodeJS 12.x. I was trying to connect to Redshift using dbManager, like this:

const middy = require('@middy/core')
const dbManager = require('@middy/db-manager');

const lambda = middy(async (event, context) => {
    const { db } = context;
    const records = await db.distinct('XXX').from('YYY');

    // print result
    console.log(records);

    // return result
    return {
        'statusCode': 200,
        'body': JSON.stringify(records)
    }
});

lambda    
    .use(dbManager({
        config: {
          client: 'pg',
          connection: {
            host: 'XXX',
            port: '1111',
            schema: 'public',
            user: 'XXX',
            password: 'XXX',
            database: 'XXX'
          }
        }
    }));

module.exports = { lambda }

This was causing Lambda to get stuck, until timeout kill it. I start to searching through the issues of this repo and I've found that set context.callbackWaitsForEmptyEventLoop to false. So I introduced the WaitsForEmptyEventLoop middleware and it works but... it only works on my machine! :-)

Yep, joke apart, if I'm executing the sam local invoke FunctionName everything works: the local Lambda invoke correctly the remote redshift and so it ends successfully. But, once I run sam deploy the same code, the same build still produce a timeout when real Lambda is executed.

Why this problem?
Any idea?

Bye

Most helpful comment

I too am wrestling with this just now.

Exploring this package atm:
https://github.com/middyjs/middy/tree/master/packages/do-not-wait-for-empty-event-loop

Looks like it works when set to:

.use(doNotWaitForEmptyEventLoop({
  runOnBefore: true,
  runOnAfter: true,
  runOnError: true
}))

All 6 comments

I too am wrestling with this just now.

Exploring this package atm:
https://github.com/middyjs/middy/tree/master/packages/do-not-wait-for-empty-event-loop

Looks like it works when set to:

.use(doNotWaitForEmptyEventLoop({
  runOnBefore: true,
  runOnAfter: true,
  runOnError: true
}))

I forgot to close some postgresql pools which caused the event loop to stay full. Adding the do-not-wait-for-empty-event-loop package solved the issue but I really need to ensure I'm closing my pg pools 馃槃

I forgot to close some postgresql pools which caused the event loop to stay full. Adding the do-not-wait-for-empty-event-loop package solved the issue but I really need to ensure I'm closing my pg pools 馃槃

How did you close the pool? I've searching for this, but I haven't found the command. Anyway this doesn't explain why it blocks on a real lambda and not locally. I mean the pool is the same.

Hey @sdomagala can you have a quick look at this? Maybe we can improve the documentation of the middleware to address common issues...

I'm trying to figuring out how to destroy the connection pool and db, now my try blocks looks like this:

const { db } = context;
console.log("context.callbackWaitsForEmptyEventLoop: " + context.callbackWaitsForEmptyEventLoop); // false

const records = await db.distinct('XXX').from('XXX');
db._context.client.pool.destroy();
console.log("db._context.client.pool.destroyed" + db._context.client.pool.destroyed); // true
db.destroy();

When I run it using sam local invoke I have false for context.callbackWaitsForEmptyEventLoop this execute the query then I call pool.destroy()but when I run sam deploy and execute on the real Lambda platform it still gets timeout.

There is a forceNewConnection option that will trigger the destroy function of the client. I've also added a not in around event loop handling to the docs.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

lmammino picture lmammino  路  3Comments

coreylight picture coreylight  路  3Comments

willfarrell picture willfarrell  路  3Comments

lmammino picture lmammino  路  6Comments

michalorman picture michalorman  路  7Comments