-
Notifications
You must be signed in to change notification settings - Fork 3
Cache: add the OpenNextCache entrypoint (Cloudflare) #44
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
conico974
wants to merge
1
commit into
conico/cache-1-core-fn
Choose a base branch
from
conico/cache-2-cf-entrypoint
base: conico/cache-1-core-fn
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,27 @@ | ||
| --- | ||
| "@opennextjs/cloudflare": patch | ||
| --- | ||
|
|
||
| Add the `OpenNextCache` named entrypoint | ||
|
|
||
| The build now emits the OpenNext cache handler function and exposes it from the worker as the | ||
| `OpenNextCache` named entrypoint, together with a `service-cache` override that reaches it over a | ||
| service binding. | ||
|
|
||
| This requires a self referencing service binding in the wrangler configuration: | ||
|
|
||
| ```jsonc | ||
| "services": [ | ||
| { | ||
| "binding": "NEXT_CACHE_SERVICE", | ||
| "service": "<your-worker-name>", | ||
| "entrypoint": "OpenNextCache" | ||
| } | ||
| ] | ||
| ``` | ||
|
|
||
| The cache runs in the same worker by default. Pointing the binding at another worker is enough to | ||
| run the cache as a service of its own. | ||
|
|
||
| Nothing selects this override yet - `defineCloudflareConfig` still runs the cache in the server | ||
| function. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
95 changes: 95 additions & 0 deletions
95
packages/cloudflare/src/api/overrides/cache/service-cache.spec.ts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,95 @@ | ||
| import { beforeEach, describe, expect, it, vi } from "vitest"; | ||
|
|
||
| import serviceCache, { BINDING_NAME } from "./service-cache.js"; | ||
|
|
||
| const fetchMock = vi.fn<(input: string, init?: RequestInit) => Promise<Response>>(); | ||
| const env: Record<string, unknown> = {}; | ||
|
|
||
| vi.mock("../../cloudflare-context.js", () => ({ | ||
| getCloudflareContext: () => ({ env }), | ||
| })); | ||
|
|
||
| function lastRequest() { | ||
| const [url, init] = fetchMock.mock.calls.at(-1)!; | ||
| return { url: new URL(url), method: init?.method ?? "GET", body: init?.body }; | ||
| } | ||
|
|
||
| describe("serviceCache", () => { | ||
| beforeEach(() => { | ||
| fetchMock.mockReset(); | ||
| fetchMock.mockResolvedValue(new Response("", { headers: { "x-opennext-cache-found": "false" } })); | ||
| env[BINDING_NAME] = { fetch: fetchMock }; | ||
| }); | ||
|
|
||
| it("throws when the service is not bound", async () => { | ||
| delete env[BINDING_NAME]; | ||
|
|
||
| await expect(serviceCache.get("key")).rejects.toThrow(BINDING_NAME); | ||
| }); | ||
|
|
||
| describe("get", () => { | ||
| it("requests the key and the cache type", async () => { | ||
| await serviceCache.get("key/with/slashes", "fetch"); | ||
|
|
||
| const { url, method } = lastRequest(); | ||
| expect(method).toBe("GET"); | ||
| expect(url.pathname).toBe(`/cache/${encodeURIComponent("key/with/slashes")}`); | ||
| expect(url.searchParams.get("type")).toBe("fetch"); | ||
| }); | ||
|
|
||
| it("returns null on a cache miss", async () => { | ||
| await expect(serviceCache.get("key")).resolves.toBeNull(); | ||
| }); | ||
|
|
||
| it("parses a cache hit", async () => { | ||
| fetchMock.mockResolvedValue( | ||
| new Response("body", { | ||
| headers: { | ||
| "x-opennext-cache-found": "true", | ||
| "x-opennext-cache-type": "cache", | ||
| "x-opennext-cache-sub-type": "route", | ||
| "x-opennext-cache-last-modified": "1234", | ||
| }, | ||
| }) | ||
| ); | ||
|
|
||
| await expect(serviceCache.get("key")).resolves.toEqual({ | ||
| lastModified: 1234, | ||
| value: expect.objectContaining({ type: "route", body: "body" }), | ||
| }); | ||
| }); | ||
| }); | ||
|
|
||
| describe("set", () => { | ||
| // The cache type is part of the key for the incremental caches, it has to be forwarded | ||
| // or entries would be written where they are not read from. | ||
| it("sends the value and the cache type", async () => { | ||
| await serviceCache.set("key", { kind: "FETCH", data: { headers: {}, body: "b", url: "u" } }, "fetch"); | ||
|
|
||
| const { url, method, body } = lastRequest(); | ||
| expect(method).toBe("PUT"); | ||
| expect(url.pathname).toBe("/cache/key"); | ||
| expect(url.searchParams.get("type")).toBe("fetch"); | ||
| expect(JSON.parse(body as string)).toEqual({ | ||
| value: { kind: "FETCH", data: { headers: {}, body: "b", url: "u" } }, | ||
| }); | ||
| }); | ||
| }); | ||
|
|
||
| it("deletes a key", async () => { | ||
| await serviceCache.delete("key"); | ||
|
|
||
| const { url, method } = lastRequest(); | ||
| expect(method).toBe("DELETE"); | ||
| expect(url.pathname).toBe("/cache/key"); | ||
| }); | ||
|
|
||
| it("revalidates tags", async () => { | ||
| await serviceCache.revalidateTags(["tag1", "tag2"]); | ||
|
|
||
| const { url, method, body } = lastRequest(); | ||
| expect(method).toBe("POST"); | ||
| expect(url.pathname).toBe("/cache/revalidate-tags"); | ||
| expect(JSON.parse(body as string)).toEqual({ tags: ["tag1", "tag2"] }); | ||
| }); | ||
| }); |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🟡 Cache service binding is missing for the R2 example when an environment is used
The cache binding is declared only at the top level of the R2 example's configuration (
servicesblock atexamples-cloudflare/overrides/r2-incremental-cache/wrangler.jsonc:11-17) while each named environment declares its own service list, so the binding disappears whenever the example is deployed or previewed with an environment.Impact: The R2 example run under its
e2eorprodenvironment has no cache service binding, so once the cache override is enabled there the cache calls would fail at runtime.Wrangler environments do not inherit binding lists
In wrangler, binding sections (
services,kv_namespaces,r2_buckets, ...) are not inheritable: when an environment defines its ownservices(hereenv.e2e.serviceswith onlyWORKER_SELF_REFERENCE), the top-level list is replaced entirely. The newly added top-level entry also points at"r2-incremental-cache", while the worker name under thee2eenvironment isr2-incremental-cache-e2e, so even if it were inherited it would not self-reference correctly (compare with theWORKER_SELF_REFERENCEentry insideenv.e2e, which uses the suffixed name).The binding should be added inside each environment's
serviceslist (with the environment-suffixed worker name) rather than only at the top level.Was this helpful? React with 👍 or 👎 to provide feedback.