Optimize caching of revisions/documents (immutable entries) in memory and cloudflare cache (#252)

* Better handle immutable cache entries in memory/cf-cache

* Format

* Update src/lib/cache/utils.ts

Co-authored-by: Steven H <shne24@gmail.com>

---------

Co-authored-by: Steven H <shne24@gmail.com>
This commit is contained in:
Samy Pessé
2024-03-13 11:54:22 +00:00
committed by GitHub
parent 658eb4d13f
commit 221d85cc4d
5 changed files with 31 additions and 12 deletions
+11 -4
View File
@@ -3,11 +3,10 @@ import { Buffer } from 'node:buffer';
import type { CacheStorage, Cache, Response as WorkerResponse } from '@cloudflare/workers-types';
import { CacheBackend, CacheEntry } from './types';
import { getCacheMaxAge } from './utils';
import { getCacheMaxAge, isCacheEntryImmutable } from './utils';
import { trace } from '../tracing';
const cacheVersion = 1;
const cacheMaxAge = 2 * 60;
/**
* Cache implementation using the Cloudflare Cache API.
@@ -102,8 +101,16 @@ function serializeEntry(entry: CacheEntry): WorkerResponse {
headers.set('Content-Type', 'application/json');
const cacheTags = ['gitbook-open', ...entry.meta.tags];
// Limit the cloudflare cache to a low fix duration
headers.set('Cache-Control', `public, max-age=${getCacheMaxAge(entry.meta, 10, cacheMaxAge)}`);
// When the entry is immutable, we can cache it for the entire duration.
// If the entry can be invalidated, we cache it for maximum 2 minutes as it could be invalidated in another data center.
headers.set(
'Cache-Control',
`public, max-age=${getCacheMaxAge(
entry.meta,
10,
isCacheEntryImmutable(entry.meta) ? 2 * 60 : undefined,
)}`,
);
headers.set('Cache-Tag', cacheTags.join(','));
// @ts-ignore
+11 -6
View File
@@ -1,9 +1,5 @@
import { CacheBackend, CacheEntry } from './types';
/**
* In production, we limit the cache to 5 minutes as it can't be invalidated on all instances.
*/
const cacheMaxAge = process.env.NODE_ENV === 'development' ? Infinity : 5 * 60;
import { isCacheEntryImmutable } from './utils';
export const memoryCache: CacheBackend = {
name: 'memory',
@@ -30,7 +26,16 @@ export const memoryCache: CacheBackend = {
...entry,
meta: {
...entry.meta,
expiresAt: Math.min(Date.now() + cacheMaxAge * 1000, entry.meta.expiresAt),
...(isCacheEntryImmutable(entry.meta) || process.env.NODE_ENV === 'development'
? {}
: {
// For mutable entries, we limit the cache to 1 minute
// as it could be invalidated at any time.
expiresAt: Math.min(
entry.meta.setAt ?? Date.now() + 60 * 1000,
entry.meta.expiresAt,
),
}),
},
});
},
+2 -1
View File
@@ -22,7 +22,8 @@ export interface CacheEntryMeta {
revalidatesAt?: number;
/**
* Tags associated with the entry.
* Tags associated with the entry, used for revalidation.
* If no tags is present, the entry is considered immutable.
*/
tags: string[];
+7
View File
@@ -12,3 +12,10 @@ export function getCacheMaxAge(meta: CacheEntryMeta, min?: number, max?: number)
return maxAge;
}
/**
* Return true if a cache entry can be considered immutable.
*/
export function isCacheEntryImmutable(meta: CacheEntryMeta): boolean {
return !meta.tags || meta.tags.length === 0;
}
-1
View File
@@ -50,7 +50,6 @@ export async function getResizedImageURL(
return () => input;
}
const signature = await generateSignature(input);
if (!signature) {
return () => input;