Skip to content

Commit

Permalink
wip: onAfterError in edge
Browse files Browse the repository at this point in the history
  • Loading branch information
lubieowoce committed Dec 3, 2024
1 parent 0f1bb2f commit 855f8c0
Show file tree
Hide file tree
Showing 5 changed files with 47 additions and 10 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,11 @@ import { normalizeAppPath } from '../../../../shared/lib/router/utils/app-paths'
import type { SizeLimit } from '../../../../types'
import { internal_getCurrentFunctionWaitUntil } from '../../../../server/web/internal-edge-wait-until'
import type { PAGE_TYPES } from '../../../../lib/page-types'
import type { NextRequestHint } from '../../../../server/web/adapter'
import type {
HandlerExtraOpts,
NextRequestHint,
} from '../../../../server/web/adapter'
import { InvariantError } from '../../../../shared/lib/invariant-error'

export function getRender({
dev,
Expand Down Expand Up @@ -157,11 +161,31 @@ export function getRender({

return async function render(
request: NextRequestHint,
event?: NextFetchEvent
event?: NextFetchEvent,
extraOpts?: HandlerExtraOpts
) {
const extendedReq = new WebNextRequest(request)
const extendedRes = new WebNextResponse(undefined)

if (dev) {
if (extraOpts) {
const { onAfterTaskError } = extraOpts
// in practice `onAfterTaskError` should be constant, so it's fine to set it like this
// but double check that it's not changing across request to prevent future bugs
if (
server['afterTaskErrorHandler'] &&
onAfterTaskError &&
server['afterTaskErrorHandler'] !== onAfterTaskError
) {
throw new InvariantError(
'Expected `extraOpts.afterTaskErrorHandler` to not change'
)
}

server['afterTaskErrorHandler'] = onAfterTaskError
}
}

handler(extendedReq, extendedRes)
const result = await extendedRes.toResponse()
request.fetchMetrics = extendedReq.fetchMetrics
Expand Down
2 changes: 2 additions & 0 deletions packages/next/src/server/next-server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1494,6 +1494,7 @@ export default class NextNodeServer extends BaseServer<
body: getRequestMeta(params.request, 'clonableBody'),
signal: signalFromNodeResponse(params.response.originalResponse),
waitUntil: this.getWaitUntil(),
onAfterTaskError: this.afterTaskErrorHandler,
},
useCache: true,
onWarning: params.onWarning,
Expand Down Expand Up @@ -1798,6 +1799,7 @@ export default class NextNodeServer extends BaseServer<
body: getRequestMeta(params.req, 'clonableBody'),
signal: signalFromNodeResponse(params.res.originalResponse),
waitUntil: this.getWaitUntil(),
onAfterTaskError: this.afterTaskErrorHandler,
},
useCache: true,
onError: params.onError,
Expand Down
16 changes: 12 additions & 4 deletions packages/next/src/server/web/adapter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,13 @@ const headersGetter: TextMapGetter<Headers> = {
get: (headers, key) => headers.get(key) ?? undefined,
}

export type HandlerExtraOpts = { onAfterTaskError?: (error: unknown) => void }
export type AdapterOptions = {
handler: (req: NextRequestHint, event: NextFetchEvent) => Promise<Response>
handler: (
req: NextRequestHint,
event: NextFetchEvent,
extraOpts?: HandlerExtraOpts
) => Promise<Response>
page: string
request: RequestData
IncrementalCache?: typeof import('../lib/incremental-cache').IncrementalCache
Expand Down Expand Up @@ -212,6 +217,8 @@ export async function adapter(
let response
let cookiesFromResponse

const onAfterTaskError = params.request.onAfterTaskError

response = await propagator(request, () => {
// we only care to make async storage available for middleware
const isMiddleware =
Expand Down Expand Up @@ -270,7 +277,7 @@ export async function adapter(
supportsDynamicResponse: true,
waitUntil,
onClose: closeController.onClose.bind(closeController),
onAfterTaskError: undefined,
onAfterTaskError,
},
requestEndedState: { ended: false },
isPrefetchRequest: request.headers.has(
Expand All @@ -283,7 +290,8 @@ export async function adapter(
requestStore,
params.handler,
request,
event
event,
{ onAfterTaskError }
)
)
} finally {
Expand All @@ -298,7 +306,7 @@ export async function adapter(
}
)
}
return params.handler(request, event)
return params.handler(request, event, { onAfterTaskError })
})

// check if response is a Response object
Expand Down
9 changes: 5 additions & 4 deletions packages/next/src/server/web/edge-route-module-wrapper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import type {

import './globals'

import { adapter, type AdapterOptions } from './adapter'
import { adapter, type AdapterOptions, type HandlerExtraOpts } from './adapter'
import { IncrementalCache } from '../lib/incremental-cache'
import { RouteMatcher } from '../route-matchers/route-matcher'
import type { NextFetchEvent } from './spec-extension/fetch-event'
Expand Down Expand Up @@ -57,7 +57,7 @@ export class EdgeRouteModuleWrapper {
const wrapper = new EdgeRouteModuleWrapper(routeModule, options.nextConfig)

// Return the wrapping function.
return (opts: AdapterOptions) => {
return (opts: Omit<AdapterOptions, 'handler' | 'IncrementalCache'>) => {
return adapter({
...opts,
IncrementalCache,
Expand All @@ -69,7 +69,8 @@ export class EdgeRouteModuleWrapper {

private async handler(
request: NextRequest,
evt: NextFetchEvent
evt: NextFetchEvent,
extraOpts?: HandlerExtraOpts
): Promise<Response> {
const utils = getUtils({
pageIsDynamic: this.matcher.isDynamic,
Expand Down Expand Up @@ -107,7 +108,7 @@ export class EdgeRouteModuleWrapper {
supportsDynamicResponse: true,
waitUntil,
onClose: closeController.onClose.bind(closeController),
onAfterTaskError: undefined,
onAfterTaskError: extraOpts?.onAfterTaskError,
experimental: {
after: isAfterEnabled,
dynamicIO: !!process.env.__NEXT_DYNAMIC_IO,
Expand Down
2 changes: 2 additions & 0 deletions packages/next/src/server/web/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ export interface RequestData {
signal: AbortSignal
/** passed in when running in edge runtime sandbox */
waitUntil?: (promise: Promise<any>) => void
/** passed in when running in edge runtime sandbox */
onAfterTaskError?: (error: unknown) => void
}

export type NodejsRequestData = Omit<RequestData, 'body'> & {
Expand Down

0 comments on commit 855f8c0

Please sign in to comment.