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

fix(setupServer): set max listeners on the "request.signal" #1765

Merged
merged 2 commits into from
Oct 10, 2023

Conversation

kettanaito
Copy link
Member

@kettanaito kettanaito commented Oct 10, 2023

Fixes the issue when having a large number of request handlers would result in the following error from Node when processing an intercepting request:

(node:3158) MaxListenersExceededWarning: Possible EventTarget memory leak detected. 11 abort listeners added to [AbortSignal].

Why was this error printed?

When a large number of event listeners is added to any target, Node preemptively prints an error letting you know that something may be off (a potential memory leak). However, in the case of the request handlers, we are expecting at least a N abort event listener to be added to the original request.signal because every request handler clones the intercepted request at least once (so it could read its body when logging it).

How is this fixed?

By using require('events').setMaxListeners() on the request.signal.

// "AbortController" so if the parent aborts, all the
// clones are automatically aborted.
setMaxListeners(
Math.max(defaultMaxListeners, this.currentHandlers.length),
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We must never set fewer max listeners than defaultMaxListeners, even if there are fewer request handlers, because that may produce false positive "possible memory leak" errors from Node.

Node sets the max listeners to 10 by default, if I'm not mistaken. If there are fewer request handlers, keep the default max listeners count.

@@ -194,11 +196,11 @@ export abstract class RequestHandler<
this.isUsed = true

const parsedResult = await this.parse({
request: mainRequestRef.clone(),
request: args.request,
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No more cloning of the intercepted request for the internal phases. Each request handler class must clone the given request by itself if it intends to read its body.

@kettanaito kettanaito mentioned this pull request Oct 10, 2023
34 tasks
@kettanaito kettanaito merged commit 17d5f3a into feat/standard-api Oct 10, 2023
9 checks passed
@kettanaito kettanaito deleted the fix/request-clone-memory-warning branch October 10, 2023 12:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant