fix(cloudflare): pass waitUntil to cache providers#16187
Conversation
🦋 Changeset detectedLatest commit: 57abd56 The changes in this PR will be included in the next version bump. Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
|
Thanks for this - the same fix is relevant to the other hosting integrations (Netlify + Vercel), I think (both support https://github.com/gllmt/astro/blob/main/packages/integrations/netlify/src/ssr-function.ts#L36 |
|
Thanks, I agree the same plumbing may also apply to Netlify and Vercel. I scoped this PR to #16145 since that issue is currently labeled |
|
Any chance of a maintainer reviewing/progressing this soon? Would be great to get this fix in. Thanks! |
ematipico
left a comment
There was a problem hiding this comment.
The code looks good, but I'm afraid we can't merge it as is. We're adding a new API, which means:
- changesets need to be
minor(at least the astro one) - the changeset needs to add a more comprehensive description https://contribute.docs.astro.build/docs-for-code-changes/changesets/
- we need you to send a PR to the docs repository
withastro/docsand update this page with the new option https://docs.astro.build/en/reference/modules/astro-app/#renderoptions
| const response = await app.render(request, { | ||
| routeData, | ||
| locals, | ||
| waitUntil: context.waitUntil.bind(context), |
There was a problem hiding this comment.
I believe this might be correct, but it doesn't hold against the types of waitUntil. You typed waitUntil with a small function that doesn't type the this.
There was a problem hiding this comment.
Thanks, that makes sense.
I initially treated this as plumbing to match the already-documented CacheProvider.onRequest() context, but exposing waitUntil through app.render() / RenderOptions does make it a public API surface.
I’ll update the waitUntil typing, promote the astro changeset to minor with a fuller description, and open a docs PR against withastro/docs for the astro-app RenderOptions page, then link it back here.
I’ll keep the implementation scope focused on Cloudflare in this PR and can follow up separately for the other adapters if that’s preferred.
There was a problem hiding this comment.
Updated this so the public waitUntil contract is a dedicated bound callback type (this: void), and the Cloudflare adapter now passes a bound function typed against RenderOptions['waitUntil'] instead of leaving it as an ad-hoc callback shape.
|
Addressed the requested follow-up changes:
Re-ran:
Docs verification:
I kept the implementation scope focused on Cloudflare here; happy to follow up separately for the other adapters if that’s preferred. |
Co-authored-by: Armand Philippot <[email protected]>
|
Fixed the lint failure. Root cause: after the Cloudflare test suite was migrated to TypeScript on this branch, this new test was still left as Updated it to Re-ran locally:
|
ArmandPhilippot
left a comment
There was a problem hiding this comment.
Just a nit for the changeset, but otherwise this LGTM! Thank you!
Co-authored-by: Armand Philippot <[email protected]>
This comment has been minimized.
This comment has been minimized.
This PR contains the following updates: | Package | Change | [Age](https://docs.renovatebot.com/merge-confidence/) | [Confidence](https://docs.renovatebot.com/merge-confidence/) | |---|---|---|---| | [astro](https://astro.build) ([source](https://github.com/withastro/astro/tree/HEAD/packages/astro)) | [`6.1.10` → `6.2.1`](https://renovatebot.com/diffs/npm/astro/6.1.10/6.2.1) |  |  | --- ### Release Notes <details> <summary>withastro/astro (astro)</summary> ### [`v6.2.1`](https://github.com/withastro/astro/blob/HEAD/packages/astro/CHANGELOG.md#621) [Compare Source](https://github.com/withastro/astro/compare/[email protected]@6.2.1) ##### Patch Changes - [#​16531](withastro/astro#16531) [`76db01d`](withastro/astro@76db01d) Thanks [@​rodrigosdev](https://github.com/rodrigosdev)! - Fixes config validation for omitted `integrations` fields with newer Zod versions. - [#​16535](withastro/astro#16535) [`7df0fe4`](withastro/astro@7df0fe4) Thanks [@​rururux](https://github.com/rururux)! - Fixed an issue where a warning was displayed when the `server` property was missing during config validation, even though it is not required. - [#​16534](withastro/astro#16534) [`5cf6c51`](withastro/astro@5cf6c51) Thanks [@​matthewp](https://github.com/matthewp)! - Fixes compatibility with Zod 4.4.0 for the `server` config property and error formatting ### [`v6.2.0`](https://github.com/withastro/astro/blob/HEAD/packages/astro/CHANGELOG.md#620) [Compare Source](https://github.com/withastro/astro/compare/[email protected]@6.2.0) ##### Minor Changes - [#​16187](withastro/astro#16187) [`fe58071`](withastro/astro@fe58071) Thanks [@​gllmt](https://github.com/gllmt)! - Adds a `waitUntil` option to the `RenderOptions` so that adapters can forward runtime background-task hooks to Astro. When provided by an adapter, runtime cache providers receive `context.waitUntil` in `CacheProvider.onRequest()`, which allows background cache work such as stale-while-revalidate without blocking the response. The Cloudflare adapter now forwards `ExecutionContext.waitUntil` to this API. - [#​16290](withastro/astro#16290) [`a49637a`](withastro/astro@a49637a) Thanks [@​ViVaLaDaniel](https://github.com/ViVaLaDaniel)! - Ensures that `server.allowedHosts` (and `vite.preview.allowedHosts`) configuration is respected when using `astro preview` with the `@astrojs/cloudflare` adapter. This improves security by preventing DNS rebinding attacks when previewing Cloudflare builds locally. - [#​15725](withastro/astro#15725) [`4108ec1`](withastro/astro@4108ec1) Thanks [@​meyer](https://github.com/meyer)! - Adds support for a new `'jsx'` value for the `compressHTML` option. When set, whitespace is stripped using JSX whitespace rules instead of the default HTML compression strategy. ```js // astro.config.mjs import { defineConfig } from 'astro/config'; export default defineConfig({ compressHTML: 'jsx', }); ``` In JSX, whitespaces never matter, as such, no amount of indentation, or newlines will not affect the rendered output. For instance, the following code: ```jsx <div> <span>foo</span> <span>bar</span> </div> ``` will be rendered as `foobar`, whereas with HTML whitespace rules, a space would be present between the words due to the newline and indentation between the tags. - [#​16477](withastro/astro#16477) [`28fb3e1`](withastro/astro@28fb3e1) Thanks [@​ematipico](https://github.com/ematipico)! - Adds experimental support for configurable log handlers. This experimental feature provides better control over Astro's logging infrastructure by allowing users to replace the default console output with custom logging implementations (e.g., structured JSON). This is particularly useful for users using on-demand rendering and wishing to connect their log aggregation services, such as Kibana, Logstash, CloudWatch, Grafana, or Loki. By default, Astro provides three built-in log handlers (`json`, `node`, and `console`), but you can also create your own. ##### JSON logging JSON logging can be enabled via the CLI for the `build`, `dev`, and `sync` commands using the `experimentalJson` flag: ```js // astro.config.mjs import { defineConfig, logHandlers } from 'astro/config'; export default defineConfig({ experimental: { logger: logHandlers.json({ pretty: true, level: 'warn', }), }, }); ``` ##### Custom logger You can also create your own custom logger by implementing the correct interface: ```js // astro.config.mjs import { defineConfig } from 'astro/config'; export default defineConfig({ experimental: { logger: { entrypoint: '@​org/custom-logger', }, }, }); ``` ```ts // @​org/custom-logger.js import type { AstroLoggerDestination, AstroLoggerMessage } from 'astro'; import { matchesLevel } from 'astor/logger'; function customLogger(level = 'info'): AstroLoggerDestination { return { write(message: AstroLoggerMessage) { if (matchesLevel(message.level, level)) { // write message somewhere } }, }; } export default customLogger; ``` For more information on enabling and using this feature in your project, see the [Experimental Logger docs](https://docs.astro.build/en/reference/experimental-flags/logger/). For a complete overview and to give feedback on this experimental API, see the [Custom logger RFC](https://github.com/withastro/roadmap/blob/logger/proposals/0059-custom-logger.md). - [#​16333](withastro/astro#16333) [`0f7c3c8`](withastro/astro@0f7c3c8) Thanks [@​florian-lefebvre](https://github.com/florian-lefebvre)! - Adds an experimental flag `svgOptimizer` that enables automatic optimization of your SVG components using the provided optimizer. This supersedes the `svgo` experimental flag, which is now removed. When enabled, your imported SVG files used as components will be optimized for smaller file sizes and better performance while maintaining visual quality. This can significantly reduce the size of your SVG assets by removing unnecessary metadata, comments, and redundant code. Astro ships with a [SVGO](https://svgo.dev/) based optimizer, but any can be used. To enable this feature, add the experimental flag in your Astro config and remove `svgo` if it was enabled: ```diff // astro.config.mjs -import { defineConfig } from "astro/config"; +import { defineConfig, svgoOptimizer } from "astro/config"; export default defineConfig({ + experimental: { + svgOptimizer: svgoOptimizer() - svgo: true + } }); ``` For more information on enabling and using this feature in your project, see the [experimental SVG optimization docs](https://docs.astro.build/en/reference/experimental-flags/svg-optimization/). - [#​16302](withastro/astro#16302) [`f6f8e80`](withastro/astro@f6f8e80) Thanks [@​florian-lefebvre](https://github.com/florian-lefebvre)! - Adds a new `experimental_getFontFileURL()` method to resolve font file URLs when using the Fonts API The `fontData` object exported from `astro:assets` was introduced to provide low-level access to font family data for advanced usage. One of the goals of this API was to be able to resolve buffers using URLs. However, it turned out to be impractical, especially during prerendering. Astro now exports a new `experimental_getFontFileURL()` helper function from `astro:assets` to resolve font file URLs from `fontData`. For example, when using [satori](https://github.com/vercel/satori) to generate Open Graph images: ```diff // src/pages/og.png.ts import type { APIRoute } from "astro"; -import { fontData } from "astro:assets"; +import { fontData, experimental_getFontFileURL } from "astro:assets"; -import { outDir } from "astro:config/server"; -import { readFile } from "node:fs/promises"; import satori from "satori"; import { html } from "satori-html"; import sharp from "sharp"; export const GET: APIRoute = async (context) => { const fontPath = fontData["--font-roboto"][0]?.src[0]?.url; if (fontPath === undefined) { throw new Error("Cannot find the font path."); } - const data = import.meta.env.DEV - ? await fetch(new URL(fontPath, context.url.origin)).then(async (res) => res.arrayBuffer()) - : await readFile(new URL(`.${fontPath}`, outDir)); + const url = experimental_getFontFileURL(fontPath, context.url); + const data = await fetch(url).then((res) => res.arrayBuffer()); const svg = await satori( html`<div style="color: black;">hello, world</div>`, { width: 600, height: 400, fonts: [ { name: "Roboto", data, weight: 400, style: "normal", }, ], }, ); const pngBuffer = await sharp(Buffer.from(svg)) .resize(600, 400) .png() .toBuffer(); return new Response(new Uint8Array(pngBuffer), { headers: { "Content-Type": "image/png", }, }); }; ``` See the [Fonts API documentation](https://docs.astro.build/en/guides/fonts/#accessing-font-data-programmatically) for more information. ##### Patch Changes - [#​15980](withastro/astro#15980) [`8812382`](withastro/astro@8812382) Thanks [@​seroperson](https://github.com/seroperson)! - Prevents script deduplication inside `<template>` elements </details> --- ### Configuration 📅 **Schedule**: (UTC) - Branch creation - At any time (no schedule defined) - Automerge - At any time (no schedule defined) 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://github.com/renovatebot/renovate). <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4xNDEuNiIsInVwZGF0ZWRJblZlciI6IjQzLjE0MS42IiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->
Closes #16145
Changes
waitUntilto theCacheProvider.onRequest()context type.waitUntilthroughBaseApp.render()so adapters can pass it to runtime cache providers.ExecutionContext.waitUntilfrom the adapter handler intoapp.render().astroand@astrojs/cloudflare.Testing
pnpm run buildnode --test packages/integrations/cloudflare/test/cache-provider-wait-until.test.jsDocs
CacheProvider.onRequest()signature.