Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MaxListenersExceededWarning: Possible EventEmitter memory leak detected. 11 error listeners added to [Keyv]. Use emitter.setMaxListeners() to increase limit #1523

Open
2 tasks done
phawxby opened this issue Nov 12, 2020 · 21 comments
Labels
bug Something does not work as it should external The issue related to an external project ✭ help wanted ✭

Comments

@phawxby
Copy link

phawxby commented Nov 12, 2020

Describe the bug

When using simple cache adapters MaxListenersExceededWarning is emitted. This has previously been investigated in #792 and #1128 but either it is a regression or did not account for highly asynchronous environments with 100's of parallel requests.

Unsure if this is best opened in either keyv or cacheable-request, but given it was declared solved in #1128 I've opened it here first.

Environment Info:
  System:
    OS: macOS 10.15.7
    CPU: (12) x64 Intel(R) Core(TM) i7-9750H CPU @ 2.60GHz
  Binaries:
    Node: 12.19.0 - ~/.nvm/versions/node/v12.19.0/bin/node
    Yarn: 1.22.10 - /usr/local/bin/yarn
    npm: 6.14.8 - ~/.nvm/versions/node/v12.19.0/bin/npm
  Browsers:
    Chrome: 86.0.4240.198
    Safari: 14.0

Got: 11.8.0

Actual behavior

MaxListenersExceededWarning: Possible EventEmitter memory leak detected. 11 error listeners added to [Keyv]. Use emitter.setMaxListeners() to increase limit

Code to reproduce

const got = require('got');

const client = got.extend({
    cache: {
        get: (key) => {
            return undefined;
        },
        set: (key, value) => {

        }
    }
});

(async () => {
    const promises = [];

    for (let i = 0; i < 20; i++) {
        promises.push(client('https://www.google.com', { method: 'HEAD' }));
    };

    await Promise.all(promises);

    console.log('Done');
})();

Checklist

  • I have read the documentation.
  • I have tried my code with the latest version of Node.js and Got.

Related Tickets

jaredwray/cacheable#97

@szmarczak szmarczak added enhancement This change will extend Got features ✭ help wanted ✭ labels Nov 12, 2020
@szmarczak
Copy link
Collaborator

Actually this isn't a memory leak.

https://github.com/lukechilds/cacheable-request/blob/0656a46a3573a4de09f592f1d334433d223e68b7/src/index.js#L190

But the code can be optimized anyway.

@szmarczak szmarczak added the external The issue related to an external project label Nov 12, 2020
@phawxby
Copy link
Author

phawxby commented Nov 12, 2020

@szmarczak ah, so the listener is removed after handling is complete so this only occurs when you have more than 10 requests in flight at any one time?

@szmarczak
Copy link
Collaborator

Correct.

@phawxby
Copy link
Author

phawxby commented Nov 16, 2020

@szmarczak so how would you suggest proceeding because having many requests in flight at any one time is fairly normal use-case. Does the max listeners limit need raising? Warnings being emitted during normal operation scares the villagers, such as myself.

@szmarczak
Copy link
Collaborator

The workaround lies in the very title of the issue:

Use emitter.setMaxListeners() to increase limit

Simply pass a Keyv instance as the cache option. Just set cache.setMaxListeners(100000) and you're good to go.

@phawxby
Copy link
Author

phawxby commented Nov 17, 2020

@szmarczak I expected that too, but it doesn't. That's why I created this (by the way, thanks for helping chase this around).

const got = require('got');
const Keyv = require('keyv');

const keyv = new Keyv();
keyv.setMaxListeners(10000);

const client = got.extend({
    cache: {
        get: (key) => {
            return undefined;
        },
        set: (key, value) => {

        }
    }
});

const keyvClient = got.extend({
    cache: keyv
});

(async () => {

    console.log('Simple cache client', 'start');
    let promises = [];
    for (let i = 0; i < 20; i++) {
        promises.push(client(`https://www.google.com?${i}`, { method: 'HEAD' }));
    };
    await Promise.all(promises);
    console.log('Simple cache client', 'end');

    console.log('Keyv cache client', 'start');
    promises = [];
    for (let i = 0; i < 20; i++) {
        promises.push(keyvClient(`https://www.google.com?${i}`, { method: 'HEAD' }));
    };
    await Promise.all(promises);
    console.log('Keyv cache client', 'end');

    console.log('Done');
})();

Output

paul@Pauls-iPad got-keyv % node test.js         
Simple cache client start
(node:55811) MaxListenersExceededWarning: Possible EventEmitter memory leak detected. 11 error listeners added to [Keyv]. Use emitter.setMaxListeners() to increase limit
(Use `node --trace-warnings ...` to show where the warning was created)
Simple cache client end
Keyv cache client start
(node:55811) MaxListenersExceededWarning: Possible EventEmitter memory leak detected. 11 error listeners added to [Keyv]. Use emitter.setMaxListeners() to increase limit
Keyv cache client end
Done

@szmarczak
Copy link
Collaborator

It's because it creates another Keyv instance:

https://github.com/lukechilds/cacheable-request/blob/0656a46a3573a4de09f592f1d334433d223e68b7/src/index.js#L19

So I don't think there is any workaround at all for now :(

@szmarczak szmarczak added bug Something does not work as it should and removed enhancement This change will extend Got features labels Nov 17, 2020
@phawxby
Copy link
Author

phawxby commented Nov 17, 2020

@szmarczak ok. Many thanks for the help with all of this!

@Fab-z4qx

This comment has been minimized.

@Fab-z4qx

This comment has been minimized.

@nardo7

This comment has been minimized.

@ckotyan

This comment has been minimized.

@simonecorsi
Copy link

simonecorsi commented Feb 10, 2021

It's because it creates another Keyv instance:

I'm facing issues for similar reasons, it's also registering a once error listener that gets cleared after response, which is okay-ish but it doesn't account for databases connection error (eg: replicas failover) which crashes the process and prevent network fallback.

I think Got could also benefit from this, I've opened a PR about this at cacheable-request, @szmarczak are you also a maintainer of that lib? WDYT?

@szmarczak
Copy link
Collaborator

I've opened a PR about this at cacheable-request

Looks good. I'll look deeper this week to look out for bugs if any.

@szmarczak are you also a maintainer of that lib?

Yes. I'm going to rewrite cacheable-request completely but first we're releasing Got 12 soon.

@phawxby
Copy link
Author

phawxby commented Nov 1, 2021

@szmarczak we've been having some issues with timeouts of tests lately and we're wondering if this is now potentially part of the cause. Have you made any progress on figuring out a fix for this?

@szmarczak
Copy link
Collaborator

This has nothing to do with timeouts.

@Fab-z4qx
Copy link

Any update on it ?

@jaredwray
Copy link
Sponsor

@Fab-z4qx - I believe this has been updated in keyv and we should be good to go. If not can you provide an updated detail of how you are getting this error and we will look into it.

@jaredwray
Copy link
Sponsor

@sindresorhus or @szmarczak - this I believe has been resolved and you can close it as the pull request was merged here: jaredwray/cacheable#101

@jaredwray
Copy link
Sponsor

@sindresorhus - did you want to close this?

@balaji2711
Copy link

I was trying to run the playwright tests and ended up with the MaxListenersExceededWarning error -

image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something does not work as it should external The issue related to an external project ✭ help wanted ✭
Projects
None yet
Development

No branches or pull requests

8 participants