File tree Expand file tree Collapse file tree 6 files changed +37
-4
lines changed
Expand file tree Collapse file tree 6 files changed +37
-4
lines changed Original file line number Diff line number Diff line change 11import type { ReadableStream } from "node:stream/web" ;
22
33import type { InternalEvent , InternalResult } from "types/open-next" ;
4+ import { awaitAllDetachedPromise } from "utils/promise" ;
45import { emptyReadableStream } from "utils/stream" ;
56
67// We import it like that so that the edge plugin can replace it
@@ -64,6 +65,8 @@ const defaultHandler = async (
6465 const body =
6566 ( response . body as ReadableStream < Uint8Array > ) ?? emptyReadableStream ( ) ;
6667
68+ await awaitAllDetachedPromise ( ) ;
69+
6770 return {
6871 type : "core" ,
6972 statusCode : response . status ,
Original file line number Diff line number Diff line change 11import type { InternalEvent , Origin } from "types/open-next" ;
2+ import { awaitAllDetachedPromise } from "utils/promise" ;
23
34import { debug } from "../adapters/logger" ;
45import { createGenericHandler } from "../core/createGenericHandler" ;
@@ -51,6 +52,7 @@ const defaultHandler = async (internalEvent: InternalEvent) => {
5152 if ( ! result . isExternalRewrite ) {
5253 origin = await originResolver . resolve ( result . internalEvent . rawPath ) ;
5354 }
55+ await awaitAllDetachedPromise ( ) ;
5456 return {
5557 type : "middleware" ,
5658 internalEvent : result . internalEvent ,
Original file line number Diff line number Diff line change @@ -3,6 +3,7 @@ import { AsyncLocalStorage } from "node:async_hooks";
33import type { OpenNextNodeResponse , StreamCreator } from "http/index.js" ;
44import { IncomingMessage } from "http/index.js" ;
55import type { InternalEvent , InternalResult } from "types/open-next" ;
6+ import { awaitAllDetachedPromise } from "utils/promise" ;
67
78import { debug , error , warn } from "../adapters/logger" ;
89import { generateOpenNextRequestContext } from "../adapters/util" ;
@@ -150,7 +151,7 @@ export async function openNextHandler(
150151 // reset lastModified. We need to do this to avoid memory leaks
151152 delete globalThis . lastModified [ requestId ] ;
152153
153- await pendingPromiseRunner . await ( ) ;
154+ await awaitAllDetachedPromise ( ) ;
154155
155156 return internalResult ;
156157 } ,
Original file line number Diff line number Diff line change @@ -11,13 +11,22 @@ const cfPropNameToHeaderName = {
1111 longitude : "x-open-next-longitude" ,
1212} ;
1313
14+ interface WorkerContext {
15+ waitUntil : ( promise : Promise < unknown > ) => void ;
16+ }
17+
1418const handler : WrapperHandler <
1519 InternalEvent ,
1620 InternalResult | ( { type : "middleware" } & MiddlewareOutputEvent )
1721> =
1822 async ( handler , converter ) =>
19- async ( request : Request , env : Record < string , string > ) : Promise < Response > => {
23+ async (
24+ request : Request ,
25+ env : Record < string , string > ,
26+ ctx : WorkerContext ,
27+ ) : Promise < Response > => {
2028 globalThis . process = process ;
29+ globalThis . openNextWaitUntil = ctx . waitUntil ;
2130
2231 // Set the environment variables
2332 // Cloudflare suggests to not override the process.env object but instead apply the values to it
Original file line number Diff line number Diff line change @@ -138,12 +138,19 @@ declare global {
138138
139139 /**
140140 * The AsyncLocalStorage instance that is used to store the request context.
141- * Only available in main functions.
141+ * Only available in main, middleware and edge functions.
142142 * TODO: should be available everywhere in the future.
143- * Defined in `requestHandler.ts`.
143+ * Defined in `requestHandler.ts`, `middleware.ts` and `edge-adapter.ts` .
144144 */
145145 var __als : AsyncLocalStorage < OpenNextRequestContext > ;
146146
147+ /**
148+ * The function that is used to run background tasks even after the response has been sent.
149+ * This one is defined by the wrapper function as most of them don't need or support this feature.
150+ * If not present, all the awaiting promises will be resolved before sending the response.
151+ */
152+ var openNextWaitUntil : ( ( promise : Promise < void > ) => void ) | undefined ;
153+
147154 /**
148155 * The entries object that contains the functions that are available in the function.
149156 * Only available in edge runtime functions.
Original file line number Diff line number Diff line change @@ -58,3 +58,14 @@ export class DetachedPromiseRunner {
5858 } ) ;
5959 }
6060}
61+
62+ export async function awaitAllDetachedPromise ( ) {
63+ const promisesToAwait =
64+ globalThis . __als . getStore ( ) ?. pendingPromiseRunner . await ( ) ??
65+ Promise . resolve ( ) ;
66+ if ( globalThis . openNextWaitUntil ) {
67+ globalThis . openNextWaitUntil ( promisesToAwait ) ;
68+ return ;
69+ }
70+ await promisesToAwait ;
71+ }
You can’t perform that action at this time.
0 commit comments