-
Notifications
You must be signed in to change notification settings - Fork 11
perf: Cache HTTP requests across all pages #174
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -184,8 +184,12 @@ const createCheckAliveURL = (ruleOptions: Options, resolvePath: (path: string, b | |
| // and see what kind of redirect is occurring | ||
| redirect: "manual" as RequestRedirect | ||
| }; | ||
|
|
||
| // Declare the variable outside the try-catch block to ensure the body is always consumed in `finally`. | ||
| let res: Response | null = null; | ||
|
|
||
| try { | ||
| const res = await fetchWithDefaults(uri, opts); | ||
| res = await fetchWithDefaults(uri, opts); | ||
| const errorResult = { | ||
| ok: false, | ||
| redirected: true, | ||
|
|
@@ -214,6 +218,7 @@ const createCheckAliveURL = (ruleOptions: Options, resolvePath: (path: string, b | |
| const finalRes = await fetchWithDefaults(redirectedUrl, { ...opts, redirect: "follow" }); | ||
| const url = URL.parse(uri); | ||
| const hash = url?.hash || null; | ||
| await finalRes.body?.cancel(); | ||
| return { | ||
| ok: finalRes.ok, | ||
| redirected: true, | ||
|
|
@@ -264,6 +269,10 @@ const createCheckAliveURL = (ruleOptions: Options, resolvePath: (path: string, b | |
| ok: false, | ||
| message: ex.message | ||
| }; | ||
| } finally { | ||
| if (res && !res.body?.locked) { | ||
| await res.body?.cancel(); | ||
| } | ||
| } | ||
| }; | ||
| }; | ||
|
|
@@ -289,6 +298,11 @@ async function isAliveLocalFile(filePath: string): Promise<AliveFunctionReturn> | |
| } | ||
| } | ||
|
|
||
| const memorizedIsAliveURIByOptions = new Map< | ||
| string, | ||
| ReturnType<typeof pMemoize<ReturnType<typeof createCheckAliveURL>>> | ||
| >(); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If you have a Cache Map globally, you will behave like a memory leak if you don't condition it by size or TTL like LRU Cache.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The function
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 📝 |
||
|
|
||
| const reporter: TextlintRuleReporter<Options> = (context, options) => { | ||
| const { Syntax, getSource, report, RuleError, fixer, getFilePath, locator } = context; | ||
| const helper = new RuleHelper(context); | ||
|
|
@@ -307,10 +321,21 @@ const reporter: TextlintRuleReporter<Options> = (context, options) => { | |
| } | ||
| } | ||
| }; | ||
| const isAliveURI = createCheckAliveURL(ruleOptions, resolvePath); | ||
| const memorizedIsAliveURI = pMemoize(isAliveURI, { | ||
| maxAge: ruleOptions.linkMaxAge | ||
| }); | ||
| const memorizedIsAliveURI = (() => { | ||
| const memoOptionsKey = JSON.stringify(ruleOptions); | ||
| const func = memorizedIsAliveURIByOptions.get(memoOptionsKey); | ||
| if (!func) { | ||
| const isAliveURI = createCheckAliveURL(ruleOptions, resolvePath); | ||
| const func = pMemoize(isAliveURI, { | ||
| maxAge: ruleOptions.linkMaxAge | ||
| }); | ||
| memorizedIsAliveURIByOptions.set(memoOptionsKey, func); | ||
| return func; | ||
| } | ||
|
|
||
| return func; | ||
| })(); | ||
|
|
||
| /** | ||
| * Checks a given URI's availability and report if it is dead. | ||
| * @param {TextLintNode} node TextLintNode the URI belongs to. | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it okay to understand that this change has nothing to do with Cache?
https://github.com/nodejs/undici?tab=readme-ov-file#garbage-collection
I feel like it's good to explicitly consume because you can't rely on GC with Node fetch
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, in my environment, after placing the cache globally, it started hanging occasionally. Therefore, I believe it is appropriate to include this change in this PR.