Skip to content

Commit

Permalink
fix: use a short-lived AbortSignal for fetch operations (#511)
Browse files Browse the repository at this point in the history
Node's `undici` module appears to be adding listeners for the `"abort"` event on any passed AbortSignal but then not cleaning them up.

This casues many `MaxListenersExceededWarning`s to appear in the console and likely causes a memory leak.

To work around this, use a short-lived `AbortSignal` for each request that can be garbage collected along with the request itself.

See https://github.com/nodejs/node/issues/52635 for more information.
  • Loading branch information
achingbrain authored Apr 22, 2024
1 parent 0ecb529 commit 5e98950
Showing 1 changed file with 10 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -91,12 +91,20 @@ export class TrustlessGateway {
}

const blockId = this.#uniqueBlockId(cid)

// workaround for https://github.com/nodejs/node/issues/52635
const innerController = new AbortController()
const abortInnerSignal = (): void => {
innerController.abort()
}
signal?.addEventListener('abort', abortInnerSignal)

try {
let pendingResponse: Promise<Uint8Array> | undefined = this.#pendingResponses.get(blockId)
if (pendingResponse == null) {
this.#attempts++
pendingResponse = fetch(gwUrl.toString(), {
signal,
signal: innerController.signal,
headers: {
Accept: 'application/vnd.ipld.raw'
},
Expand All @@ -122,6 +130,7 @@ export class TrustlessGateway {
this.#errors++
throw new Error(`unable to fetch raw block for CID ${cid}`)
} finally {
signal?.removeEventListener('abort', abortInnerSignal)
this.#pendingResponses.delete(blockId)
}
}
Expand Down

0 comments on commit 5e98950

Please sign in to comment.