@safaricom-mxl/nextjs-turbo-redis-cache
Version:
Next.js redis cache handler
154 lines (150 loc) • 5.72 kB
text/typescript
import { RedisClientOptions } from 'redis';
type CacheEntry = {
value: unknown;
lastModified: number;
tags: string[];
};
type CreateRedisStringsHandlerOptions = {
/** Redis redisUrl to use.
* @default process.env.REDIS_URL? process.env.REDIS_URL : process.env.REDISHOST
? `redis://${process.env.REDISHOST}:${process.env.REDISPORT}`
: 'redis://localhost:6379'
*/
redisUrl?: string;
/** Redis database number to use. Uses DB 0 for production, DB 1 otherwise
* @default process.env.VERCEL_ENV === 'production' ? 0 : 1
*/
database?: number;
/** Prefix added to all Redis keys
* @default process.env.VERCEL_URL || 'UNDEFINED_URL_'
*/
keyPrefix?: string;
/** Timeout in milliseconds for time critical Redis operations (during cache get, which blocks site rendering).
* If redis get is not fulfilled within this time, the cache handler will return null so site rendering will
* not be blocked further and site can fallback to re-render/re-fetch the content.
* @default 500
*/
getTimeoutMs?: number;
/** Number of entries to query in one batch during full sync of shared tags hash map
* @default 250
*/
revalidateTagQuerySize?: number;
/** Key used to store shared tags hash map in Redis
* @default '__sharedTags__'
*/
sharedTagsKey?: string;
/** Average interval in milliseconds between tag map full re-syncs
* @default 3600000 (1 hour)
*/
avgResyncIntervalMs?: number;
/** Enable deduplication of Redis get requests via internal in-memory cache
* @default true
*/
redisGetDeduplication?: boolean;
/** Time in milliseconds to cache Redis get results in memory. Set this to 0 to disable in-memory caching completely
* @default 10000
*/
inMemoryCachingTime?: number;
/** Default stale age in seconds for cached items
* @default 1209600 (14 days)
*/
defaultStaleAge?: number;
/** Function to calculate expire age (redis TTL value) from stale age
* @default Production: staleAge * 2, Other: staleAge * 1.2
*/
estimateExpireAge?: (staleAge: number) => number;
/** Kill container on Redis client error if error threshold is reached
* @default 0 (0 means no error threshold)
*/
killContainerOnErrorThreshold?: number;
/** Additional Redis client socket options
* @example { tls: true, rejectUnauthorized: false }
*/
socketOptions?: RedisClientOptions["socket"];
/** Additional Redis client options to be passed directly to createClient
* @example { username: 'user', password: 'pass' }
*/
clientOptions?: Omit<RedisClientOptions, "url" | "database" | "socket">;
};
declare class RedisStringsHandler {
private client;
private sharedTagsMap;
private revalidatedTagsMap;
private inMemoryDeduplicationCache;
private getTimeoutMs;
private redisGet;
private redisDeduplicationHandler;
private deduplicatedRedisGet;
private keyPrefix;
private redisGetDeduplication;
private inMemoryCachingTime;
private defaultStaleAge;
private estimateExpireAge;
private killContainerOnErrorThreshold;
constructor({ redisUrl, database, keyPrefix, sharedTagsKey, getTimeoutMs, revalidateTagQuerySize, avgResyncIntervalMs, redisGetDeduplication, inMemoryCachingTime, defaultStaleAge, estimateExpireAge, killContainerOnErrorThreshold, socketOptions, clientOptions, }: CreateRedisStringsHandlerOptions);
resetRequestCache(): void;
close(): Promise<void>;
private clientReadyCalls;
private assertClientIsReady;
get(key: string, ctx: {
kind: "APP_ROUTE" | "APP_PAGE";
isRoutePPREnabled: boolean;
isFallback: boolean;
} | {
kind: "FETCH";
revalidate: number;
fetchUrl: string;
fetchIdx: number;
tags: string[];
softTags: string[];
isFallback: boolean;
}): Promise<CacheEntry | null>;
set(key: string, data: {
kind: "APP_PAGE";
status: number;
headers: {
"x-nextjs-stale-time": string;
"x-next-cache-tags": string;
};
html: string;
rscData: Buffer;
segmentData: unknown;
postboned: unknown;
} | {
kind: "APP_ROUTE";
status: number;
headers: {
"cache-control"?: string;
"x-nextjs-stale-time": string;
"x-next-cache-tags": string;
};
body: Buffer;
} | {
kind: "FETCH";
data: {
headers: Record<string, string>;
body: string;
status: number;
url: string;
};
revalidate: number | false;
}, ctx: {
isRoutePPREnabled: boolean;
isFallback: boolean;
tags?: string[];
revalidate?: number | false;
cacheControl?: {
revalidate: 5;
expire: undefined;
};
}): Promise<void>;
revalidateTag(tagOrTags: string | string[], ...rest: any[]): Promise<void>;
}
declare class CachedHandler {
constructor(options: CreateRedisStringsHandlerOptions);
get(...args: Parameters<RedisStringsHandler["get"]>): ReturnType<RedisStringsHandler["get"]>;
set(...args: Parameters<RedisStringsHandler["set"]>): ReturnType<RedisStringsHandler["set"]>;
revalidateTag(...args: Parameters<RedisStringsHandler["revalidateTag"]>): ReturnType<RedisStringsHandler["revalidateTag"]>;
resetRequestCache(...args: Parameters<RedisStringsHandler["resetRequestCache"]>): ReturnType<RedisStringsHandler["resetRequestCache"]>;
}
export { RedisStringsHandler, CachedHandler as default };