Skip to content

Commit d2d2bf9

Browse files
authored
fix: mark file system incremental cache as external so it's memory is shared (#80586)
This moves the in-memory LRU cache on the file system cache handler as external so that it's shared between different instances of the file system cache module.
1 parent 77c4546 commit d2d2bf9

File tree

2 files changed

+52
-40
lines changed

2 files changed

+52
-40
lines changed

packages/next/src/server/lib/incremental-cache/file-system-cache.ts

Lines changed: 18 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import type { RouteMetadata } from '../../../export/routes/types'
2-
import type { CacheHandler, CacheHandlerContext, CacheHandlerValue } from './'
2+
import type { CacheHandler, CacheHandlerContext, CacheHandlerValue } from '.'
33
import type { CacheFs } from '../../../shared/lib/utils'
44
import {
55
CachedRouteKind,
@@ -10,7 +10,7 @@ import {
1010
type SetIncrementalResponseCacheContext,
1111
} from '../../response-cache'
1212

13-
import { LRUCache } from '../lru-cache'
13+
import type { LRUCache } from '../lru-cache'
1414
import path from '../../../shared/lib/isomorphic/path'
1515
import {
1616
NEXT_CACHE_TAGS_HEADER,
@@ -23,6 +23,7 @@ import {
2323
} from '../../../lib/constants'
2424
import { isStale, tagsManifest } from './tags-manifest.external'
2525
import { MultiFileWriter } from '../../../lib/multi-file-writer'
26+
import { getMemoryCache } from './memory-cache.external'
2627

2728
type FileSystemCacheContext = Omit<
2829
CacheHandlerContext,
@@ -32,54 +33,31 @@ type FileSystemCacheContext = Omit<
3233
serverDistDir: string
3334
}
3435

35-
let memoryCache: LRUCache<CacheHandlerValue> | undefined
36-
3736
export default class FileSystemCache implements CacheHandler {
3837
private fs: FileSystemCacheContext['fs']
3938
private flushToDisk?: FileSystemCacheContext['flushToDisk']
4039
private serverDistDir: FileSystemCacheContext['serverDistDir']
4140
private revalidatedTags: string[]
42-
private debug: boolean
41+
private static debug: boolean = !!process.env.NEXT_PRIVATE_DEBUG_CACHE
42+
private static memoryCache: LRUCache<CacheHandlerValue> | undefined
4343

4444
constructor(ctx: FileSystemCacheContext) {
4545
this.fs = ctx.fs
4646
this.flushToDisk = ctx.flushToDisk
4747
this.serverDistDir = ctx.serverDistDir
4848
this.revalidatedTags = ctx.revalidatedTags
49-
this.debug = !!process.env.NEXT_PRIVATE_DEBUG_CACHE
5049

5150
if (ctx.maxMemoryCacheSize) {
52-
if (!memoryCache) {
53-
if (this.debug) {
51+
if (!FileSystemCache.memoryCache) {
52+
if (FileSystemCache.debug) {
5453
console.log('using memory store for fetch cache')
5554
}
5655

57-
memoryCache = new LRUCache(ctx.maxMemoryCacheSize, function length({
58-
value,
59-
}) {
60-
if (!value) {
61-
return 25
62-
} else if (value.kind === CachedRouteKind.REDIRECT) {
63-
return JSON.stringify(value.props).length
64-
} else if (value.kind === CachedRouteKind.IMAGE) {
65-
throw new Error('invariant image should not be incremental-cache')
66-
} else if (value.kind === CachedRouteKind.FETCH) {
67-
return JSON.stringify(value.data || '').length
68-
} else if (value.kind === CachedRouteKind.APP_ROUTE) {
69-
return value.body.length
70-
}
71-
// rough estimate of size of cache value
72-
return (
73-
value.html.length +
74-
(JSON.stringify(
75-
value.kind === CachedRouteKind.APP_PAGE
76-
? value.rscData
77-
: value.pageData
78-
)?.length || 0)
79-
)
80-
})
56+
FileSystemCache.memoryCache = getMemoryCache(ctx.maxMemoryCacheSize)
57+
} else if (FileSystemCache.debug) {
58+
console.log('memory store already initialized')
8159
}
82-
} else if (this.debug) {
60+
} else if (FileSystemCache.debug) {
8361
console.log('not using memory store for fetch cache')
8462
}
8563
}
@@ -92,7 +70,7 @@ export default class FileSystemCache implements CacheHandler {
9270
let [tags] = args
9371
tags = typeof tags === 'string' ? [tags] : tags
9472

95-
if (this.debug) {
73+
if (FileSystemCache.debug) {
9674
console.log('revalidateTag', tags)
9775
}
9876

@@ -111,9 +89,9 @@ export default class FileSystemCache implements CacheHandler {
11189
const [key, ctx] = args
11290
const { kind } = ctx
11391

114-
let data = memoryCache?.get(key)
92+
let data = FileSystemCache.memoryCache?.get(key)
11593

116-
if (this.debug) {
94+
if (FileSystemCache.debug) {
11795
if (kind === IncrementalCacheKind.FETCH) {
11896
console.log('get', key, ctx.tags, kind, !!data)
11997
} else {
@@ -182,7 +160,7 @@ export default class FileSystemCache implements CacheHandler {
182160
// TODO: remove this when we can send the tags
183161
// via header on GET same as SET
184162
if (!tags?.every((tag) => storedTags?.includes(tag))) {
185-
if (this.debug) {
163+
if (FileSystemCache.debug) {
186164
console.log('tags vs storedTags mismatch', tags, storedTags)
187165
}
188166
await this.set(key, data.value, {
@@ -291,7 +269,7 @@ export default class FileSystemCache implements CacheHandler {
291269
}
292270

293271
if (data) {
294-
memoryCache?.set(key, data)
272+
FileSystemCache.memoryCache?.set(key, data)
295273
}
296274
} catch {
297275
return null
@@ -345,12 +323,12 @@ export default class FileSystemCache implements CacheHandler {
345323
data: IncrementalCacheValue | null,
346324
ctx: SetIncrementalFetchCacheContext | SetIncrementalResponseCacheContext
347325
) {
348-
memoryCache?.set(key, {
326+
FileSystemCache.memoryCache?.set(key, {
349327
value: data,
350328
lastModified: Date.now(),
351329
})
352330

353-
if (this.debug) {
331+
if (FileSystemCache.debug) {
354332
console.log('set', key)
355333
}
356334

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import type { CacheHandlerValue } from '.'
2+
import { CachedRouteKind } from '../../response-cache/types'
3+
import { LRUCache } from '../lru-cache'
4+
5+
let memoryCache: LRUCache<CacheHandlerValue> | undefined
6+
7+
export function getMemoryCache(maxMemoryCacheSize: number) {
8+
if (!memoryCache) {
9+
memoryCache = new LRUCache(maxMemoryCacheSize, function length({ value }) {
10+
if (!value) {
11+
return 25
12+
} else if (value.kind === CachedRouteKind.REDIRECT) {
13+
return JSON.stringify(value.props).length
14+
} else if (value.kind === CachedRouteKind.IMAGE) {
15+
throw new Error('invariant image should not be incremental-cache')
16+
} else if (value.kind === CachedRouteKind.FETCH) {
17+
return JSON.stringify(value.data || '').length
18+
} else if (value.kind === CachedRouteKind.APP_ROUTE) {
19+
return value.body.length
20+
}
21+
// rough estimate of size of cache value
22+
return (
23+
value.html.length +
24+
(JSON.stringify(
25+
value.kind === CachedRouteKind.APP_PAGE
26+
? value.rscData
27+
: value.pageData
28+
)?.length || 0)
29+
)
30+
})
31+
}
32+
33+
return memoryCache
34+
}

0 commit comments

Comments
 (0)