laconia icon indicating copy to clipboard operation
laconia copied to clipboard

Socket connections requires set context.callbackWaitsForEmptyEventLoop to false

Open hugosenari opened this issue 5 years ago • 3 comments

Describe the bug When my code leaves one open connection (ie: with some DBs), AWS Lambda throws timeout, even after my function run.

To Reproduce Make any code that uses socket connections (ie: MySQL, Mongodb...); Resolves function with some value; And leaves that connection open for the next lambda function call.

Expected behavior Since using promise to resolve function without laconia doesn't trows timeout. I would expect the same with it.

Actual behavior AWS Lambda throws timeout, even after my function resolves.

Additional context Correct behavior (#48) would break laconia/batch and maybe others user cases

#415 aimed to solve this without contract breaks

hugosenari avatar Nov 26 '19 17:11 hugosenari

Break API

Pros:

  • Clean up API;
  • Solve this and warning (#48) problem.

Cons:

  • User upgrade may be more difficult;
  • Require rewrite laconia/batch;

Create another entrypoint

Pros:

  • Easy migration;
  • Left some way to use sync version (ie: laconia/batch);

Cons:

  • More code to deal;
  • More boilerplate;
  • Will not solve problem for adapters (ie: laconia/api, laconia/adapter)

hugosenari avatar Nov 26 '19 17:11 hugosenari

Great description @hugosenari.

I have a doubt on the expected behaviour, where you mention:

Since using promise to resolve function without laconia doesn't trows timeout. I would expect the same with it.

In my experience, whenever I open up a socket connection, even without Laconia, I will need to set callbackWaitsForEmptyEventLoop to false, especially if I want to freeze the connection. See also this comment, or this post. Otherwise, it will timeout, which is the expected behaviour from AWS Lambda.

ceilfors avatar Nov 27 '19 06:11 ceilfors

Almost one year later... sorry :)

Here goes my tests results.

Promise + Connection = Success

REPORT RequestId: e6293e658730
Duration: 10.96 ms
Billed Duration: 100 ms
Memory Size: 128 MB
Max Memory Used: 64 MB
Init Duration: 128.88 ms	

Callback - Connection = Success

REPORT RequestId: 322aebe37100	
Duration: 16.49 ms	
Billed Duration: 100 ms	
Memory Size: 128 MB	
Max Memory Used: 63 MB	
Init Duration: 126.88 ms	

Callback + Connection = Timeout:

REPORT RequestId: dae829af27b9	
Duration: 3003.14 ms	
Billed Duration: 3000 ms	
Memory Size: 128 MB	
Max Memory Used: 14 MB	
2020-06-17T02:26:29.143Z dae829af27b9 Task timed out after 3.00 seconds

Promise Code:

const net = require('net');
const client = net.createConnection(53, '1.1.1.1');
console.log('connecting');
exports.handler = async (event) => {
    const response = await {
        statusCode: 200,
        body: JSON.stringify(`
            Hello from Lambda!
            ${client.destroyed}
            ${client.remoteAddress}
            ${client.write('olar')}
        `),
    };
    console.log(response.body);
    return response;
};

Callback Code:

const net = require('net');
const client = net.createConnection(53, '1.1.1.1');
console.log('connecting');
exports.handler = (event, ctx, cb) => {
    const response = {
        statusCode: 200,
        body: JSON.stringify(`
            Hello from Lambda!
            ${client.destroyed}
            ${client.remoteAddress}
            ${client.write('olar')}
        `),
    };
    console.log(response.body);
    return cb(null, response);
};

hugosenari avatar Jun 17 '20 02:06 hugosenari