Skip to content

Commit

Permalink
refactor: retrieve cache handler kv instance inside constructor
Browse files Browse the repository at this point in the history
  • Loading branch information
james-elicx committed Oct 7, 2024
1 parent 8f36d47 commit d935d9c
Show file tree
Hide file tree
Showing 10 changed files with 42 additions and 21 deletions.
7 changes: 7 additions & 0 deletions .changeset/slow-dolphins-sparkle.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
"@opennextjs/cloudflare": patch
---

refactor: retrieve cache handler kv instance inside constructor

The cache handler was retrieving it's KV instance as a static property on the class that was defined at some point during the execution of the Next.js server. This moves the retrieval of the KV instance to happen inside the constructor for the class, so that it is retrieved during instantiation instead.
1 change: 1 addition & 0 deletions packages/cloudflare/env.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ declare global {
__NEXT_PRIVATE_STANDALONE_CONFIG?: string;
SKIP_NEXT_APP_BUILD?: string;
NEXT_PRIVATE_DEBUG_CACHE?: string;
__OPENNEXT_KV_BINDING_NAME: string;
[key: string]: string | Fetcher;
}
}
Expand Down
19 changes: 17 additions & 2 deletions packages/cloudflare/src/cli/build/build-worker.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Plugin, build } from "esbuild";
import { cacheHandlerFileName, patchCache } from "./patches/investigated/patch-cache";
import { cp, readFile, writeFile } from "node:fs/promises";
import { existsSync, readFileSync } from "node:fs";
import { Config } from "../config";
Expand All @@ -8,7 +9,6 @@ import { fileURLToPath } from "node:url";
import { inlineEvalManifest } from "./patches/to-investigate/inline-eval-manifest";
import { inlineMiddlewareManifestRequire } from "./patches/to-investigate/inline-middleware-manifest-require";
import { inlineNextRequire } from "./patches/to-investigate/inline-next-require";
import { patchCache } from "./patches/investigated/patch-cache";
import { patchExceptionBubbling } from "./patches/to-investigate/patch-exception-bubbling";
import { patchFindDir } from "./patches/to-investigate/patch-find-dir";
import { patchReadFile } from "./patches/to-investigate/patch-read-file";
Expand Down Expand Up @@ -53,6 +53,9 @@ export async function buildWorker(config: Config): Promise<void> {

const templateDir = path.join(config.paths.internalPackage, "cli", "templates");

const cacheHandlerEntrypoint = path.join(templateDir, "cache-handler", "index.ts");
const cacheHandlerOutputFile = path.join(config.paths.builderOutput, cacheHandlerFileName);

const workerEntrypoint = path.join(templateDir, "worker.ts");
const workerOutputFile = path.join(config.paths.builderOutput, "index.mjs");

Expand All @@ -66,6 +69,18 @@ export async function buildWorker(config: Config): Promise<void> {
patchWranglerDeps(config);
updateWebpackChunksFile(config);

await build({
entryPoints: [cacheHandlerEntrypoint],
bundle: true,
outfile: cacheHandlerOutputFile,
format: "esm",
target: "esnext",
minify: true,
define: {
"process.env.__OPENNEXT_KV_BINDING_NAME": `"${config.cache.kvBindingName}"`,
},
});

await build({
entryPoints: [workerEntrypoint],
bundle: true,
Expand Down Expand Up @@ -167,7 +182,7 @@ async function updateWorkerBundledCode(workerOutputFile: string, config: Config)
patchedCode = inlineNextRequire(patchedCode, config);
patchedCode = patchFindDir(patchedCode, config);
patchedCode = inlineEvalManifest(patchedCode, config);
patchedCode = patchCache(patchedCode, config);
patchedCode = patchCache(patchedCode);
patchedCode = inlineMiddlewareManifestRequire(patchedCode, config);
patchedCode = patchExceptionBubbling(patchedCode);

Expand Down
Original file line number Diff line number Diff line change
@@ -1,24 +1,20 @@
import { Config } from "../../../config";
import path from "node:path";
export const cacheHandlerFileName = "cache-handler.mjs";

/**
* Install the cloudflare KV cache handler
*/
export function patchCache(code: string, config: Config): string {
export function patchCache(code: string): string {
console.log("# patchCache");

const cacheHandler = path.join(config.paths.internalPackage, "cli", "cache-handler", "index.mjs");

const patchedCode = code.replace(
"const { cacheHandler } = this.nextConfig;",
`const cacheHandler = null;
CacheHandler = (await import('${cacheHandler}')).OpenNextCacheHandler;
CacheHandler.maybeKVNamespace = process.env["${config.cache.kvBindingName}"];
CacheHandler = (await import('./${cacheHandlerFileName}')).OpenNextCacheHandler;
`
);

if (patchedCode === code) {
throw new Error("Cache patch not applied");
throw new Error("Patch `patchCache` not applied");
}

return patchedCode;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { NEXT_META_SUFFIX, SEED_DATA_DIR } from "../../cache-handler";
import { NEXT_META_SUFFIX, SEED_DATA_DIR } from "../../templates/cache-handler";
import { copyFileSync, existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
import { dirname, join } from "node:path";
import { Config } from "../../config";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,29 +13,31 @@ import {
} from "./constants";
import { getSeedBodyFile, getSeedMetaFile, getSeedTextFile, parseCtx } from "./utils";
import type { IncrementalCacheValue } from "next/dist/server/response-cache";
import { KVNamespace } from "@cloudflare/workers-types";
import type { KVNamespace } from "@cloudflare/workers-types";

type CacheEntry = {
lastModified: number;
value: IncrementalCacheValue | null;
};

export class OpenNextCacheHandler implements CacheHandler {
static maybeKVNamespace: KVNamespace | undefined = undefined;
protected kv: KVNamespace | undefined;

protected debug: boolean = !!process.env.NEXT_PRIVATE_DEBUG_CACHE;

constructor(protected ctx: CacheHandlerContext) {}
constructor(protected ctx: CacheHandlerContext) {
this.kv = process.env[process.env.__OPENNEXT_KV_BINDING_NAME] as KVNamespace | undefined;
}

async get(...args: Parameters<CacheHandler["get"]>): Promise<CacheHandlerValue | null> {
const [key, _ctx] = args;
const ctx = parseCtx(_ctx);

if (this.debug) console.log(`cache - get: ${key}, ${ctx?.kind}`);

if (OpenNextCacheHandler.maybeKVNamespace !== undefined) {
if (this.kv !== undefined) {
try {
const value = await OpenNextCacheHandler.maybeKVNamespace.get<CacheEntry>(key, "json");
const value = await this.kv.get<CacheEntry>(key, "json");
if (value) return value;
} catch (e) {
console.error(`Failed to get value for key = ${key}: ${e}`);
Expand Down Expand Up @@ -115,7 +117,7 @@ export class OpenNextCacheHandler implements CacheHandler {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const [key, entry, _ctx] = args;

if (OpenNextCacheHandler.maybeKVNamespace === undefined) {
if (this.kv === undefined) {
return;
}

Expand All @@ -127,15 +129,15 @@ export class OpenNextCacheHandler implements CacheHandler {
};

try {
await OpenNextCacheHandler.maybeKVNamespace.put(key, JSON.stringify(data));
await this.kv.put(key, JSON.stringify(data));
} catch (e) {
console.error(`Failed to set value for key = ${key}: ${e}`);
}
}

async revalidateTag(...args: Parameters<CacheHandler["revalidateTag"]>) {
const [tags] = args;
if (OpenNextCacheHandler.maybeKVNamespace === undefined) {
if (this.kv === undefined) {
return;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { IncrementalCache } from "next/dist/server/lib/incremental-cache";
import type { IncrementalCache } from "next/dist/server/lib/incremental-cache";
import { NEXT_META_SUFFIX } from "./constants";

type PrerenderedRouteMeta = {
Expand Down
2 changes: 1 addition & 1 deletion packages/cloudflare/tsup.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { cp } from "node:fs/promises";
import { defineConfig } from "tsup";

const cliConfig = defineConfig({
entry: ["src/cli/index.ts", "src/cli/cache-handler/index.ts"],
entry: ["src/cli/index.ts"],
outDir: "dist/cli",
dts: false,
format: ["esm"],
Expand Down

0 comments on commit d935d9c

Please sign in to comment.