Skip to content

Commit da419fd

Browse files
author
Peter Bengtsson
authored
Memoize loadRedirects() with disk (github#22161)
* memoize loadRedirects with disk in development * no need to await on sync functions * un-uncomment * wip * wip * cache with max age * rename redirects memoize cache file
1 parent 711bd22 commit da419fd

File tree

2 files changed

+48
-17
lines changed

2 files changed

+48
-17
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,4 @@ coverage/
1515
blc_output.log
1616
blc_output_internal.log
1717
broken_links.md
18+
lib/redirects/.redirects-cache_*.json

lib/redirects/precompile.js

Lines changed: 47 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,53 @@
1-
import { languageKeys } from '../languages.js'
1+
import assert from 'assert'
2+
import fs from 'fs/promises'
3+
import path from 'path'
4+
import { isPromise } from 'util/types'
5+
import { fileURLToPath } from 'url'
6+
27
import readJsonFile from '../read-json-file.js'
38
import { latest } from '../../lib/enterprise-server-releases.js'
49
import getExceptionRedirects from './exception-redirects.js'
5-
const developerRedirects = readJsonFile('./lib/redirects/static/developer.json')
6-
const latestDevRedirects = {}
7-
8-
// Replace hardcoded 'latest' with real value in the redirected path
9-
Object.entries(developerRedirects).forEach(([oldPath, newPath]) => {
10-
latestDevRedirects[oldPath] = newPath.replace(
11-
'enterprise-server@latest',
12-
`enterprise-server@${latest}`
13-
)
14-
})
10+
import { languageKeys } from '../languages.js'
11+
12+
function diskMemoize(filePath, asyncFn, maxAgeSeconds = 60 * 60) {
13+
return async (...args) => {
14+
try {
15+
const stats = await fs.stat(filePath)
16+
const ageSeconds = (new Date().getTime() - stats.mtime.getTime()) / 1000
17+
if (ageSeconds < maxAgeSeconds) {
18+
const value = JSON.parse(await fs.readFile(filePath, 'utf-8'))
19+
console.log(`Redirects disk-cache HIT on ${filePath}`)
20+
return value
21+
}
22+
console.log(`Redirects disk-cache ${filePath} too old`)
23+
} catch (err) {
24+
if (err.code !== 'ENOENT') throw err
25+
}
26+
console.log(`Redirects disk-cache MISS on ${filePath}`)
27+
const promise = asyncFn(...args)
28+
assert(isPromise(promise), "memoized function didn't return a promise")
29+
return promise.then(async (value) => {
30+
await fs.writeFile(filePath, JSON.stringify(value), 'utf-8')
31+
return value
32+
})
33+
}
34+
}
35+
36+
const __dirname = path.dirname(fileURLToPath(import.meta.url))
37+
const DISK_CACHE_FILEPATH = path.join(__dirname, `.redirects-cache_${languageKeys.join('_')}.json`)
1538

1639
// This function runs at server warmup and precompiles possible redirect routes.
1740
// It outputs them in key-value pairs within a neat Javascript object: { oldPath: newPath }
18-
export default async function precompileRedirects(pageList) {
19-
const allRedirects = Object.assign({}, latestDevRedirects)
41+
const precompileRedirects = diskMemoize(DISK_CACHE_FILEPATH, async (pageList) => {
42+
const allRedirects = readJsonFile('./lib/redirects/static/developer.json')
43+
44+
// Replace hardcoded 'latest' with real value in the redirected path
45+
Object.entries(allRedirects).forEach(([oldPath, newPath]) => {
46+
allRedirects[oldPath] = newPath.replace(
47+
'enterprise-server@latest',
48+
`enterprise-server@${latest}`
49+
)
50+
})
2051

2152
// Exception redirects are those that are essentially unicorn one-offs.
2253
// For example, we have redirects for documents that used to be on
@@ -35,9 +66,8 @@ export default async function precompileRedirects(pageList) {
3566

3667
// CURRENT PAGES PERMALINKS AND FRONTMATTER
3768
// create backwards-compatible old paths for page permalinks and frontmatter redirects
38-
await Promise.all(
39-
pageList.map(async (page) => Object.assign(allRedirects, page.buildRedirects()))
40-
)
69+
pageList.forEach((page) => Object.assign(allRedirects, page.buildRedirects()))
4170

4271
return allRedirects
43-
}
72+
})
73+
export default precompileRedirects

0 commit comments

Comments
 (0)