inngest 4.2.3 → 4.2.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"engine.cjs","names":["hashjs","isRecord","createExecutionEngine: InngestExecutionFactory","headers: Record<string, string>","InngestExecution","ExecutionVersion","options: InngestExecutionOptions","StepMode","Stream","MiddlewareManager","internalLoggerSymbol","trace","version","getAsyncLocalStorage","headerKeys","createDeferredPromise","retryWithBackoff","defaultMaxRetries","buildSseMetadataEvent","prependToStream","resultData: unknown","streamingResult: ExecutionResult","StepOpCode","commonCheckpointHandler: CheckpointHandlers[StepMode][\"\"]","serializeError","syncHandlers: CheckpointHandlers[StepMode.Sync]","sseResponse: SseResponse","asyncHandlers: CheckpointHandlers[StepMode.Async]","asyncCheckpointingHandlers: CheckpointHandlers[StepMode.AsyncCheckpointing]","step","UnreachableError","outgoingOp: OutgoingOp","getAsyncCtx","interval: GoInterval | undefined","runAsPromise","goIntervalTiming","innerHandler: () => Promise<unknown>","err: Error","NonRetriableError","StepError","RetryAfterError","validateEvents","undefinedToNull","createDeferredPromiseWithStack","loop: ExecutionState[\"loop\"]","experimentStepRunSymbol","createGroupTools","z","jsonErrorSchema","deserializeError","foundStepsToReport: Map<string, FoundStep>","unhandledFoundStepsToReport: Map<string, FoundStep>","expectedNextStepIndexes: Map<string, number>","remainingStepCompletionOrder: string[]","foundStepsReportPromise: Promise<void> | undefined","ErrCode","extensionPromise: Promise<void>","resolveNextTick","resolveAfterPending","stepHandler: StepHandler","getStepOptions","extraOpts: Record<string, unknown> | undefined","step: FoundStep","createStepTools","createTimeoutPromise","STEP_INDEXING_SUFFIX"],"sources":["../../../src/components/execution/engine.ts"],"sourcesContent":["import { trace } from \"@opentelemetry/api\";\nimport hashjs from \"hash.js\";\nimport ms, { type StringValue } from \"ms\";\nimport { z } from \"zod/v3\";\n\nimport {\n defaultMaxRetries,\n ExecutionVersion,\n headerKeys,\n internalEvents,\n} from \"../../helpers/consts.ts\";\n\nimport {\n deserializeError,\n ErrCode,\n serializeError,\n} from \"../../helpers/errors.js\";\nimport { undefinedToNull } from \"../../helpers/functions.js\";\nimport {\n createDeferredPromise,\n createDeferredPromiseWithStack,\n createTimeoutPromise,\n type DeferredPromiseReturn,\n type GoInterval,\n goIntervalTiming,\n resolveAfterPending,\n resolveNextTick,\n retryWithBackoff,\n runAsPromise,\n} from \"../../helpers/promises.ts\";\nimport * as Temporal from \"../../helpers/temporal.ts\";\nimport {\n isRecord,\n type MaybePromise,\n type Simplify,\n} from \"../../helpers/types.ts\";\nimport {\n type APIStepPayload,\n type Context,\n type EventPayload,\n type FailureEventArgs,\n type Handler,\n type HashedOp,\n jsonErrorSchema,\n type OutgoingOp,\n StepMode,\n StepOpCode,\n} from \"../../types.ts\";\nimport { version } from \"../../version.ts\";\nimport { internalLoggerSymbol } from \"../Inngest.ts\";\nimport { createGroupTools } from \"../InngestGroupTools.ts\";\nimport type {\n MetadataKind,\n MetadataOpcode,\n MetadataScope,\n MetadataUpdate,\n} from \"../InngestMetadata.ts\";\nimport {\n createStepTools,\n type ExperimentStepTools,\n experimentStepRunSymbol,\n type FoundStep,\n getStepOptions,\n STEP_INDEXING_SUFFIX,\n type StepHandler,\n} from \"../InngestStepTools.ts\";\nimport { MiddlewareManager } from \"../middleware/index.ts\";\nimport type { Middleware } from \"../middleware/middleware.ts\";\nimport { UnreachableError } from \"../middleware/utils.ts\";\nimport { NonRetriableError } from \"../NonRetriableError.ts\";\nimport { RetryAfterError } from \"../RetryAfterError.ts\";\nimport { StepError } from \"../StepError.ts\";\nimport { Stream } from \"../StreamTools.ts\";\nimport { validateEvents } from \"../triggers/utils.js\";\nimport { getAsyncCtx, getAsyncLocalStorage } from \"./als.ts\";\nimport {\n type BasicFoundStep,\n type ExecutionResult,\n type IInngestExecution,\n InngestExecution,\n type InngestExecutionFactory,\n type InngestExecutionOptions,\n type MemoizedOp,\n} from \"./InngestExecution.ts\";\nimport { clientProcessorMap } from \"./otel/access.ts\";\nimport {\n buildSseMetadataEvent,\n prependToStream,\n type SseResponse,\n} from \"./streaming.ts\";\n\nconst { sha1 } = hashjs;\n\n/**\n * Retry configuration for checkpoint operations.\n *\n * Checkpoint calls use exponential backoff with jitter to handle transient\n * network failures (e.g., dev server temporarily down, cloud hiccup). If\n * retries exhaust, the error propagates up - for Sync mode this results in a\n * 500 error, for AsyncCheckpointing the caller handles fallback.\n */\nconst CHECKPOINT_RETRY_OPTIONS = { maxAttempts: 5, baseDelay: 100 };\n\nfunction errorMessage(error: unknown): string {\n if (error instanceof Error) {\n return error.message;\n }\n if (isRecord(error) && typeof error.message === \"string\") {\n return error.message;\n }\n return String(error);\n}\n\n/**\n * Placeholder step ID used when completing a checkpointed run.\n */\nconst RUN_COMPLETE_STEP_ID = \"complete\";\n\nconst STEP_NOT_FOUND_MAX_FOUND_STEPS = 25;\n\nexport const createExecutionEngine: InngestExecutionFactory = (options) => {\n return new InngestExecutionEngine(options);\n};\n\nfunction extractSseResponse(response: Response, body: string): SseResponse {\n const headers: Record<string, string> = {};\n response.headers.forEach((value, key) => {\n headers[key] = value;\n });\n return { body, statusCode: response.status, headers };\n}\n\nfunction defaultSseResponse(data: unknown): SseResponse {\n return {\n body: JSON.stringify(data),\n statusCode: 200,\n headers: { \"content-type\": \"application/json\" },\n };\n}\n\nfunction jsonResponse(data: unknown, status = 200): Response {\n return new Response(JSON.stringify(data), {\n status,\n headers: { \"Content-Type\": \"application/json\" },\n });\n}\n\nclass InngestExecutionEngine\n extends InngestExecution\n implements IInngestExecution\n{\n public version = ExecutionVersion.V2;\n\n private state: ExecutionState;\n private fnArg: Context.Any;\n private checkpointHandlers: CheckpointHandlers;\n private timeoutDuration = 1000 * 10;\n private execution: Promise<ExecutionResult> | undefined;\n private userFnToRun: Handler.Any;\n private middlewareManager: MiddlewareManager;\n /**\n * Close the stream via {@link streamCloseSucceeded}, {@link streamCloseFailed},\n * or {@link streamEnd} — never call `streamTools.close*`/`end` directly, as\n * the wrappers ensure the redirect event is flushed first.\n */\n private streamTools: Stream;\n\n /**\n * Resolved when `stream.push()`/`pipe()` is first called in sync mode,\n * allowing `_start()` to return the SSE Response to the HTTP layer while\n * the core loop continues executing steps in the background.\n */\n private earlyStreamResponse:\n | DeferredPromiseReturn<ExecutionResult>\n | undefined;\n\n /**\n * Whether the `inngest.redirect_info` SSE event has already been sent.\n * Prevents duplicate redirect events.\n */\n private redirectSent = false;\n\n /**\n * Promise that resolves once the redirect event has been written (or the\n * attempt completes). Stored so that `checkpointAndSwitchToAsync` can\n * await it before closing the writer.\n */\n private redirectPromise: Promise<void> = Promise.resolve();\n\n /**\n * If we're supposed to run a particular step via `requestedRunStep`, this\n * will be a `Promise` that resolves after no steps have been found for\n * `timeoutDuration` milliseconds.\n *\n * If we're not supposed to run a particular step, this will be `undefined`.\n */\n private timeout?: ReturnType<typeof createTimeoutPromise>;\n private rootSpanId?: string;\n\n /**\n * If we're checkpointing and have been given a maximum runtime, this will be\n * a `Promise` that resolves after that duration has elapsed, allowing us to\n * ensure that we end the execution in good time, especially in serverless\n * environments.\n */\n private checkpointingMaxRuntimeTimer?: ReturnType<\n typeof createTimeoutPromise\n >;\n\n /**\n * If we're checkpointing and have been given a maximum buffer interval, this\n * will be a `Promise` that resolves after that duration has elapsed, allowing\n * us to periodically checkpoint even if the step buffer hasn't filled.\n */\n private checkpointingMaxBufferIntervalTimer?: ReturnType<\n typeof createTimeoutPromise\n >;\n\n constructor(rawOptions: InngestExecutionOptions) {\n const options: InngestExecutionOptions = {\n ...rawOptions,\n stepMode: rawOptions.stepMode ?? StepMode.Async,\n };\n\n super(options);\n\n /**\n * Check we have everything we need for checkpointing\n */\n if (this.options.stepMode === StepMode.Sync) {\n if (!this.options.createResponse) {\n throw new Error(\"createResponse is required for sync step mode\");\n }\n }\n\n this.userFnToRun = this.getUserFnToRun();\n this.streamTools = new Stream({\n onActivated: () => this.handleStreamActivated(),\n onWriteError: (err) =>\n this.devDebug(\n \"stream write error (client may have disconnected):\",\n err,\n ),\n });\n this.state = this.createExecutionState();\n this.fnArg = this.createFnArg();\n\n // Setup middleware\n const mwInstances =\n this.options.middlewareInstances ??\n (this.options.client.middleware || []).map((Cls) => {\n return new Cls({ client: this.options.client });\n });\n this.middlewareManager = new MiddlewareManager(\n this.fnArg,\n () => this.state.stepState,\n mwInstances,\n this.options.fn,\n this.options.client[internalLoggerSymbol],\n );\n\n this.checkpointHandlers = this.createCheckpointHandlers();\n this.initializeTimer(this.state);\n this.initializeCheckpointRuntimeTimer(this.state);\n\n this.devDebug(\n \"created new V1 execution for run;\",\n this.options.requestedRunStep\n ? `wanting to run step \"${this.options.requestedRunStep}\"`\n : \"discovering steps\",\n );\n\n this.devDebug(\"existing state keys:\", Object.keys(this.state.stepState));\n }\n\n /**\n * Idempotently start the execution of the user's function.\n */\n public start() {\n if (!this.execution) {\n this.devDebug(\"starting V1 execution\");\n\n const tracer = trace.getTracer(\"inngest\", version);\n\n this.execution = getAsyncLocalStorage().then((als) => {\n return als.run(\n {\n app: this.options.client,\n execution: {\n ctx: this.fnArg,\n instance: this,\n stream: this.streamTools,\n },\n },\n async () => {\n return tracer.startActiveSpan(\"inngest.execution\", (span) => {\n this.rootSpanId = span.spanContext().spanId;\n clientProcessorMap.get(this.options.client)?.declareStartingSpan({\n span,\n runId: this.options.runId,\n traceparent: this.options.headers[headerKeys.TraceParent],\n tracestate: this.options.headers[headerKeys.TraceState],\n });\n\n return this._start()\n .then((result) => {\n this.devDebug(\"result:\", result);\n return result;\n })\n .finally(() => {\n span.end();\n });\n });\n },\n );\n });\n }\n\n return this.execution;\n }\n\n public addMetadata(\n stepId: string,\n kind: MetadataKind,\n scope: MetadataScope,\n op: MetadataOpcode,\n values: Record<string, unknown>,\n ) {\n if (!this.state.metadata) {\n this.state.metadata = new Map();\n }\n\n const updates = this.state.metadata.get(stepId) ?? [];\n updates.push({ kind, scope, op, values });\n this.state.metadata.set(stepId, updates);\n\n return true;\n }\n\n /**\n * Starts execution of the user's function and the core loop.\n */\n private async _start(): Promise<ExecutionResult> {\n // Set up a deferred promise that handleStreamActivated resolves to return\n // the SSE Response early while the core loop keeps running.\n if (this.options.stepMode === StepMode.Sync && this.options.acceptsSse) {\n this.earlyStreamResponse = createDeferredPromise<ExecutionResult>();\n }\n\n const coreLoop = this.runCoreLoop();\n\n if (this.earlyStreamResponse) {\n // Suppress: if earlyStreamResponse wins the race and coreLoop later\n // rejects, the rejection must not go unhandled.\n coreLoop.catch((err) => {\n this.options.client[internalLoggerSymbol].error(\n { err },\n \"Core loop rejected after early stream response was sent\",\n );\n });\n\n return Promise.race([this.earlyStreamResponse.promise, coreLoop]);\n }\n\n return coreLoop;\n }\n\n /**\n * The core checkpoint loop: processes checkpoints until a handler returns\n * a result.\n */\n private async runCoreLoop(): Promise<ExecutionResult> {\n try {\n const allCheckpointHandler = this.getCheckpointHandler(\"\");\n await this.startExecution();\n\n let i = 0;\n\n for await (const checkpoint of this.state.loop) {\n await allCheckpointHandler(checkpoint, i);\n\n const handler = this.getCheckpointHandler(checkpoint.type);\n const result = await handler(checkpoint, i++);\n\n if (result) {\n return result;\n }\n }\n } catch (error) {\n // If earlyStreamResponse was set up, close the stream with an error event\n // and resolve (not reject) with a well-formed result so the caller gets a\n // structured response instead of a raw Error.\n if (this.earlyStreamResponse) {\n await this.streamCloseFailed(\"Internal execution error\");\n const result = this.transformOutput({ error });\n this.earlyStreamResponse.resolve(result);\n return result;\n }\n\n return this.transformOutput({ error });\n } finally {\n void this.state.loop.return();\n }\n\n /**\n * If we're here, the generator somehow finished without returning a value.\n * This should never happen.\n */\n throw new Error(\"Core loop finished without returning a value\");\n }\n\n private async checkpoint(steps: OutgoingOp[]): Promise<void> {\n if (this.options.stepMode === StepMode.Sync) {\n if (!this.state.checkpointedRun) {\n // We have to start the run\n const res = await retryWithBackoff(\n () =>\n this.options.client[\"inngestApi\"].checkpointNewRun({\n runId: this.fnArg.runId,\n event: this.fnArg.event as APIStepPayload,\n steps,\n executionVersion: this.version,\n retries: this.fnArg.maxAttempts ?? defaultMaxRetries,\n }),\n CHECKPOINT_RETRY_OPTIONS,\n );\n\n this.state.checkpointedRun = {\n appId: res.data.app_id,\n fnId: res.data.fn_id,\n token: res.data.token,\n realtimeToken: res.data.realtime_token,\n };\n\n // Try sending redirect (no-op if stream isn't activated yet).\n this.sendRedirectIfReady();\n } else {\n await retryWithBackoff(\n () =>\n this.options.client[\"inngestApi\"].checkpointSteps({\n appId: this.state.checkpointedRun!.appId,\n fnId: this.state.checkpointedRun!.fnId,\n runId: this.fnArg.runId,\n steps,\n }),\n CHECKPOINT_RETRY_OPTIONS,\n );\n }\n } else if (this.options.stepMode === StepMode.AsyncCheckpointing) {\n const { internalFnId, queueItemId } = this.options;\n if (!queueItemId) {\n throw new Error(\n \"Missing queueItemId for async checkpointing. This is a bug in the Inngest SDK.\",\n );\n }\n\n if (!internalFnId) {\n throw new Error(\n \"Missing internalFnId for async checkpointing. This is a bug in the Inngest SDK.\",\n );\n }\n\n await retryWithBackoff(\n () =>\n this.options.client[\"inngestApi\"].checkpointStepsAsync({\n runId: this.fnArg.runId,\n fnId: internalFnId,\n queueItemId,\n steps,\n }),\n CHECKPOINT_RETRY_OPTIONS,\n );\n } else {\n throw new Error(\n \"Checkpointing is only supported in Sync and AsyncCheckpointing step modes. This is a bug in the Inngest SDK.\",\n );\n }\n }\n\n private async checkpointAndSwitchToAsync(\n steps: OutgoingOp[],\n stepError?: unknown,\n ): Promise<ExecutionResult> {\n await this.checkpoint(steps);\n\n if (!this.state.checkpointedRun?.token) {\n throw new Error(\"Failed to checkpoint and switch to async mode\");\n }\n\n const token = this.state.checkpointedRun.token;\n\n if (this.streamTools.activated) {\n if (stepError && !this.retriability(stepError)) {\n // Permanent failure — close with a failed event so the client\n // sees the error.\n await this.streamCloseFailed(errorMessage(stepError));\n } else {\n // End stream without a result event — client uses redirect_info\n // to reconnect.\n await this.streamEnd();\n }\n } else if (this.options.acceptsSse) {\n // Stream was never activated (no stream.push/pipe), but the client\n // accepts SSE. Close and return the SSE response so the client gets\n // metadata + redirect_info events and can follow the redirect.\n await this.streamEnd();\n return {\n type: \"function-resolved\",\n ctx: this.fnArg,\n ops: this.ops,\n data: this.buildSyncSseResponse(),\n };\n }\n\n return {\n type: \"change-mode\",\n ctx: this.fnArg,\n ops: this.ops,\n to: StepMode.Async,\n token,\n };\n }\n\n /**\n * Prepend the `inngest.metadata` SSE event to the stream's readable side.\n * The returned stream can be used as a fetch body or Response body.\n *\n * NOTE: `this.streamTools.readable` can only be consumed once, so only one\n * of `buildSyncSseResponse` or `postCheckpointStream` may be called per\n * execution.\n */\n private buildMetadataPrefixedStream(): ReadableStream<Uint8Array> {\n const metadataEvent = buildSseMetadataEvent(this.fnArg.runId);\n return prependToStream(\n new TextEncoder().encode(metadataEvent),\n this.streamTools.readable,\n );\n }\n\n /**\n * Build the initial SSE `Response` that marks the start of streaming to the\n * client. Only used in sync mode. In async mode, the stream is POSTed to the\n * Inngest Server via {@link postCheckpointStream} instead.\n *\n * The response body is the stream's readable side, prefixed with the\n * `inngest.metadata` SSE event.\n */\n private buildSyncSseResponse(): Response {\n return new Response(this.buildMetadataPrefixedStream(), {\n status: 200,\n headers: {\n \"Content-Type\": \"text/event-stream\",\n \"Cache-Control\": \"no-cache\",\n },\n });\n }\n\n /**\n * Wraps a plain return value as an SSE Response.\n *\n * Used when the client sent `Accept: text/event-stream` but\n * `stream.push()`/`pipe()` was NOT called during execution. The\n * checkpointable data is the function's return value. The SSE events are just\n * a delivery mechanism.\n */\n private async wrapResultAsSse(\n checkpoint: Simplify<\n { type: \"function-resolved\" } & Checkpoints[\"function-resolved\"]\n >,\n sseResponse: SseResponse,\n ): Promise<ExecutionResult> {\n const resultData: unknown = checkpoint.data;\n\n // Close the stream with a terminal succeeded event\n await this.streamCloseSucceeded(sseResponse);\n\n const clientResponse = this.buildSyncSseResponse();\n\n // Run transformOutput to fire middleware hooks\n const result = this.transformOutput({ data: resultData });\n\n const streamingResult: ExecutionResult = {\n ...result,\n data: clientResponse,\n } as ExecutionResult;\n\n // Background: checkpoint the return value (not the stream bytes).\n void this.checkpointReturnValue(resultData);\n\n return streamingResult;\n }\n\n /**\n * Called when `stream.push()`/`pipe()` is first invoked during sync\n * execution. Resolves {@link earlyStreamResponse} so that `_start()` can\n * return the SSE Response to the HTTP layer immediately, while the core\n * checkpoint loop keeps running steps in the background.\n */\n private handleStreamActivated(): undefined {\n if (this.earlyStreamResponse) {\n // \"function-resolved\" tells the HTTP layer to send the Response,\n // even though the function is still running.\n this.earlyStreamResponse.resolve({\n type: \"function-resolved\",\n ctx: this.fnArg,\n ops: this.ops,\n data: this.buildSyncSseResponse(),\n });\n\n // Checkpoint may have already provided the realtime token — try redirect now.\n this.sendRedirectIfReady();\n\n return undefined;\n }\n\n // Async/AsyncCheckpointing mode: start the streaming POST immediately.\n // In sync mode without SSE, the stream has no consumer — skip the POST.\n if (this.options.stepMode !== StepMode.Sync) {\n this.postCheckpointStream();\n }\n this.sendRedirectIfReady();\n return undefined;\n }\n\n /**\n * Sends the `inngest.redirect_info` SSE event when both conditions are met:\n * 1. The client accepts SSE (so there's a stream to write the event to)\n * 2. We have a realtime token (first checkpoint has completed)\n *\n * Called after the first checkpoint AND on stream activation, whichever\n * comes second, so the redirect is sent as early as possible.\n */\n private sendRedirectIfReady(): void {\n if (this.redirectSent) {\n return;\n }\n\n if (!this.options.acceptsSse) {\n return;\n }\n\n if (!this.state.checkpointedRun) {\n // This is part of the happy path. We may not have checkpointed the run\n // yet, which happens after the first step ends\n return;\n }\n\n this.redirectSent = true;\n\n const { realtimeToken } = this.state.checkpointedRun;\n\n this.redirectPromise = (async () => {\n try {\n const redirect =\n await this.options.client[\"inngestApi\"].getRealtimeStreamRedirect(\n realtimeToken,\n );\n\n this.streamTools.sendRedirectInfo({\n runId: this.fnArg.runId,\n url: redirect.url,\n });\n } catch (err) {\n this.options.client[internalLoggerSymbol].warn(\n { err },\n \"Failed to fetch realtime stream redirect URL\",\n );\n }\n })();\n }\n\n /**\n * Await the pending redirect-info fetch, then close the stream with a\n * succeeded result. Awaiting first guarantees the redirect event is\n * enqueued on the write chain before the close event.\n */\n private async streamCloseSucceeded(response: SseResponse): Promise<void> {\n await this.redirectPromise;\n this.streamTools.closeSucceeded(response);\n }\n\n /**\n * Await the pending redirect-info fetch, then close the stream with a\n * failed result.\n */\n private async streamCloseFailed(error: string): Promise<void> {\n await this.redirectPromise;\n this.streamTools.closeFailed(error);\n }\n\n /**\n * Await the pending redirect-info fetch, then close the stream without\n * a result event.\n */\n private async streamEnd(): Promise<void> {\n await this.redirectPromise;\n this.streamTools.end();\n }\n\n /**\n * POST stream data to the checkpoint stream ingest endpoint.\n *\n * Called eagerly from handleStreamActivated so chunks flow in\n * real-time, or after completion if stream.push() was never called.\n */\n private postCheckpointStream(): void {\n try {\n // Fire and forget — completes when the stream closes.\n void this.options.client[\"inngestApi\"]\n .checkpointStream({\n runId: this.fnArg.runId,\n body: this.buildMetadataPrefixedStream(),\n })\n .catch((err: unknown) => {\n this.devDebug(\"checkpoint stream POST error:\", err);\n });\n } catch (err) {\n this.devDebug(\"checkpoint stream POST error:\", err);\n }\n }\n\n /**\n * Checkpoints the return value of a function that was delivered via SSE.\n * Runs in the background so it doesn't block the client stream.\n */\n private async checkpointReturnValue(data: unknown): Promise<void> {\n try {\n if (this.options.createResponse) {\n await this.checkpoint([\n {\n op: StepOpCode.RunComplete,\n id: hashId(RUN_COMPLETE_STEP_ID),\n data: await this.options.createResponse(jsonResponse(data)),\n },\n ]);\n }\n } catch (err) {\n this.devDebug(\n \"error during background checkpoint of SSE result, client stream unaffected:\",\n err,\n );\n }\n }\n\n /**\n * Creates a handler for every checkpoint type, defining what to do when we\n * reach that checkpoint in the core loop.\n */\n private createCheckpointHandlers(): CheckpointHandlers {\n const commonCheckpointHandler: CheckpointHandlers[StepMode][\"\"] = (\n checkpoint,\n ) => {\n this.devDebug(`${this.options.stepMode} checkpoint:`, checkpoint);\n };\n\n const stepRanHandler = async (\n stepResult: OutgoingOp,\n ): Promise<ExecutionResult> => {\n const transformResult = await this.transformOutput(stepResult);\n\n /**\n * Transforming output will always return either function rejection or\n * resolution. In most cases, this can be immediately returned, but in\n * this particular case we want to handle it differently.\n */\n if (transformResult.type === \"function-resolved\") {\n return {\n type: \"step-ran\",\n ctx: transformResult.ctx,\n ops: transformResult.ops,\n step: {\n ...stepResult,\n data: transformResult.data,\n },\n };\n } else if (transformResult.type === \"function-rejected\") {\n const stepForResponse = {\n ...stepResult,\n error: transformResult.error,\n };\n\n if (stepResult.op === StepOpCode.StepFailed) {\n const ser = serializeError(transformResult.error);\n stepForResponse.data = {\n __serialized: true,\n name: ser.name,\n message: ser.message,\n stack: \"\",\n };\n }\n\n return {\n type: \"step-ran\",\n ctx: transformResult.ctx,\n ops: transformResult.ops,\n retriable: transformResult.retriable,\n step: stepForResponse,\n };\n }\n\n return transformResult;\n };\n\n const maybeReturnNewSteps = async (): Promise<\n ExecutionResult | undefined\n > => {\n const newSteps = await this.filterNewSteps(\n Array.from(this.state.steps.values()),\n );\n if (newSteps) {\n return {\n type: \"steps-found\",\n ctx: this.fnArg,\n ops: this.ops,\n steps: newSteps,\n };\n }\n\n return;\n };\n\n const attemptCheckpointAndResume = async (\n stepResult?: OutgoingOp,\n resume = true,\n force = false,\n ): Promise<ExecutionResult | undefined> => {\n // If we're here, we successfully ran a step, so we may now need\n // to checkpoint it depending on the step buffer configured.\n if (stepResult) {\n const stepToResume = this.resumeStepWithResult(stepResult, resume);\n\n // Clear `executingStep` immediately after resuming, before any await.\n // `resumeStepWithResult` resolves the step's promise, queuing a\n // microtask for the function to continue. Any subsequent await (e.g.\n // the `transformOutput` hook) yields and lets that microtask run, so\n // `executingStep` must already be cleared to avoid a false positive\n // NESTING_STEPS warning in the next step's handler.\n delete this.state.executingStep;\n\n // Buffer a copy with transformed data for checkpointing\n this.state.checkpointingStepBuffer.push({\n ...stepToResume,\n data: stepResult.data,\n });\n }\n\n if (\n force ||\n !this.options.checkpointingConfig?.bufferedSteps ||\n this.state.checkpointingStepBuffer.length >=\n this.options.checkpointingConfig.bufferedSteps\n ) {\n this.devDebug(\"checkpointing and resuming execution after step run\");\n\n try {\n this.devDebug(\n `checkpointing all buffered steps:`,\n this.state.checkpointingStepBuffer\n .map((op) => op.displayName || op.id)\n .join(\", \"),\n );\n\n return void (await this.checkpoint(\n this.state.checkpointingStepBuffer,\n ));\n } catch (err) {\n // If checkpointing fails for any reason, fall back to returning\n // ALL buffered steps to the executor via the normal async flow.\n // The executor persists completed steps and rediscovers any\n // parallel/errored steps on the next invocation.\n this.devDebug(\n \"error checkpointing after step run, so falling back to async\",\n err,\n );\n\n const buffered = this.state.checkpointingStepBuffer;\n\n if (buffered.length) {\n return {\n type: \"steps-found\" as const,\n ctx: this.fnArg,\n ops: this.ops,\n steps: buffered as [OutgoingOp, ...OutgoingOp[]],\n };\n }\n\n return;\n } finally {\n // Clear the checkpointing buffer\n this.state.checkpointingStepBuffer = [];\n }\n } else {\n this.devDebug(\n `not checkpointing yet, continuing execution as we haven't reached buffered step limit of ${this.options.checkpointingConfig?.bufferedSteps}`,\n );\n }\n\n return;\n };\n\n const syncHandlers: CheckpointHandlers[StepMode.Sync] = {\n /**\n * Run for all checkpoints. Best used for logging or common actions.\n * Use other handlers to return values and interrupt the core loop.\n */\n \"\": commonCheckpointHandler,\n\n \"function-resolved\": async (checkpoint) => {\n const usingSseStream = !!this.earlyStreamResponse;\n\n if (this.streamTools.activated) {\n let resultData: unknown = checkpoint.data;\n let sseResponse: SseResponse;\n if (checkpoint.data instanceof Response) {\n // Clone when not SSE so the Response body stays intact for passthrough.\n const body = await (usingSseStream\n ? checkpoint.data.text()\n : checkpoint.data.clone().text());\n sseResponse = extractSseResponse(checkpoint.data, body);\n resultData = body;\n } else {\n sseResponse = defaultSseResponse(resultData);\n }\n\n // Always close the stream — either the SSE client or the\n // server-side checkpoint POST needs the terminal result event.\n await this.streamCloseSucceeded(sseResponse);\n\n if (usingSseStream) {\n // SSE path: response already sent; checkpoint in background.\n void this.checkpointReturnValue(resultData);\n return this.transformOutput({ data: resultData });\n }\n\n // Non-SSE: fall through to normal response handling.\n }\n\n // If the client accepts SSE (but stream.push() was NOT called), build\n // the SSE Response now. The SSE envelope is always needed when the\n // client requests it because it carries inngest.metadata and\n // inngest.redirect_info. Without these the client can't reconnect if a\n // future execution goes async.\n if (this.options.acceptsSse) {\n let sseResponse: SseResponse;\n if (checkpoint.data instanceof Response) {\n const body = await checkpoint.data.text();\n sseResponse = extractSseResponse(checkpoint.data, body);\n checkpoint = { ...checkpoint, data: body };\n } else {\n sseResponse = defaultSseResponse(checkpoint.data);\n }\n return this.wrapResultAsSse(checkpoint, sseResponse);\n }\n\n // Response pass-through: deliver as-is. Checkpoint null because the\n // Response body (ReadableStream) can only be consumed once.\n if (checkpoint.data instanceof Response) {\n void this.checkpointReturnValue(null);\n return this.transformOutput({ data: checkpoint.data });\n }\n\n // Non-streaming path\n await this.checkpoint([\n {\n op: StepOpCode.RunComplete,\n id: hashId(RUN_COMPLETE_STEP_ID),\n data: await this.options.createResponse!(\n jsonResponse(checkpoint.data),\n ),\n },\n ]);\n\n // Apply middleware transformation before returning\n return this.transformOutput({ data: checkpoint.data });\n },\n\n \"function-rejected\": async (checkpoint) => {\n const usingSseStream = !!this.earlyStreamResponse;\n const isFinal = !this.retriability(checkpoint.error);\n\n if (this.streamTools.activated && usingSseStream) {\n // SSE path: checkpoint the error, then close the stream.\n // The checkpoint triggers sendRedirectIfReady which starts\n // the (near-instant) redirect URL resolution. Chaining the\n // close as a continuation ensures the redirect event is\n // written first, without blocking the handler's return on\n // the checkpoint's retry budget.\n void (async () => {\n try {\n await this.checkpoint([\n {\n id: hashId(RUN_COMPLETE_STEP_ID),\n op: isFinal ? StepOpCode.StepFailed : StepOpCode.StepError,\n error: checkpoint.error,\n },\n ]);\n } catch (err) {\n this.options.client[internalLoggerSymbol].warn(\n { err },\n \"Failed to checkpoint function error\",\n );\n }\n\n if (isFinal) {\n await this.streamCloseFailed(errorMessage(checkpoint.error));\n } else {\n await this.streamEnd();\n }\n })();\n\n return this.transformOutput({ error: checkpoint.error });\n }\n\n // If the function throws during sync execution, we want to switch to\n // async mode so that we can retry. The exception is that we're already\n // at max attempts, in which case we do actually want to reject.\n if (isFinal) {\n return this.transformOutput({ error: checkpoint.error });\n }\n\n // Retryable — checkpoint the error and switch to async mode.\n // checkpointAndSwitchToAsync handles closing the stream.\n return this.checkpointAndSwitchToAsync([\n {\n id: hashId(RUN_COMPLETE_STEP_ID),\n op: StepOpCode.StepError,\n error: checkpoint.error,\n },\n ]);\n },\n\n \"step-not-found\": () => {\n return {\n type: \"function-rejected\",\n ctx: this.fnArg,\n error: new Error(\n \"Step not found when checkpointing; this should never happen\",\n ),\n ops: this.ops,\n retriable: false,\n };\n },\n\n \"steps-found\": async ({ steps }) => {\n // If we're entering parallelism or async mode, checkpoint and switch\n // to async.\n if (steps.length !== 1 || steps[0].mode !== StepMode.Sync) {\n return this.checkpointAndSwitchToAsync(\n steps.map((step) => ({ ...step, id: step.hashedId })),\n );\n }\n\n // Otherwise we're good to start executing things right now.\n const result = await this.executeStep(steps[0]);\n\n const transformed = await stepRanHandler(result);\n if (transformed.type !== \"step-ran\") {\n throw new Error(\n \"Unexpected checkpoint handler result type after running step in sync mode\",\n );\n }\n\n if (result.error) {\n return this.checkpointAndSwitchToAsync(\n [transformed.step],\n result.error,\n );\n }\n\n // Resume the step with original data for user code\n //\n // Note: We should likely also pass this through `transformOutput` and\n // then `transformInput` to mimic the entire middleware cycle, to ensure\n // that any transformations that purposefully skew the resulting type\n // are supported.\n const stepToResume = this.resumeStepWithResult(result);\n\n // Clear executingStep now that the step result has been processed.\n // Without this, the next step discovery would see stale state and\n // emit a false positive NESTING_STEPS warning.\n delete this.state.executingStep;\n\n // Checkpoint with transformed data from middleware\n const stepForCheckpoint = {\n ...stepToResume,\n data: transformed.step.data,\n };\n\n return void (await this.checkpoint([stepForCheckpoint]));\n },\n\n \"checkpointing-runtime-reached\": () => {\n return this.checkpointAndSwitchToAsync([\n {\n op: StepOpCode.DiscoveryRequest,\n\n // Append with time because we don't want Executor-side\n // idempotency to dedupe. There may have been a previous\n // discovery request.\n id: _internals.hashId(`discovery-request-${Date.now()}`),\n },\n ]);\n },\n\n \"checkpointing-buffer-interval-reached\": () => {\n return attemptCheckpointAndResume(undefined, false, true);\n },\n };\n\n const asyncHandlers: CheckpointHandlers[StepMode.Async] = {\n /**\n * Run for all checkpoints. Best used for logging or common actions.\n * Use other handlers to return values and interrupt the core loop.\n */\n \"\": commonCheckpointHandler,\n\n /**\n * The user's function has completed and returned a value.\n */\n \"function-resolved\": async ({ data }) => {\n let resultData: unknown = data;\n let sseResponse: SseResponse;\n if (data instanceof Response) {\n const body = await data.text();\n sseResponse = extractSseResponse(data, body);\n resultData = body;\n } else {\n sseResponse = defaultSseResponse(resultData);\n }\n\n // Check for unreported new steps (e.g. from `Promise.race` where\n // the winning branch completed before losing branches reported)\n // before closing the stream — once closed, no more events can be sent.\n const newStepsResult = await maybeReturnNewSteps();\n if (newStepsResult) {\n return newStepsResult;\n }\n\n // Close the stream with a terminal succeeded event.\n await this.streamCloseSucceeded(sseResponse);\n\n // If stream was never activated, start the POST now so the\n // client waiting at the GET endpoint gets the result event.\n if (!this.streamTools.activated) {\n this.postCheckpointStream();\n }\n\n // We need to do this even here for async, as we could be returning\n // data from an API endpoint, even if we were triggered async.\n if (this.options.createResponse) {\n data = await this.options.createResponse(jsonResponse(resultData));\n }\n\n return this.transformOutput({ data });\n },\n\n /**\n * The user's function has thrown an error.\n */\n \"function-rejected\": async (checkpoint) => {\n const isFinal = !this.retriability(checkpoint.error);\n\n if (isFinal) {\n await this.streamCloseFailed(errorMessage(checkpoint.error));\n } else {\n // Retryable error — suppress the result event; the run will retry.\n await this.streamEnd();\n }\n\n if (!this.streamTools.activated) {\n this.postCheckpointStream();\n }\n\n return this.transformOutput({ error: checkpoint.error });\n },\n\n /**\n * We've found one or more steps. Here we may want to run a step or report\n * them back to Inngest.\n */\n \"steps-found\": async ({ steps }) => {\n const stepResult = await this.tryExecuteStep(steps);\n if (stepResult) {\n return stepRanHandler(stepResult);\n }\n\n return maybeReturnNewSteps();\n },\n\n /**\n * While trying to find a step that Inngest has told us to run, we've\n * timed out or have otherwise decided that it doesn't exist.\n */\n \"step-not-found\": ({ step }) => {\n const { foundSteps, totalFoundSteps } = this.getStepNotFoundDetails();\n return {\n type: \"step-not-found\",\n ctx: this.fnArg,\n ops: this.ops,\n step,\n foundSteps,\n totalFoundSteps,\n };\n },\n\n \"checkpointing-runtime-reached\": () => {\n throw new Error(\n \"Checkpointing maximum runtime reached, but this is not in a checkpointing step mode. This is a bug in the Inngest SDK.\",\n );\n },\n\n \"checkpointing-buffer-interval-reached\": () => {\n throw new Error(\n \"Checkpointing maximum buffer interval reached, but this is not in a checkpointing step mode. This is a bug in the Inngest SDK.\",\n );\n },\n };\n\n const asyncCheckpointingHandlers: CheckpointHandlers[StepMode.AsyncCheckpointing] =\n {\n \"\": commonCheckpointHandler,\n \"function-resolved\": async (checkpoint, i) => {\n const output = await asyncHandlers[\"function-resolved\"](\n checkpoint,\n i,\n );\n if (output?.type === \"function-resolved\") {\n const steps = this.state.checkpointingStepBuffer.concat({\n op: StepOpCode.RunComplete,\n id: hashId(RUN_COMPLETE_STEP_ID),\n data: output.data,\n });\n\n if (isNonEmpty(steps)) {\n return {\n type: \"steps-found\",\n ctx: output.ctx,\n ops: output.ops,\n steps,\n };\n }\n }\n\n return;\n },\n \"function-rejected\": async (checkpoint) => {\n // If we have buffered steps, attempt checkpointing them first\n if (this.state.checkpointingStepBuffer.length) {\n const fallback = await attemptCheckpointAndResume(\n undefined,\n false,\n true,\n );\n if (fallback) {\n return fallback;\n }\n }\n\n return await this.transformOutput({ error: checkpoint.error });\n },\n \"step-not-found\": asyncHandlers[\"step-not-found\"],\n \"steps-found\": async ({ steps }) => {\n // Note that if we have a requested run step, we'll never be\n // checkpointing, as that's an async parallel execution mode.\n\n // Break found steps in to { stepsToResume, newSteps }\n const { stepsToResume, newSteps } = steps.reduce(\n (acc, step) => {\n if (!step.hasStepState) {\n acc.newSteps.push(step);\n } else if (!step.fulfilled) {\n acc.stepsToResume.push(step);\n }\n\n return acc;\n },\n { stepsToResume: [], newSteps: [] } as {\n stepsToResume: FoundStep[];\n newSteps: FoundStep[];\n },\n );\n\n this.devDebug(\"split found steps in to:\", {\n stepsToResume: stepsToResume.length,\n newSteps: newSteps.length,\n });\n\n // Got new steps? Exit early.\n if (!this.options.requestedRunStep && newSteps.length) {\n const stepResult = await this.tryExecuteStep(newSteps);\n if (stepResult) {\n this.devDebug(`executed step \"${stepResult.id}\" successfully`);\n\n // We executed a step!\n //\n // We know that because we're in this mode, we're always free to\n // checkpoint and continue if we ran a step and it was successful.\n if (stepResult.error) {\n // Flush buffered steps before falling back to async,\n // so previously-successful steps aren't lost.\n if (this.state.checkpointingStepBuffer.length) {\n const fallback = await attemptCheckpointAndResume(\n undefined,\n false,\n true,\n );\n if (fallback) {\n return fallback;\n }\n }\n\n return stepRanHandler(stepResult);\n }\n\n // If we're here, we successfully ran a step, so we may now need\n // to checkpoint it depending on the step buffer configured.\n return await attemptCheckpointAndResume(stepResult);\n }\n\n // Flush any buffered checkpoint steps before returning\n // new steps to the executor. Without this, steps executed\n // in-process during AsyncCheckpointing but not yet\n // checkpointed would be lost. When the executor later calls\n // back with requestedRunStep, those steps would be missing\n // from stepState, causing \"step not found\" errors.\n if (this.state.checkpointingStepBuffer.length) {\n const fallback = await attemptCheckpointAndResume(\n undefined,\n false,\n true,\n );\n if (fallback) {\n return fallback;\n }\n }\n\n return maybeReturnNewSteps();\n }\n\n // If we have stepsToResume, resume as many as possible and resume execution\n if (stepsToResume.length) {\n this.devDebug(`resuming ${stepsToResume.length} steps`);\n\n for (const st of stepsToResume) {\n this.resumeStepWithResult({\n ...st,\n id: st.hashedId,\n });\n }\n }\n\n return;\n },\n \"checkpointing-runtime-reached\": async () => {\n this.options.client[internalLoggerSymbol].debug(\n \"Checkpointing runtime reached; sending discovery request\",\n );\n\n return {\n type: \"steps-found\",\n ctx: this.fnArg,\n ops: this.ops,\n steps: [\n {\n op: StepOpCode.DiscoveryRequest,\n\n // Append with time because we don't want Executor-side\n // idempotency to dedupe. There may have been a previous\n // discovery request.\n id: _internals.hashId(`discovery-request-${Date.now()}`),\n },\n ],\n };\n },\n\n \"checkpointing-buffer-interval-reached\": () => {\n return attemptCheckpointAndResume(undefined, false, true);\n },\n };\n\n return {\n [StepMode.Async]: asyncHandlers,\n [StepMode.Sync]: syncHandlers,\n [StepMode.AsyncCheckpointing]: asyncCheckpointingHandlers,\n };\n }\n\n private getCheckpointHandler(type: keyof CheckpointHandlers[StepMode]) {\n return this.checkpointHandlers[this.options.stepMode][type] as (\n checkpoint: Checkpoint,\n iteration: number,\n ) => MaybePromise<ExecutionResult | undefined>;\n }\n\n private async tryExecuteStep(\n steps: FoundStep[],\n ): Promise<OutgoingOp | undefined> {\n const hashedStepIdToRun =\n this.options.requestedRunStep || this.getEarlyExecRunStep(steps);\n if (!hashedStepIdToRun) {\n return;\n }\n\n const step = steps.find(\n (step) => step.hashedId === hashedStepIdToRun && step.fn,\n );\n\n if (step) {\n return await this.executeStep(step);\n }\n\n /**\n * Ensure we reset the timeout if we have a requested run step but couldn't\n * find it, but also that we don't reset if we found and executed it.\n */\n return void this.timeout?.reset();\n }\n\n /**\n * Given a list of outgoing ops, decide if we can execute an op early and\n * return the ID of the step to execute if we can.\n */\n private getEarlyExecRunStep(steps: FoundStep[]): string | undefined {\n /**\n * We may have been disabled due to parallelism, in which case we can't\n * immediately execute unless explicitly requested.\n */\n if (this.options.disableImmediateExecution) return;\n\n const unfulfilledSteps = steps.filter((step) => !step.fulfilled);\n if (unfulfilledSteps.length !== 1) return;\n\n const op = unfulfilledSteps[0];\n\n if (\n op &&\n op.op === StepOpCode.StepPlanned\n // TODO We must individually check properties here that we do not want to\n // execute on, such as retry counts. Nothing exists here that falls in to\n // this case, but should be accounted for when we add them.\n // && typeof op.opts === \"undefined\"\n ) {\n return op.hashedId;\n }\n\n return;\n }\n\n private async filterNewSteps(\n foundSteps: FoundStep[],\n ): Promise<[OutgoingOp, ...OutgoingOp[]] | undefined> {\n if (this.options.requestedRunStep) {\n return;\n }\n\n const newSteps = foundSteps.reduce((acc, step) => {\n if (!step.hasStepState) {\n acc.push(step);\n }\n\n return acc;\n }, [] as FoundStep[]);\n\n if (!newSteps.length) {\n return;\n }\n\n await this.middlewareManager.onMemoizationEnd();\n\n const stepList = newSteps.map<OutgoingOp>((step) => {\n return {\n displayName: step.displayName,\n op: step.op,\n id: step.hashedId,\n name: step.name,\n opts: step.opts,\n userland: step.userland,\n };\n });\n\n if (!isNonEmpty(stepList)) {\n throw new UnreachableError(\"stepList is empty\");\n }\n\n return stepList;\n }\n\n private async executeStep(foundStep: FoundStep): Promise<OutgoingOp> {\n const { id, name, opts, fn, displayName, userland, hashedId } = foundStep;\n const { stepInfo, wrappedHandler, setActualHandler } = foundStep.middleware;\n\n this.devDebug(`preparing to execute step \"${id}\"`);\n\n this.timeout?.clear();\n\n const outgoingOp: OutgoingOp = {\n id: hashedId,\n op: StepOpCode.StepRun,\n name,\n opts,\n displayName,\n userland,\n };\n this.state.executingStep = outgoingOp;\n\n const store = await getAsyncCtx();\n\n if (store?.execution) {\n store.execution.executingStep = {\n id,\n name: displayName,\n hashedId,\n };\n }\n\n this.devDebug(`executing step \"${id}\"`);\n\n if (this.rootSpanId && this.options.checkpointingConfig) {\n clientProcessorMap\n .get(this.options.client)\n ?.declareStepExecution(\n this.rootSpanId,\n userland.id ?? \"\",\n userland.index ?? 0,\n hashedId,\n this.options.data?.attempt ?? 0,\n );\n }\n\n let interval: GoInterval | undefined;\n\n // `fn` already has middleware-transformed args baked in via `fnArgs` (i.e.\n // the `transformStepInput` middleware hook already ran).\n const actualHandler = () => runAsPromise(fn);\n\n await this.middlewareManager.onMemoizationEnd();\n await this.middlewareManager.onStepStart(stepInfo);\n\n // If wrappedHandler hasn't been called yet (no deferred from discovery),\n // set one up so wrapStep's next() still blocks until memoization.\n if (!foundStep.memoizationDeferred) {\n const deferred = createDeferredPromise<unknown>();\n foundStep.memoizationDeferred = deferred;\n setActualHandler(() => deferred.promise);\n foundStep.transformedResultPromise = wrappedHandler();\n foundStep.transformedResultPromise.catch(() => {\n // Swallow — errors handled by handle()\n });\n }\n\n // Build wrapStepHandler chain around the actual handler\n const wrappedActualHandler =\n this.middlewareManager.buildWrapStepHandlerChain(actualHandler, stepInfo);\n\n return goIntervalTiming(() => wrappedActualHandler())\n .finally(() => {\n this.devDebug(`finished executing step \"${id}\"`);\n\n this.state.executingStep = undefined;\n\n if (this.rootSpanId && this.options.checkpointingConfig) {\n clientProcessorMap\n .get(this.options.client)\n ?.clearStepExecution(this.rootSpanId);\n }\n\n if (store?.execution) {\n delete store.execution.executingStep;\n }\n })\n .then<OutgoingOp>(async ({ resultPromise, interval: _interval }) => {\n interval = _interval;\n const metadata = this.state.metadata?.get(id);\n const serverData = await resultPromise;\n\n // Don't resolve memoizationDeferred here. wrapStep's next() must\n // block until the step is actually memoized (i.e. handle() fires\n // with confirmed data from the server). handle() resolves it.\n await this.middlewareManager.onStepComplete(stepInfo, serverData);\n\n // Emit inngest.commit — step data is finalized.\n this.streamTools.commit(hashedId);\n\n return {\n ...outgoingOp,\n data: serverData,\n ...(metadata && metadata.length > 0 ? { metadata: metadata } : {}),\n };\n })\n .catch<OutgoingOp>((error) => {\n // Don't reject memoizationDeferred — handle() will reject it when\n // the error is memoized.\n return this.buildStepErrorOp({\n error,\n id,\n outgoingOp,\n stepInfo,\n });\n })\n .then((op) => ({\n ...op,\n timing: interval,\n }));\n }\n\n /**\n * Starts execution of the user's function, including triggering checkpoints\n * and middleware hooks where appropriate.\n */\n private async startExecution(): Promise<void> {\n /**\n * Start the timer to time out the run if needed.\n */\n void this.timeout?.start();\n void this.checkpointingMaxRuntimeTimer?.start();\n void this.checkpointingMaxBufferIntervalTimer?.start();\n\n const fnInputResult = await this.middlewareManager.transformFunctionInput();\n this.applyFunctionInputMutations(fnInputResult);\n\n if (this.state.allStateUsed()) {\n await this.middlewareManager.onMemoizationEnd();\n }\n\n if (this.state.stepsToFulfill === 0 && this.fnArg.attempt === 0) {\n await this.middlewareManager.onRunStart();\n }\n\n const innerHandler: () => Promise<unknown> = async () => {\n await this.validateEventSchemas();\n return this.userFnToRun(this.fnArg);\n };\n\n const runHandler = this.middlewareManager.wrapRunHandler(innerHandler);\n\n runAsPromise(runHandler)\n .then(async (data) => {\n await this.middlewareManager.onRunComplete(data);\n this.state.setCheckpoint({ type: \"function-resolved\", data });\n })\n .catch(async (error) => {\n // Preserve Error instances; stringify non-Error throws (e.g. `throw {}`)\n let err: Error;\n if (error instanceof Error) {\n err = error;\n } else if (typeof error === \"object\") {\n err = new Error(JSON.stringify(error));\n } else {\n err = new Error(String(error));\n }\n\n await this.middlewareManager.onRunError(err, !this.retriability(err));\n this.state.setCheckpoint({ type: \"function-rejected\", error: err });\n });\n }\n\n /**\n * Determine whether the given error is retriable. Returns `false` when the\n * run should not be retried, a duration string for `RetryAfterError`, or\n * `true` for normal retry behavior.\n */\n private retriability(error: unknown): boolean | string {\n const areRetriesExhausted =\n this.fnArg.maxAttempts &&\n this.fnArg.maxAttempts - 1 === this.fnArg.attempt;\n if (areRetriesExhausted) {\n return false;\n }\n\n // TODO: Replace this fragile inheritance + name check. Maybe we should have\n // an \"~inngest\" field with an object that specifies \"isRetriable\".\n if (\n error instanceof NonRetriableError ||\n // biome-ignore lint/suspicious/noExplicitAny: instanceof fails across module boundaries\n (error as any)?.name === \"NonRetriableError\"\n ) {\n return false;\n }\n\n // If the function-level code did not change the error, then we don't want\n // to retry. The vast majority of the time this means there wasn't a `catch`\n // block.\n const isUncaughtStepError =\n error instanceof StepError &&\n error === this.state.recentlyRejectedStepError;\n if (isUncaughtStepError) {\n return false;\n }\n\n // TODO: Replace this fragile inheritance + name check. Maybe we should have\n // an \"~inngest\" field with an object that specifies \"retryAfter\".\n if (\n error instanceof RetryAfterError ||\n // biome-ignore lint/suspicious/noExplicitAny: instanceof fails across module boundaries\n (error as any)?.name === \"RetryAfterError\"\n ) {\n return (error as RetryAfterError).retryAfter;\n }\n\n return true;\n }\n\n /**\n * Build the OutgoingOp for a failed step, notifying middleware and choosing\n * retriable vs non-retriable opcode.\n */\n private async buildStepErrorOp({\n error,\n id,\n outgoingOp,\n stepInfo,\n }: {\n error: unknown;\n id: string;\n outgoingOp: OutgoingOp;\n stepInfo: Middleware.StepInfo;\n }): Promise<OutgoingOp> {\n const isFinal = !this.retriability(error);\n const metadata = this.state.metadata?.get(id);\n\n await this.middlewareManager.onStepError(\n stepInfo,\n error instanceof Error ? error : new Error(String(error)),\n isFinal,\n );\n\n // Step's stream should be rolled back\n this.streamTools.rollback(outgoingOp.id);\n\n // Serialize the error so it survives JSON.stringify (raw Error\n // objects have non-enumerable properties that get dropped).\n // This is critical for checkpoint requests where the error is\n // sent as JSON in the request body.\n const serialized = serializeError(error);\n\n return {\n ...outgoingOp,\n error: serialized,\n op: isFinal ? StepOpCode.StepFailed : StepOpCode.StepError,\n ...(metadata && metadata.length > 0 ? { metadata } : {}),\n };\n }\n\n /**\n * Validate event data against schemas defined in function triggers.\n */\n private async validateEventSchemas(): Promise<void> {\n if (this.options.isFailureHandler) {\n // Skip validation because the main function's triggers don't apply to its\n // `onFailure` handler. The `onFailure` handler is a separate Inngest\n // function that's implicitly triggered by the \"inngest/function.failed\"\n // event.\n return;\n }\n\n const triggers = this.options.fn.opts.triggers;\n if (!triggers || triggers.length === 0) return;\n\n const fnArgEvents = this.fnArg.events;\n if (!fnArgEvents || fnArgEvents.length === 0) return;\n\n const events = fnArgEvents.map((event) => ({\n name: event.name,\n data: event.data,\n }));\n\n await validateEvents(events, triggers);\n }\n\n /**\n * Using middleware, transform output before returning.\n */\n private transformOutput(dataOrError: {\n data?: unknown;\n error?: unknown;\n }): ExecutionResult {\n const { data, error } = dataOrError;\n\n if (typeof error !== \"undefined\") {\n const retriable = this.retriability(error);\n const serializedError = serializeError(error);\n\n return {\n type: \"function-rejected\",\n ctx: this.fnArg,\n ops: this.ops,\n error: serializedError,\n retriable,\n };\n }\n\n return {\n type: \"function-resolved\",\n ctx: this.fnArg,\n ops: this.ops,\n data: undefinedToNull(data),\n };\n }\n\n private createExecutionState(): ExecutionState {\n const d = createDeferredPromiseWithStack<Checkpoint>();\n let checkpointResolve = d.deferred.resolve;\n const checkpointResults = d.results;\n\n const loop: ExecutionState[\"loop\"] = (async function* (\n cleanUp?: () => void,\n ) {\n try {\n while (true) {\n const res = (await checkpointResults.next()).value;\n if (res) {\n yield res;\n }\n }\n } finally {\n cleanUp?.();\n }\n })(() => {\n this.timeout?.clear();\n this.checkpointingMaxRuntimeTimer?.clear();\n this.checkpointingMaxBufferIntervalTimer?.clear();\n void checkpointResults.return();\n });\n\n const stepsToFulfill = Object.keys(this.options.stepState).length;\n\n const state: ExecutionState = {\n stepState: this.options.stepState,\n stepsToFulfill,\n steps: new Map(),\n loop,\n hasSteps: Boolean(stepsToFulfill),\n stepCompletionOrder: [...this.options.stepCompletionOrder],\n remainingStepsToBeSeen: new Set(this.options.stepCompletionOrder),\n setCheckpoint: (checkpoint: Checkpoint) => {\n this.devDebug(\"setting checkpoint:\", checkpoint.type);\n\n ({ resolve: checkpointResolve } = checkpointResolve(checkpoint));\n },\n allStateUsed: () => {\n return this.state.remainingStepsToBeSeen.size === 0;\n },\n checkpointingStepBuffer: [],\n metadata: new Map(),\n };\n\n return state;\n }\n\n get ops(): Record<string, MemoizedOp> {\n return Object.fromEntries(this.state.steps);\n }\n\n private createFnArg(): Context.Any {\n const step = this.createStepTools();\n const experimentStepRun = (step as unknown as ExperimentStepTools)[\n experimentStepRunSymbol\n ];\n\n let fnArg = {\n ...(this.options.data as { event: EventPayload }),\n step,\n group: createGroupTools({ experimentStepRun }),\n } as Context.Any;\n\n /**\n * Handle use of the `onFailure` option by deserializing the error.\n */\n if (this.options.isFailureHandler) {\n const eventData = z\n .object({ error: jsonErrorSchema })\n .parse(fnArg.event?.data);\n\n (fnArg as Partial<Pick<FailureEventArgs, \"error\">>) = {\n ...fnArg,\n error: deserializeError(eventData.error),\n };\n }\n\n return this.options.transformCtx?.(fnArg) ?? fnArg;\n }\n\n /**\n * Apply mutations from `transformFunctionInput` back to execution state.\n * Allows middleware to modify event data, step tools, memoized step data,\n * and inject custom fields into the handler context.\n */\n private applyFunctionInputMutations(\n result: Middleware.TransformFunctionInputArgs,\n ): void {\n const { event, events, step, ...extensions } = result.ctx;\n\n // Mutate in place so the ALS store's reference to this.fnArg stays valid.\n if (event !== this.fnArg.event) {\n this.fnArg.event = event;\n }\n\n if (events !== this.fnArg.events) {\n this.fnArg.events = events;\n }\n\n if (step !== this.fnArg.step) {\n this.fnArg.step = step;\n }\n\n if (Object.keys(extensions).length > 0) {\n Object.assign(this.fnArg, extensions);\n }\n\n // Apply step data mutations\n for (const [hashedId, stepData] of Object.entries(result.steps)) {\n const existing = this.state.stepState[hashedId];\n if (\n existing &&\n stepData &&\n stepData.type === \"data\" &&\n stepData.data !== existing.data\n ) {\n this.state.stepState[hashedId] = { ...existing, data: stepData.data };\n }\n }\n }\n\n private createStepTools(): ReturnType<typeof createStepTools> {\n /**\n * A list of steps that have been found and are being rolled up before being\n * reported to the core loop.\n */\n const foundStepsToReport: Map<string, FoundStep> = new Map();\n\n /**\n * A map of the subset of found steps to report that have not yet been\n * handled. Used for fast access to steps that need to be handled in order.\n */\n const unhandledFoundStepsToReport: Map<string, FoundStep> = new Map();\n\n /**\n * A map of the latest sequential step indexes found for each step ID. Used\n * to ensure that we don't index steps in parallel.\n *\n * Note that these must be sequential; if we've seen or assigned `a:1`,\n * `a:2` and `a:4`, the latest sequential step index is `2`.\n *\n */\n const expectedNextStepIndexes: Map<string, number> = new Map();\n\n /**\n * An ordered list of step IDs that have yet to be handled in this\n * execution. Used to ensure that we handle steps in the order they were\n * found and based on the `stepCompletionOrder` in this execution's state.\n */\n const remainingStepCompletionOrder: string[] =\n this.state.stepCompletionOrder.slice();\n\n /**\n * A promise that's used to ensure that step reporting cannot be run more than\n * once in a given asynchronous time span.\n */\n let foundStepsReportPromise: Promise<void> | undefined;\n\n /**\n * A flag used to ensure that we only warn about parallel indexing once per\n * execution to avoid spamming the console.\n */\n let warnOfParallelIndexing = false;\n\n /**\n * Counts the number of times we've extended this tick.\n */\n let tickExtensionCount = 0;\n\n /**\n * Given a colliding step ID, maybe warn the user about parallel indexing.\n */\n const maybeWarnOfParallelIndexing = (userlandCollisionId: string) => {\n if (warnOfParallelIndexing) {\n return;\n }\n\n const hashedCollisionId = _internals.hashId(userlandCollisionId);\n\n const stepExists = this.state.steps.has(hashedCollisionId);\n if (stepExists) {\n const stepFoundThisTick = foundStepsToReport.has(hashedCollisionId);\n if (!stepFoundThisTick) {\n warnOfParallelIndexing = true;\n\n this.options.client[\"warnMetadata\"](\n { run_id: this.fnArg.runId },\n ErrCode.AUTOMATIC_PARALLEL_INDEXING,\n {\n message: `Duplicate step ID \"${userlandCollisionId}\" detected across parallel chains`,\n explanation:\n \"Using the same ID for steps in different parallel chains can cause unexpected behaviour. Your function is still running.\",\n action:\n \"Use a unique ID for each step, especially those in parallel.\",\n code: ErrCode.AUTOMATIC_PARALLEL_INDEXING,\n },\n );\n }\n }\n };\n\n /**\n * A helper used to report steps to the core loop. Used after adding an item\n * to `foundStepsToReport`.\n */\n const reportNextTick = () => {\n // Being explicit instead of using `??=` to appease TypeScript.\n if (foundStepsReportPromise) {\n return;\n }\n\n let extensionPromise: Promise<void>;\n if (++tickExtensionCount >= 10) {\n tickExtensionCount = 0;\n extensionPromise = resolveNextTick();\n } else {\n extensionPromise = resolveAfterPending();\n }\n\n foundStepsReportPromise = extensionPromise.then(() => {\n foundStepsReportPromise = undefined;\n\n for (let i = 0; i < remainingStepCompletionOrder.length; i++) {\n const nextStepId = remainingStepCompletionOrder[i];\n if (!nextStepId) {\n // Strange - skip this empty index\n continue;\n }\n\n const handled = unhandledFoundStepsToReport.get(nextStepId)?.handle();\n if (handled) {\n remainingStepCompletionOrder.splice(i, 1);\n unhandledFoundStepsToReport.delete(nextStepId);\n return void reportNextTick();\n }\n }\n\n // If we've handled no steps in this \"tick,\" roll up everything we've\n // found and report it.\n const steps = [...foundStepsToReport.values()];\n foundStepsToReport.clear();\n unhandledFoundStepsToReport.clear();\n\n if (!isNonEmpty(steps)) {\n return;\n }\n\n return void this.state.setCheckpoint({\n type: \"steps-found\",\n steps: steps,\n });\n });\n };\n\n /**\n * A helper used to push a step to the list of steps to report.\n */\n const pushStepToReport = (step: FoundStep) => {\n foundStepsToReport.set(step.hashedId, step);\n unhandledFoundStepsToReport.set(step.hashedId, step);\n reportNextTick();\n };\n\n const stepHandler: StepHandler = async ({\n args,\n matchOp,\n opts,\n }): Promise<unknown> => {\n const stepOptions = getStepOptions(args[0]);\n const opId = matchOp(stepOptions, ...args.slice(1));\n\n if (this.state.executingStep) {\n /**\n * If a step is found after asynchronous actions during another step's\n * execution, everything is fine. The problem here is if we've found\n * that a step nested inside another a step, which is something we don't\n * support at the time of writing.\n *\n * In this case, we could use something like Async Hooks to understand\n * how the step is being triggered, though this isn't available in all\n * environments.\n *\n * Therefore, we'll only show a warning here to indicate that this is\n * potentially an issue.\n */\n this.options.client[\"warnMetadata\"](\n { run_id: this.fnArg.runId },\n ErrCode.NESTING_STEPS,\n {\n message: `Nested step tooling detected in \"${opId.displayName ?? opId.id}\"`,\n explanation:\n \"Nesting step.* calls is not supported. This warning may also appear if steps are separated by regular async calls, which is fine.\",\n action:\n \"Avoid using step.* inside other step.* calls. Use a separate async function or promise chaining to compose steps.\",\n code: ErrCode.NESTING_STEPS,\n },\n );\n }\n\n // Apply middleware transformations (may change step ID, affecting\n // memoization lookup)\n const {\n hashedId,\n isFulfilled,\n setActualHandler,\n stepInfo,\n stepState,\n wrappedHandler,\n } = await this.applyMiddlewareToStep(\n opId,\n expectedNextStepIndexes,\n maybeWarnOfParallelIndexing,\n );\n\n const { promise, resolve, reject } = createDeferredPromise();\n\n let extraOpts: Record<string, unknown> | undefined;\n let fnArgs = [...args];\n\n if (\n typeof stepState?.input !== \"undefined\" &&\n Array.isArray(stepState.input)\n ) {\n switch (opId.op) {\n // `step.run()` has its function input affected\n case StepOpCode.StepPlanned: {\n fnArgs = [...args.slice(0, 2), ...stepState.input];\n\n extraOpts = { input: [...stepState.input] };\n break;\n }\n\n // `step.ai.infer()` has its body affected\n case StepOpCode.AiGateway: {\n extraOpts = {\n body: {\n ...(typeof opId.opts?.body === \"object\"\n ? { ...opId.opts.body }\n : {}),\n ...stepState.input[0],\n },\n };\n break;\n }\n }\n }\n\n // If transformStepInput middleware may have changed the input, update\n // `fnArgs` so `fn` uses the transformed values. Skip if replay already\n // set `extraOpts`.\n if (!extraOpts && Array.isArray(stepInfo.input)) {\n fnArgs = [...args.slice(0, 2), ...stepInfo.input];\n }\n\n const step: FoundStep = {\n ...opId,\n opts: { ...opId.opts, ...extraOpts },\n rawArgs: fnArgs,\n hashedId,\n input: stepState?.input,\n\n fn: opts?.fn ? () => opts.fn?.(this.fnArg, ...fnArgs) : undefined,\n promise,\n fulfilled: isFulfilled,\n hasStepState: Boolean(stepState),\n displayName: opId.displayName ?? opId.id,\n handled: false,\n\n // Middleware context for deferred handler pattern\n middleware: {\n wrappedHandler,\n stepInfo,\n setActualHandler,\n },\n\n handle: () => {\n if (step.handled) {\n return false;\n }\n\n this.devDebug(`handling step \"${hashedId}\"`);\n\n step.handled = true;\n\n // Refetch step state because it may have been changed since we found\n // the step. This could be due to checkpointing, where we run this\n // live and then return to the function.\n const result = this.state.stepState[hashedId];\n\n if (step.fulfilled && result) {\n result.fulfilled = true;\n\n // For some execution scenarios such as testing, `data`, `error`,\n // and `input` may be `Promises`. This could also be the case for\n // future middleware applications. For this reason, we'll make sure\n // the values are fully resolved before continuing.\n void Promise.all([result.data, result.error, result.input]).then(\n async () => {\n // If the wrapStep chain already ran during discovery in this\n // same request (checkpointing), reuse its result instead of\n // firing wrappedHandler() again. This prevents middleware from\n // seeing a duplicate wrapStep call per step per request.\n if (step.transformedResultPromise) {\n // Resolve the memoization deferred so wrapStep's next()\n // unblocks. The step data is now confirmed memoized.\n if (step.memoizationDeferred) {\n if (typeof result.data !== \"undefined\") {\n step.memoizationDeferred.resolve(await result.data);\n } else {\n const stepError = new StepError(opId.id, result.error);\n this.state.recentlyRejectedStepError = stepError;\n step.memoizationDeferred.reject(stepError);\n }\n }\n\n step.transformedResultPromise.then(resolve, reject);\n return;\n }\n\n // The wrapStep chain is about to fire again to resolve the\n // step promise through middleware (e.g. deserialization).\n // Mark the step as memoized so middleware can distinguish\n // this from the original execution call.\n //\n // This need for this change was discovered when checkpointing +\n // middleware's \"double `wrapStep` call\" behavior had `memoized:\n // false` on the 2nd call\n step.middleware.stepInfo.memoized = true;\n\n if (typeof result.data !== \"undefined\") {\n // Validate waitForEvent results against the schema if present\n // Skip validation if result.data is null (timeout case)\n if (\n opId.op === StepOpCode.WaitForEvent &&\n result.data !== null\n ) {\n const { event } = (step.rawArgs?.[1] ?? {}) as {\n event: unknown;\n };\n if (!event) {\n // Unreachable\n throw new Error(\"Missing event option in waitForEvent\");\n }\n try {\n await validateEvents(\n [result.data],\n\n // @ts-expect-error - This is a full event object at runtime\n [{ event }],\n );\n } catch (err) {\n this.state.recentlyRejectedStepError = new StepError(\n opId.id,\n err,\n );\n reject(this.state.recentlyRejectedStepError);\n return;\n }\n }\n\n // Set inner handler to return memoized data\n step.middleware.setActualHandler(() =>\n Promise.resolve(result.data),\n );\n\n step.middleware.wrappedHandler().then(resolve);\n } else {\n const stepError = new StepError(opId.id, result.error);\n this.state.recentlyRejectedStepError = stepError;\n\n // Set inner handler to reject with step error\n step.middleware.setActualHandler(() =>\n Promise.reject(stepError),\n );\n\n step.middleware.wrappedHandler().catch(reject);\n }\n },\n );\n }\n\n return true;\n },\n };\n\n this.state.steps.set(hashedId, step);\n this.state.hasSteps = true;\n\n const isNewStepWithHandler = !isFulfilled && !stepState && step.fn;\n if (isNewStepWithHandler) {\n // New, never-seen step with a handler (e.g. `step.run`). Kick off the\n // middleware wrapStep chain now so it runs during discovery, not later\n // in executeStep.\n //\n // This is necessary so that middleware can inject their own steps.\n // Reporting is deferred to the center of the onion so that if\n // middleware throws or injects prerequisites, the step is never\n // reported.\n const deferred = createDeferredPromise<unknown>();\n step.memoizationDeferred = deferred;\n\n setActualHandler(() => {\n pushStepToReport(step);\n return deferred.promise;\n });\n\n step.transformedResultPromise = wrappedHandler();\n step.transformedResultPromise.catch((error) => {\n reject(error);\n });\n } else {\n pushStepToReport(step);\n }\n\n return promise;\n };\n\n return createStepTools(this.options.client, this, stepHandler);\n }\n\n /**\n * Applies middleware transformations to a step, resolves ID collisions,\n * and performs memoization lookup.\n */\n private async applyMiddlewareToStep(\n opId: HashedOp,\n expectedNextStepIndexes: Map<string, number>,\n maybeWarnOfParallelIndexing: (userlandCollisionId: string) => void,\n ): Promise<MiddlewareApplicationResult> {\n // 1. Resolve initial collision with original ID\n const initialCollision = resolveStepIdCollision({\n baseId: opId.id,\n expectedIndexes: expectedNextStepIndexes,\n stepsMap: this.state.steps,\n });\n if (initialCollision.finalId !== opId.id) {\n maybeWarnOfParallelIndexing(opId.id);\n opId.id = initialCollision.finalId;\n if (initialCollision.index !== undefined) {\n opId.userland.index = initialCollision.index;\n }\n }\n\n const originalId = opId.userland.id;\n let hashedId = _internals.hashId(opId.id);\n\n // 2. Apply middleware (stepType, input extraction, deferred handler).\n // Pass preliminary memoization status so middleware sees it.\n const prepared = await this.middlewareManager.applyToStep({\n displayName: opId.displayName ?? opId.userland.id,\n hashedId,\n memoized:\n Boolean(this.state.stepState[hashedId]) &&\n typeof this.state.stepState[hashedId]?.input === \"undefined\",\n op: opId.op,\n opts: opId.opts,\n userlandId: opId.userland.id,\n });\n const { entryPoint, opName, opOpts, setActualHandler, stepInfo } = prepared;\n\n if (opName !== undefined) {\n opId.name = opName;\n }\n if (opOpts !== undefined) {\n opId.opts = opOpts;\n }\n\n // 3. If middleware changed the step ID, re-resolve collisions\n if (stepInfo.options.id !== originalId) {\n opId.id = stepInfo.options.id;\n opId.userland.id = stepInfo.options.id;\n\n const secondCollision = resolveStepIdCollision({\n baseId: stepInfo.options.id,\n expectedIndexes: expectedNextStepIndexes,\n stepsMap: this.state.steps,\n });\n if (secondCollision.finalId !== stepInfo.options.id) {\n opId.id = secondCollision.finalId;\n opId.userland.id = secondCollision.finalId;\n stepInfo.options.id = secondCollision.finalId;\n if (secondCollision.index !== undefined) {\n opId.userland.index = secondCollision.index;\n }\n }\n\n // Recompute hashedId with final ID\n hashedId = _internals.hashId(opId.id);\n stepInfo.hashedId = hashedId;\n }\n\n // 4. Final memoization lookup with potentially modified hashedId.\n // Also marks step as seen and may trigger onMemoizationEnd.\n const stepState = this.state.stepState[hashedId];\n let isFulfilled = false;\n if (stepState) {\n stepState.seen = true;\n this.state.remainingStepsToBeSeen.delete(hashedId);\n\n if (this.state.allStateUsed()) {\n await this.middlewareManager.onMemoizationEnd();\n }\n\n if (typeof stepState.input === \"undefined\") {\n isFulfilled = true;\n }\n stepInfo.memoized = isFulfilled;\n } else {\n stepInfo.memoized = false;\n }\n\n // 5. Build wrapStep chain after all mutations so middleware sees final values\n const wrappedHandler = this.middlewareManager.buildWrapStepChain(\n entryPoint,\n stepInfo,\n );\n\n return {\n hashedId,\n stepInfo,\n wrappedHandler,\n setActualHandler,\n stepState,\n isFulfilled,\n };\n }\n\n private resumeStepWithResult(resultOp: OutgoingOp, resume = true): FoundStep {\n const userlandStep = this.state.steps.get(resultOp.id);\n if (!userlandStep) {\n throw new Error(\n \"Step not found in memoization state during async checkpointing; this should never happen and is a bug in the Inngest SDK\",\n );\n }\n\n const data = undefinedToNull(resultOp.data);\n\n userlandStep.data = data;\n userlandStep.timing = resultOp.timing;\n userlandStep.op = resultOp.op;\n userlandStep.id = resultOp.id;\n userlandStep.metadata = resultOp.metadata;\n\n if (resume) {\n userlandStep.fulfilled = true;\n userlandStep.hasStepState = true;\n this.state.stepState[resultOp.id] = userlandStep;\n\n userlandStep.handle();\n }\n\n return userlandStep;\n }\n\n private getUserFnToRun(): Handler.Any {\n if (!this.options.isFailureHandler) {\n return this.options.fn[\"fn\"];\n }\n\n if (!this.options.fn[\"onFailureFn\"]) {\n /**\n * Somehow, we've ended up detecting that this is a failure handler but\n * doesn't have an `onFailure` function. This should never happen.\n */\n throw new Error(\"Cannot find function `onFailure` handler\");\n }\n\n return this.options.fn[\"onFailureFn\"];\n }\n\n private initializeTimer(state: ExecutionState): void {\n if (!this.options.requestedRunStep) {\n return;\n }\n\n this.timeout = createTimeoutPromise(this.timeoutDuration);\n\n void this.timeout.then(async () => {\n await this.middlewareManager.onMemoizationEnd();\n const { foundSteps, totalFoundSteps } = this.getStepNotFoundDetails();\n state.setCheckpoint({\n type: \"step-not-found\",\n step: {\n id: this.options.requestedRunStep as string,\n op: StepOpCode.StepNotFound,\n },\n foundSteps,\n totalFoundSteps,\n });\n });\n }\n\n private getStepNotFoundDetails(): {\n foundSteps: BasicFoundStep[];\n totalFoundSteps: number;\n } {\n const foundSteps = [...this.state.steps.values()]\n .filter((step) => !step.hasStepState)\n .map<BasicFoundStep>((step) => ({\n id: step.hashedId,\n name: step.name,\n displayName: step.displayName,\n }))\n .sort((a, b) => a.id.localeCompare(b.id));\n\n return {\n foundSteps: foundSteps.slice(0, STEP_NOT_FOUND_MAX_FOUND_STEPS),\n totalFoundSteps: foundSteps.length,\n };\n }\n\n private initializeCheckpointRuntimeTimer(state: ExecutionState): void {\n this.devDebug(\n \"initializing checkpointing runtime timers\",\n this.options.checkpointingConfig,\n );\n\n if (this.options.checkpointingConfig?.maxRuntime) {\n const maxRuntimeMs = Temporal.isTemporalDuration(\n this.options.checkpointingConfig.maxRuntime,\n )\n ? this.options.checkpointingConfig.maxRuntime.total({\n unit: \"milliseconds\",\n })\n : typeof this.options.checkpointingConfig.maxRuntime === \"string\"\n ? ms(this.options.checkpointingConfig.maxRuntime as StringValue) // type assertion to satisfy ms package\n : (this.options.checkpointingConfig.maxRuntime as number);\n\n // 0 or negative max runtime? Skip.\n if (Number.isFinite(maxRuntimeMs) && maxRuntimeMs > 0) {\n this.checkpointingMaxRuntimeTimer = createTimeoutPromise(maxRuntimeMs);\n\n void this.checkpointingMaxRuntimeTimer.then(async () => {\n await this.middlewareManager.onMemoizationEnd();\n state.setCheckpoint({\n type: \"checkpointing-runtime-reached\",\n });\n });\n }\n }\n\n if (this.options.checkpointingConfig?.maxInterval) {\n const maxIntervalMs = Temporal.isTemporalDuration(\n this.options.checkpointingConfig.maxInterval,\n )\n ? this.options.checkpointingConfig.maxInterval.total({\n unit: \"milliseconds\",\n })\n : typeof this.options.checkpointingConfig.maxInterval === \"string\"\n ? ms(this.options.checkpointingConfig.maxInterval as StringValue) // type assertion to satisfy ms package\n : (this.options.checkpointingConfig.maxInterval as number);\n\n // 0 or negative max interval? Skip.\n if (Number.isFinite(maxIntervalMs) && maxIntervalMs > 0) {\n this.checkpointingMaxBufferIntervalTimer =\n createTimeoutPromise(maxIntervalMs);\n\n void this.checkpointingMaxBufferIntervalTimer.then(async () => {\n // Note that this will not immediately run; it will be queued like all\n // other checkpoints so that we're never running multiple checkpoints\n // at the same time and it's easier to reason about those decision\n // points.\n //\n // A change in the future may be to make this particular checkpointing\n // action immediate and have the checkpoint action itself be\n // idempotent.\n state.setCheckpoint({\n type: \"checkpointing-buffer-interval-reached\",\n });\n\n this.checkpointingMaxBufferIntervalTimer?.reset();\n });\n }\n }\n }\n}\n\n/**\n * Types of checkpoints that can be reached during execution.\n */\nexport interface Checkpoints {\n \"steps-found\": { steps: [FoundStep, ...FoundStep[]] };\n \"function-rejected\": { error: unknown };\n \"function-resolved\": { data: unknown };\n \"step-not-found\": {\n step: OutgoingOp;\n foundSteps: BasicFoundStep[];\n totalFoundSteps: number;\n };\n \"checkpointing-runtime-reached\": {};\n \"checkpointing-buffer-interval-reached\": {};\n}\n\ntype Checkpoint = {\n [K in keyof Checkpoints]: Simplify<{ type: K } & Checkpoints[K]>;\n}[keyof Checkpoints];\n\ntype CheckpointHandlers = Record<\n StepMode,\n {\n [C in Checkpoint as C[\"type\"]]: (\n checkpoint: C,\n\n /**\n * This is the number of checkpoints that have been seen before this one was\n * triggered.\n *\n * The catch-all `\"\"` checkpoint does not increment this count.\n */\n i: number,\n ) => MaybePromise<ExecutionResult | undefined>;\n } & {\n \"\": (\n checkpoint: Checkpoint,\n\n /**\n * This is the number of checkpoints that have been seen before this one was\n * triggered.\n *\n * The catch-all `\"\"` checkpoint does not increment this count.\n */\n i: number,\n ) => MaybePromise<void>;\n }\n>;\n\nexport interface ExecutionState {\n /**\n * A value that indicates that we're executing this step. Can be used to\n * ensure steps are not accidentally nested until we support this across all\n * platforms.\n */\n executingStep?: Readonly<Omit<OutgoingOp, \"id\">>;\n\n /**\n * A map of step IDs to their data, used to fill previously-completed steps\n * with state from the executor.\n */\n stepState: Record<string, MemoizedOp>;\n\n /**\n * The number of steps we expect to fulfil based on the state passed from the\n * Executor.\n */\n stepsToFulfill: number;\n\n /**\n * A map of step IDs to their functions to run. The executor can request a\n * specific step to run, so we need to store the function to run here.\n */\n steps: Map<string, FoundStep>;\n\n /**\n * A flag which represents whether or not steps are understood to be used in\n * this function. This is used to determine whether or not we should run\n * some steps (such as `step.sendEvent`) inline as they are found.\n */\n hasSteps: boolean;\n\n /**\n * The core loop - a generator used to take an action upon finding the next\n * checkpoint. Manages the flow of execution and cleaning up after itself.\n */\n loop: AsyncGenerator<Checkpoint, void, void>;\n\n /**\n * A function that resolves the `Promise` returned by `waitForNextDecision`.\n */\n setCheckpoint: (data: Checkpoint) => void;\n\n /**\n * Returns whether or not all state passed from the executor has been used to\n * fulfill found steps.\n */\n allStateUsed: () => boolean;\n\n /**\n * An ordered list of step IDs that represents the order in which their\n * execution was completed.\n */\n stepCompletionOrder: string[];\n\n /**\n * An set of step IDs that have yet to be seen in this execution. Used to\n * decide when to trigger middleware based on the current state.\n */\n remainingStepsToBeSeen: Set<string>;\n\n /**\n * If defined, this is the error that purposefully thrown when memoizing step\n * state in order to support per-step errors.\n *\n * We use this so that if the function itself rejects with the same error, we\n * know that it was entirely uncaught (or at the very least rethrown), so we\n * should send a `NonRetriableError` to stop needless execution of a function\n * that will continue to fail.\n *\n * TODO This is imperfect, as this state is currently kept around for longer\n * than it needs to be. It should disappear as soon as we've seen that the\n * error did not immediately throw. It may need to be refactored to work a\n * little more smoothly with the core loop.\n */\n recentlyRejectedStepError?: StepError;\n\n /**\n * If defined, this indicates that we're running a checkpointed function run,\n * and contains the data needed to report progress back to Inngest.\n */\n checkpointedRun?: {\n fnId: string;\n appId: string;\n token?: string;\n realtimeToken: string;\n };\n\n /**\n * A buffer of steps that are currently queued to be checkpointed.\n */\n checkpointingStepBuffer: OutgoingOp[];\n\n /**\n * Metadata collected during execution to be sent with outgoing ops.\n */\n metadata?: Map<string, Array<MetadataUpdate>>;\n}\n\nconst hashId = (id: string): string => {\n return sha1().update(id).digest(\"hex\");\n};\n\nconst hashOp = (op: OutgoingOp): OutgoingOp => {\n return {\n ...op,\n id: hashId(op.id),\n };\n};\n\n/**\n * Result of resolving a step ID collision.\n */\ninterface CollisionResolutionResult {\n /** The final ID to use (either original or with index suffix). */\n finalId: string;\n\n /** The index used, if collision was detected. */\n index?: number;\n}\n\n/** Result of applying middleware to a step. */\ninterface MiddlewareApplicationResult {\n hashedId: string;\n isFulfilled: boolean;\n setActualHandler: (handler: () => Promise<unknown>) => void;\n stepInfo: Middleware.StepInfo;\n stepState: MemoizedOp | undefined;\n wrappedHandler: () => Promise<unknown>;\n}\n\n/**\n * Resolves step ID collisions by appending an index suffix if needed.\n * Consolidates the duplicated collision detection logic.\n *\n * @param baseId - The original step ID\n * @param stepsMap - Map of existing steps (keyed by hashed ID)\n * @param expectedIndexes - Map tracking expected next index for each base ID\n * @returns The final ID to use and optional index\n */\nfunction resolveStepIdCollision({\n baseId,\n expectedIndexes,\n stepsMap,\n}: {\n baseId: string;\n expectedIndexes: Map<string, number>;\n stepsMap: Map<string, FoundStep>;\n}): CollisionResolutionResult {\n const hashedBaseId = hashId(baseId);\n\n // Check both stepsMap (steps added to state) and expectedIndexes (claimed by\n // concurrent in-progress step handlers that haven't been added to state yet).\n if (!stepsMap.has(hashedBaseId) && !expectedIndexes.has(baseId)) {\n // No collision. Claim this base ID so concurrent callers detect collision.\n expectedIndexes.set(baseId, 1);\n return { finalId: baseId };\n }\n\n // Collision detected. Find next available index\n const expectedNextIndex = expectedIndexes.get(baseId) ?? 1;\n const maxIndex = expectedNextIndex + stepsMap.size + 1;\n for (let i = expectedNextIndex; i < maxIndex; i++) {\n const indexedId = baseId + STEP_INDEXING_SUFFIX + i;\n const hashedIndexedId = hashId(indexedId);\n\n if (!stepsMap.has(hashedIndexedId)) {\n expectedIndexes.set(baseId, i + 1);\n return { finalId: indexedId, index: i };\n }\n }\n\n throw new UnreachableError(\n `Could not resolve step ID collision for \"${baseId}\" after ${stepsMap.size + 1} attempts`,\n );\n}\n\nfunction isNonEmpty<T>(arr: T[]): arr is [T, ...T[]] {\n return arr.length > 0;\n}\n\n/**\n * Exported for testing.\n */\nexport const _internals = { hashOp, hashId, resolveStepIdCollision };\n"],"mappings":"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"}
1
+ {"version":3,"file":"engine.cjs","names":["hashjs","isRecord","createExecutionEngine: InngestExecutionFactory","headers: Record<string, string>","InngestExecution","ExecutionVersion","options: InngestExecutionOptions","StepMode","Stream","MiddlewareManager","internalLoggerSymbol","trace","version","getAsyncLocalStorage","headerKeys","createDeferredPromise","retryWithBackoff","defaultMaxRetries","buildSseMetadataEvent","prependToStream","resultData: unknown","streamingResult: ExecutionResult","StepOpCode","commonCheckpointHandler: CheckpointHandlers[StepMode][\"\"]","serializeError","syncHandlers: CheckpointHandlers[StepMode.Sync]","sseResponse: SseResponse","asyncHandlers: CheckpointHandlers[StepMode.Async]","asyncCheckpointingHandlers: CheckpointHandlers[StepMode.AsyncCheckpointing]","step","UnreachableError","outgoingOp: OutgoingOp","getAsyncCtx","interval: GoInterval | undefined","runAsPromise","goIntervalTiming","innerHandler: () => Promise<unknown>","err: Error","NonRetriableError","StepError","RetryAfterError","validateEvents","undefinedToNull","createDeferredPromiseWithStack","loop: ExecutionState[\"loop\"]","experimentStepRunSymbol","createGroupTools","z","jsonErrorSchema","deserializeError","foundStepsToReport: Map<string, FoundStep>","unhandledFoundStepsToReport: Map<string, FoundStep>","expectedNextStepIndexes: Map<string, number>","remainingStepCompletionOrder: string[]","foundStepsReportPromise: Promise<void> | undefined","ErrCode","extensionPromise: Promise<void>","resolveNextTick","resolveAfterPending","stepHandler: StepHandler","getStepOptions","extraOpts: Record<string, unknown> | undefined","step: FoundStep","createStepTools","createTimeoutPromise","STEP_INDEXING_SUFFIX"],"sources":["../../../src/components/execution/engine.ts"],"sourcesContent":["import { trace } from \"@opentelemetry/api\";\nimport hashjs from \"hash.js\";\nimport ms, { type StringValue } from \"ms\";\nimport { z } from \"zod/v3\";\n\nimport {\n defaultMaxRetries,\n ExecutionVersion,\n headerKeys,\n internalEvents,\n} from \"../../helpers/consts.ts\";\n\nimport {\n deserializeError,\n ErrCode,\n serializeError,\n} from \"../../helpers/errors.js\";\nimport { undefinedToNull } from \"../../helpers/functions.js\";\nimport {\n createDeferredPromise,\n createDeferredPromiseWithStack,\n createTimeoutPromise,\n type DeferredPromiseReturn,\n type GoInterval,\n goIntervalTiming,\n resolveAfterPending,\n resolveNextTick,\n retryWithBackoff,\n runAsPromise,\n} from \"../../helpers/promises.ts\";\nimport * as Temporal from \"../../helpers/temporal.ts\";\nimport {\n isRecord,\n type MaybePromise,\n type Simplify,\n} from \"../../helpers/types.ts\";\nimport {\n type APIStepPayload,\n type Context,\n type EventPayload,\n type FailureEventArgs,\n type Handler,\n type HashedOp,\n jsonErrorSchema,\n type OutgoingOp,\n StepMode,\n StepOpCode,\n} from \"../../types.ts\";\nimport { version } from \"../../version.ts\";\nimport { internalLoggerSymbol } from \"../Inngest.ts\";\nimport { createGroupTools } from \"../InngestGroupTools.ts\";\nimport type {\n MetadataKind,\n MetadataOpcode,\n MetadataScope,\n MetadataUpdate,\n} from \"../InngestMetadata.ts\";\nimport {\n createStepTools,\n type ExperimentStepTools,\n experimentStepRunSymbol,\n type FoundStep,\n getStepOptions,\n STEP_INDEXING_SUFFIX,\n type StepHandler,\n} from \"../InngestStepTools.ts\";\nimport { MiddlewareManager } from \"../middleware/index.ts\";\nimport type { Middleware } from \"../middleware/middleware.ts\";\nimport { UnreachableError } from \"../middleware/utils.ts\";\nimport { NonRetriableError } from \"../NonRetriableError.ts\";\nimport { RetryAfterError } from \"../RetryAfterError.ts\";\nimport { StepError } from \"../StepError.ts\";\nimport { Stream } from \"../StreamTools.ts\";\nimport { validateEvents } from \"../triggers/utils.js\";\nimport { getAsyncCtx, getAsyncLocalStorage } from \"./als.ts\";\nimport {\n type BasicFoundStep,\n type ExecutionResult,\n type IInngestExecution,\n InngestExecution,\n type InngestExecutionFactory,\n type InngestExecutionOptions,\n type MemoizedOp,\n} from \"./InngestExecution.ts\";\nimport { clientProcessorMap } from \"./otel/access.ts\";\nimport {\n buildSseMetadataEvent,\n prependToStream,\n type SseResponse,\n} from \"./streaming.ts\";\n\nconst { sha1 } = hashjs;\n\n/**\n * Retry configuration for checkpoint operations.\n *\n * Checkpoint calls use exponential backoff with jitter to handle transient\n * network failures (e.g., dev server temporarily down, cloud hiccup). If\n * retries exhaust, the error propagates up - for Sync mode this results in a\n * 500 error, for AsyncCheckpointing the caller handles fallback.\n */\nconst CHECKPOINT_RETRY_OPTIONS = { maxAttempts: 5, baseDelay: 100 };\n\nfunction errorMessage(error: unknown): string {\n if (error instanceof Error) {\n return error.message;\n }\n if (isRecord(error) && typeof error.message === \"string\") {\n return error.message;\n }\n return String(error);\n}\n\n/**\n * Placeholder step ID used when completing a checkpointed run.\n */\nconst RUN_COMPLETE_STEP_ID = \"complete\";\n\nconst STEP_NOT_FOUND_MAX_FOUND_STEPS = 25;\n\nexport const createExecutionEngine: InngestExecutionFactory = (options) => {\n return new InngestExecutionEngine(options);\n};\n\nfunction extractSseResponse(response: Response, body: string): SseResponse {\n const headers: Record<string, string> = {};\n response.headers.forEach((value, key) => {\n headers[key] = value;\n });\n return { body, statusCode: response.status, headers };\n}\n\nfunction defaultSseResponse(data: unknown): SseResponse {\n return {\n body: JSON.stringify(data),\n statusCode: 200,\n headers: { \"content-type\": \"application/json\" },\n };\n}\n\nfunction jsonResponse(data: unknown, status = 200): Response {\n return new Response(JSON.stringify(data), {\n status,\n headers: { \"Content-Type\": \"application/json\" },\n });\n}\n\nclass InngestExecutionEngine\n extends InngestExecution\n implements IInngestExecution\n{\n public version = ExecutionVersion.V2;\n\n private state: ExecutionState;\n private fnArg: Context.Any;\n private checkpointHandlers: CheckpointHandlers;\n private timeoutDuration = 1000 * 10;\n private execution: Promise<ExecutionResult> | undefined;\n private userFnToRun: Handler.Any;\n private middlewareManager: MiddlewareManager;\n /**\n * Close the stream via {@link streamCloseSucceeded}, {@link streamCloseFailed},\n * or {@link streamEnd} — never call `streamTools.close*`/`end` directly, as\n * the wrappers ensure the redirect event is flushed first.\n */\n private streamTools: Stream;\n\n /**\n * Resolved when `stream.push()`/`pipe()` is first called in sync mode,\n * allowing `_start()` to return the SSE Response to the HTTP layer while\n * the core loop continues executing steps in the background.\n */\n private earlyStreamResponse:\n | DeferredPromiseReturn<ExecutionResult>\n | undefined;\n\n /**\n * Whether the `inngest.redirect_info` SSE event has already been sent.\n * Prevents duplicate redirect events.\n */\n private redirectSent = false;\n\n /**\n * Promise that resolves once the redirect event has been written (or the\n * attempt completes). Stored so that `checkpointAndSwitchToAsync` can\n * await it before closing the writer.\n */\n private redirectPromise: Promise<void> = Promise.resolve();\n\n /**\n * If we're supposed to run a particular step via `requestedRunStep`, this\n * will be a `Promise` that resolves after no steps have been found for\n * `timeoutDuration` milliseconds.\n *\n * If we're not supposed to run a particular step, this will be `undefined`.\n */\n private timeout?: ReturnType<typeof createTimeoutPromise>;\n private rootSpanId?: string;\n\n /**\n * If we're checkpointing and have been given a maximum runtime, this will be\n * a `Promise` that resolves after that duration has elapsed, allowing us to\n * ensure that we end the execution in good time, especially in serverless\n * environments.\n */\n private checkpointingMaxRuntimeTimer?: ReturnType<\n typeof createTimeoutPromise\n >;\n\n /**\n * If we're checkpointing and have been given a maximum buffer interval, this\n * will be a `Promise` that resolves after that duration has elapsed, allowing\n * us to periodically checkpoint even if the step buffer hasn't filled.\n */\n private checkpointingMaxBufferIntervalTimer?: ReturnType<\n typeof createTimeoutPromise\n >;\n\n constructor(rawOptions: InngestExecutionOptions) {\n const options: InngestExecutionOptions = {\n ...rawOptions,\n stepMode: rawOptions.stepMode ?? StepMode.Async,\n };\n\n super(options);\n\n /**\n * Check we have everything we need for checkpointing\n */\n if (this.options.stepMode === StepMode.Sync) {\n if (!this.options.createResponse) {\n throw new Error(\"createResponse is required for sync step mode\");\n }\n }\n\n this.userFnToRun = this.getUserFnToRun();\n this.streamTools = new Stream({\n onActivated: () => this.handleStreamActivated(),\n onWriteError: (err) =>\n this.devDebug(\n \"stream write error (client may have disconnected):\",\n err,\n ),\n });\n this.state = this.createExecutionState();\n this.fnArg = this.createFnArg();\n\n // Setup middleware\n const mwInstances =\n this.options.middlewareInstances ??\n (this.options.client.middleware || []).map((Cls) => {\n return new Cls({ client: this.options.client });\n });\n this.middlewareManager = new MiddlewareManager(\n this.fnArg,\n () => this.state.stepState,\n mwInstances,\n this.options.fn,\n this.options.client[internalLoggerSymbol],\n );\n\n this.checkpointHandlers = this.createCheckpointHandlers();\n this.initializeTimer(this.state);\n this.initializeCheckpointRuntimeTimer(this.state);\n\n this.devDebug(\n \"created new V1 execution for run;\",\n this.options.requestedRunStep\n ? `wanting to run step \"${this.options.requestedRunStep}\"`\n : \"discovering steps\",\n );\n\n this.devDebug(\"existing state keys:\", Object.keys(this.state.stepState));\n }\n\n /**\n * Idempotently start the execution of the user's function.\n */\n public start() {\n if (!this.execution) {\n this.devDebug(\"starting V1 execution\");\n\n const tracer = trace.getTracer(\"inngest\", version);\n\n this.execution = getAsyncLocalStorage().then((als) => {\n return als.run(\n {\n app: this.options.client,\n execution: {\n ctx: this.fnArg,\n instance: this,\n stream: this.streamTools,\n },\n },\n async () => {\n return tracer.startActiveSpan(\"inngest.execution\", (span) => {\n this.rootSpanId = span.spanContext().spanId;\n clientProcessorMap.get(this.options.client)?.declareStartingSpan({\n span,\n runId: this.options.runId,\n traceparent: this.options.headers[headerKeys.TraceParent],\n tracestate: this.options.headers[headerKeys.TraceState],\n });\n\n return this._start()\n .then((result) => {\n this.devDebug(\"result:\", result);\n return result;\n })\n .finally(() => {\n span.end();\n });\n });\n },\n );\n });\n }\n\n return this.execution;\n }\n\n public addMetadata(\n stepId: string,\n kind: MetadataKind,\n scope: MetadataScope,\n op: MetadataOpcode,\n values: Record<string, unknown>,\n ) {\n if (!this.state.metadata) {\n this.state.metadata = new Map();\n }\n\n const updates = this.state.metadata.get(stepId) ?? [];\n updates.push({ kind, scope, op, values });\n this.state.metadata.set(stepId, updates);\n\n return true;\n }\n\n /**\n * Starts execution of the user's function and the core loop.\n */\n private async _start(): Promise<ExecutionResult> {\n // Set up a deferred promise that handleStreamActivated resolves to return\n // the SSE Response early while the core loop keeps running.\n if (this.options.stepMode === StepMode.Sync && this.options.acceptsSse) {\n this.earlyStreamResponse = createDeferredPromise<ExecutionResult>();\n }\n\n const coreLoop = this.runCoreLoop();\n\n if (this.earlyStreamResponse) {\n // Suppress: if earlyStreamResponse wins the race and coreLoop later\n // rejects, the rejection must not go unhandled.\n coreLoop.catch((err) => {\n this.options.client[internalLoggerSymbol].error(\n { err },\n \"Core loop rejected after early stream response was sent\",\n );\n });\n\n return Promise.race([this.earlyStreamResponse.promise, coreLoop]);\n }\n\n return coreLoop;\n }\n\n /**\n * The core checkpoint loop: processes checkpoints until a handler returns\n * a result.\n */\n private async runCoreLoop(): Promise<ExecutionResult> {\n try {\n const allCheckpointHandler = this.getCheckpointHandler(\"\");\n await this.startExecution();\n\n let i = 0;\n\n for await (const checkpoint of this.state.loop) {\n await allCheckpointHandler(checkpoint, i);\n\n const handler = this.getCheckpointHandler(checkpoint.type);\n const result = await handler(checkpoint, i++);\n\n if (result) {\n return result;\n }\n }\n } catch (error) {\n // If earlyStreamResponse was set up, close the stream with an error event\n // and resolve (not reject) with a well-formed result so the caller gets a\n // structured response instead of a raw Error.\n if (this.earlyStreamResponse) {\n await this.streamCloseFailed(\"Internal execution error\");\n const result = this.transformOutput({ error });\n this.earlyStreamResponse.resolve(result);\n return result;\n }\n\n return this.transformOutput({ error });\n } finally {\n void this.state.loop.return();\n }\n\n /**\n * If we're here, the generator somehow finished without returning a value.\n * This should never happen.\n */\n throw new Error(\"Core loop finished without returning a value\");\n }\n\n private async checkpoint(steps: OutgoingOp[]): Promise<void> {\n if (this.options.stepMode === StepMode.Sync) {\n if (!this.state.checkpointedRun) {\n // We have to start the run\n const res = await retryWithBackoff(\n () =>\n this.options.client[\"inngestApi\"].checkpointNewRun({\n runId: this.fnArg.runId,\n event: this.fnArg.event as APIStepPayload,\n steps,\n executionVersion: this.version,\n retries: this.fnArg.maxAttempts ?? defaultMaxRetries,\n }),\n CHECKPOINT_RETRY_OPTIONS,\n );\n\n this.state.checkpointedRun = {\n appId: res.data.app_id,\n fnId: res.data.fn_id,\n token: res.data.token,\n realtimeToken: res.data.realtime_token,\n };\n\n // Try sending redirect (no-op if stream isn't activated yet).\n this.sendRedirectIfReady();\n } else {\n await retryWithBackoff(\n () =>\n this.options.client[\"inngestApi\"].checkpointSteps({\n appId: this.state.checkpointedRun!.appId,\n fnId: this.state.checkpointedRun!.fnId,\n runId: this.fnArg.runId,\n steps,\n }),\n CHECKPOINT_RETRY_OPTIONS,\n );\n }\n } else if (this.options.stepMode === StepMode.AsyncCheckpointing) {\n const { internalFnId, queueItemId } = this.options;\n if (!queueItemId) {\n throw new Error(\n \"Missing queueItemId for async checkpointing. This is a bug in the Inngest SDK.\",\n );\n }\n\n if (!internalFnId) {\n throw new Error(\n \"Missing internalFnId for async checkpointing. This is a bug in the Inngest SDK.\",\n );\n }\n\n await retryWithBackoff(\n () =>\n this.options.client[\"inngestApi\"].checkpointStepsAsync({\n runId: this.fnArg.runId,\n fnId: internalFnId,\n queueItemId,\n steps,\n }),\n CHECKPOINT_RETRY_OPTIONS,\n );\n } else {\n throw new Error(\n \"Checkpointing is only supported in Sync and AsyncCheckpointing step modes. This is a bug in the Inngest SDK.\",\n );\n }\n }\n\n private async checkpointAndSwitchToAsync(\n steps: OutgoingOp[],\n stepError?: unknown,\n ): Promise<ExecutionResult> {\n await this.checkpoint(steps);\n\n if (!this.state.checkpointedRun?.token) {\n throw new Error(\"Failed to checkpoint and switch to async mode\");\n }\n\n const token = this.state.checkpointedRun.token;\n\n if (this.streamTools.activated) {\n if (stepError && !this.retriability(stepError)) {\n // Permanent failure — close with a failed event so the client\n // sees the error.\n await this.streamCloseFailed(errorMessage(stepError));\n } else {\n // End stream without a result event — client uses redirect_info\n // to reconnect.\n await this.streamEnd();\n }\n } else if (this.options.acceptsSse) {\n // Stream was never activated (no stream.push/pipe), but the client\n // accepts SSE. Close and return the SSE response so the client gets\n // metadata + redirect_info events and can follow the redirect.\n await this.streamEnd();\n return {\n type: \"function-resolved\",\n ctx: this.fnArg,\n ops: this.ops,\n data: this.buildSyncSseResponse(),\n };\n }\n\n return {\n type: \"change-mode\",\n ctx: this.fnArg,\n ops: this.ops,\n to: StepMode.Async,\n token,\n };\n }\n\n /**\n * Prepend the `inngest.metadata` SSE event to the stream's readable side.\n * The returned stream can be used as a fetch body or Response body.\n *\n * NOTE: `this.streamTools.readable` can only be consumed once, so only one\n * of `buildSyncSseResponse` or `postCheckpointStream` may be called per\n * execution.\n */\n private buildMetadataPrefixedStream(): ReadableStream<Uint8Array> {\n const metadataEvent = buildSseMetadataEvent(this.fnArg.runId);\n return prependToStream(\n new TextEncoder().encode(metadataEvent),\n this.streamTools.readable,\n );\n }\n\n /**\n * Build the initial SSE `Response` that marks the start of streaming to the\n * client. Only used in sync mode. In async mode, the stream is POSTed to the\n * Inngest Server via {@link postCheckpointStream} instead.\n *\n * The response body is the stream's readable side, prefixed with the\n * `inngest.metadata` SSE event.\n */\n private buildSyncSseResponse(): Response {\n return new Response(this.buildMetadataPrefixedStream(), {\n status: 200,\n headers: {\n \"Content-Type\": \"text/event-stream\",\n \"Cache-Control\": \"no-cache\",\n },\n });\n }\n\n /**\n * Wraps a plain return value as an SSE Response.\n *\n * Used when the client sent `Accept: text/event-stream` but\n * `stream.push()`/`pipe()` was NOT called during execution. The\n * checkpointable data is the function's return value. The SSE events are just\n * a delivery mechanism.\n */\n private async wrapResultAsSse(\n checkpoint: Simplify<\n { type: \"function-resolved\" } & Checkpoints[\"function-resolved\"]\n >,\n sseResponse: SseResponse,\n ): Promise<ExecutionResult> {\n const resultData: unknown = checkpoint.data;\n\n // Close the stream with a terminal succeeded event\n await this.streamCloseSucceeded(sseResponse);\n\n const clientResponse = this.buildSyncSseResponse();\n\n // Run transformOutput to fire middleware hooks\n const result = this.transformOutput({ data: resultData });\n\n const streamingResult: ExecutionResult = {\n ...result,\n data: clientResponse,\n } as ExecutionResult;\n\n // Background: checkpoint the return value (not the stream bytes).\n void this.checkpointReturnValue(resultData);\n\n return streamingResult;\n }\n\n /**\n * Called when `stream.push()`/`pipe()` is first invoked during sync\n * execution. Resolves {@link earlyStreamResponse} so that `_start()` can\n * return the SSE Response to the HTTP layer immediately, while the core\n * checkpoint loop keeps running steps in the background.\n */\n private handleStreamActivated(): undefined {\n if (this.earlyStreamResponse) {\n // \"function-resolved\" tells the HTTP layer to send the Response,\n // even though the function is still running.\n this.earlyStreamResponse.resolve({\n type: \"function-resolved\",\n ctx: this.fnArg,\n ops: this.ops,\n data: this.buildSyncSseResponse(),\n });\n\n // Checkpoint may have already provided the realtime token — try redirect now.\n this.sendRedirectIfReady();\n\n return undefined;\n }\n\n // Async/AsyncCheckpointing mode: start the streaming POST immediately.\n // In sync mode without SSE, the stream has no consumer — skip the POST.\n if (this.options.stepMode !== StepMode.Sync) {\n this.postCheckpointStream();\n }\n this.sendRedirectIfReady();\n return undefined;\n }\n\n /**\n * Sends the `inngest.redirect_info` SSE event when both conditions are met:\n * 1. The client accepts SSE (so there's a stream to write the event to)\n * 2. We have a realtime token (first checkpoint has completed)\n *\n * Called after the first checkpoint AND on stream activation, whichever\n * comes second, so the redirect is sent as early as possible.\n */\n private sendRedirectIfReady(): void {\n if (this.redirectSent) {\n return;\n }\n\n if (!this.options.acceptsSse) {\n return;\n }\n\n if (!this.state.checkpointedRun) {\n // This is part of the happy path. We may not have checkpointed the run\n // yet, which happens after the first step ends\n return;\n }\n\n this.redirectSent = true;\n\n const { realtimeToken } = this.state.checkpointedRun;\n\n this.redirectPromise = (async () => {\n try {\n const redirect =\n await this.options.client[\"inngestApi\"].getRealtimeStreamRedirect(\n realtimeToken,\n );\n\n this.streamTools.sendRedirectInfo({\n runId: this.fnArg.runId,\n url: redirect.url,\n });\n } catch (err) {\n this.options.client[internalLoggerSymbol].warn(\n { err },\n \"Failed to fetch realtime stream redirect URL\",\n );\n }\n })();\n }\n\n /**\n * Await the pending redirect-info fetch, then close the stream with a\n * succeeded result. Awaiting first guarantees the redirect event is\n * enqueued on the write chain before the close event.\n */\n private async streamCloseSucceeded(response: SseResponse): Promise<void> {\n await this.redirectPromise;\n this.streamTools.closeSucceeded(response);\n }\n\n /**\n * Await the pending redirect-info fetch, then close the stream with a\n * failed result.\n */\n private async streamCloseFailed(error: string): Promise<void> {\n await this.redirectPromise;\n this.streamTools.closeFailed(error);\n }\n\n /**\n * Await the pending redirect-info fetch, then close the stream without\n * a result event.\n */\n private async streamEnd(): Promise<void> {\n await this.redirectPromise;\n this.streamTools.end();\n }\n\n /**\n * POST stream data to the checkpoint stream ingest endpoint.\n *\n * Called eagerly from handleStreamActivated so chunks flow in\n * real-time, or after completion if stream.push() was never called.\n */\n private postCheckpointStream(): void {\n try {\n // Fire and forget — completes when the stream closes.\n void this.options.client[\"inngestApi\"]\n .checkpointStream({\n runId: this.fnArg.runId,\n body: this.buildMetadataPrefixedStream(),\n })\n .catch((err: unknown) => {\n this.devDebug(\"checkpoint stream POST error:\", err);\n });\n } catch (err) {\n this.devDebug(\"checkpoint stream POST error:\", err);\n }\n }\n\n /**\n * Checkpoints the return value of a function that was delivered via SSE.\n * Runs in the background so it doesn't block the client stream.\n */\n private async checkpointReturnValue(data: unknown): Promise<void> {\n try {\n if (this.options.createResponse) {\n await this.checkpoint([\n {\n op: StepOpCode.RunComplete,\n id: hashId(RUN_COMPLETE_STEP_ID),\n data: await this.options.createResponse(jsonResponse(data)),\n },\n ]);\n }\n } catch (err) {\n this.devDebug(\n \"error during background checkpoint of SSE result, client stream unaffected:\",\n err,\n );\n }\n }\n\n /**\n * Creates a handler for every checkpoint type, defining what to do when we\n * reach that checkpoint in the core loop.\n */\n private createCheckpointHandlers(): CheckpointHandlers {\n const commonCheckpointHandler: CheckpointHandlers[StepMode][\"\"] = (\n checkpoint,\n ) => {\n this.devDebug(`${this.options.stepMode} checkpoint:`, checkpoint);\n };\n\n const stepRanHandler = async (\n stepResult: OutgoingOp,\n ): Promise<ExecutionResult> => {\n const transformResult = await this.transformOutput(stepResult);\n\n /**\n * Transforming output will always return either function rejection or\n * resolution. In most cases, this can be immediately returned, but in\n * this particular case we want to handle it differently.\n */\n if (transformResult.type === \"function-resolved\") {\n return {\n type: \"step-ran\",\n ctx: transformResult.ctx,\n ops: transformResult.ops,\n step: {\n ...stepResult,\n data: transformResult.data,\n },\n };\n } else if (transformResult.type === \"function-rejected\") {\n const stepForResponse = {\n ...stepResult,\n error: transformResult.error,\n };\n\n if (stepResult.op === StepOpCode.StepFailed) {\n const ser = serializeError(transformResult.error);\n stepForResponse.data = {\n __serialized: true,\n name: ser.name,\n message: ser.message,\n stack: \"\",\n };\n }\n\n return {\n type: \"step-ran\",\n ctx: transformResult.ctx,\n ops: transformResult.ops,\n retriable: transformResult.retriable,\n step: stepForResponse,\n };\n }\n\n return transformResult;\n };\n\n const maybeReturnNewSteps = async (): Promise<\n ExecutionResult | undefined\n > => {\n const newSteps = await this.filterNewSteps(\n Array.from(this.state.steps.values()),\n );\n if (newSteps) {\n return {\n type: \"steps-found\",\n ctx: this.fnArg,\n ops: this.ops,\n steps: newSteps,\n };\n }\n\n return;\n };\n\n const attemptCheckpointAndResume = async (\n stepResult?: OutgoingOp,\n resume = true,\n force = false,\n ): Promise<ExecutionResult | undefined> => {\n // If we're here, we successfully ran a step, so we may now need\n // to checkpoint it depending on the step buffer configured.\n if (stepResult) {\n const stepToResume = this.resumeStepWithResult(stepResult, resume);\n\n // Clear `executingStep` immediately after resuming, before any await.\n // `resumeStepWithResult` resolves the step's promise, queuing a\n // microtask for the function to continue. Any subsequent await (e.g.\n // the `transformOutput` hook) yields and lets that microtask run, so\n // `executingStep` must already be cleared to avoid a false positive\n // NESTING_STEPS warning in the next step's handler.\n delete this.state.executingStep;\n\n // Buffer a copy with transformed data for checkpointing\n this.state.checkpointingStepBuffer.push({\n ...stepToResume,\n data: stepResult.data,\n });\n }\n\n if (\n force ||\n !this.options.checkpointingConfig?.bufferedSteps ||\n this.state.checkpointingStepBuffer.length >=\n this.options.checkpointingConfig.bufferedSteps\n ) {\n this.devDebug(\"checkpointing and resuming execution after step run\");\n\n try {\n this.devDebug(\n `checkpointing all buffered steps:`,\n this.state.checkpointingStepBuffer\n .map((op) => op.displayName || op.id)\n .join(\", \"),\n );\n\n return void (await this.checkpoint(\n this.state.checkpointingStepBuffer,\n ));\n } catch (err) {\n // If checkpointing fails for any reason, fall back to returning\n // ALL buffered steps to the executor via the normal async flow.\n // The executor persists completed steps and rediscovers any\n // parallel/errored steps on the next invocation.\n this.devDebug(\n \"error checkpointing after step run, so falling back to async\",\n err,\n );\n\n const buffered = this.state.checkpointingStepBuffer;\n\n if (buffered.length) {\n return {\n type: \"steps-found\" as const,\n ctx: this.fnArg,\n ops: this.ops,\n steps: buffered as [OutgoingOp, ...OutgoingOp[]],\n };\n }\n\n return;\n } finally {\n // Clear the checkpointing buffer\n this.state.checkpointingStepBuffer = [];\n }\n } else {\n this.devDebug(\n `not checkpointing yet, continuing execution as we haven't reached buffered step limit of ${this.options.checkpointingConfig?.bufferedSteps}`,\n );\n }\n\n return;\n };\n\n const syncHandlers: CheckpointHandlers[StepMode.Sync] = {\n /**\n * Run for all checkpoints. Best used for logging or common actions.\n * Use other handlers to return values and interrupt the core loop.\n */\n \"\": commonCheckpointHandler,\n\n \"function-resolved\": async (checkpoint) => {\n const usingSseStream = !!this.earlyStreamResponse;\n\n if (this.streamTools.activated) {\n let resultData: unknown = checkpoint.data;\n let sseResponse: SseResponse;\n if (checkpoint.data instanceof Response) {\n // Clone when not SSE so the Response body stays intact for passthrough.\n const body = await (usingSseStream\n ? checkpoint.data.text()\n : checkpoint.data.clone().text());\n sseResponse = extractSseResponse(checkpoint.data, body);\n resultData = body;\n } else {\n sseResponse = defaultSseResponse(resultData);\n }\n\n // Always close the stream — either the SSE client or the\n // server-side checkpoint POST needs the terminal result event.\n await this.streamCloseSucceeded(sseResponse);\n\n if (usingSseStream) {\n // SSE path: response already sent; checkpoint in background.\n void this.checkpointReturnValue(resultData);\n return this.transformOutput({ data: resultData });\n }\n\n // Non-SSE: fall through to normal response handling.\n }\n\n // If the client accepts SSE (but stream.push() was NOT called), build\n // the SSE Response now. The SSE envelope is always needed when the\n // client requests it because it carries inngest.metadata and\n // inngest.redirect_info. Without these the client can't reconnect if a\n // future execution goes async.\n if (this.options.acceptsSse) {\n let sseResponse: SseResponse;\n if (checkpoint.data instanceof Response) {\n const body = await checkpoint.data.text();\n sseResponse = extractSseResponse(checkpoint.data, body);\n checkpoint = { ...checkpoint, data: body };\n } else {\n sseResponse = defaultSseResponse(checkpoint.data);\n }\n return this.wrapResultAsSse(checkpoint, sseResponse);\n }\n\n // Response pass-through: deliver as-is. Checkpoint null because the\n // Response body (ReadableStream) can only be consumed once.\n if (checkpoint.data instanceof Response) {\n void this.checkpointReturnValue(null);\n return this.transformOutput({ data: checkpoint.data });\n }\n\n // Non-streaming path\n await this.checkpoint([\n {\n op: StepOpCode.RunComplete,\n id: hashId(RUN_COMPLETE_STEP_ID),\n data: await this.options.createResponse!(\n jsonResponse(checkpoint.data),\n ),\n },\n ]);\n\n // Apply middleware transformation before returning\n return this.transformOutput({ data: checkpoint.data });\n },\n\n \"function-rejected\": async (checkpoint) => {\n const usingSseStream = !!this.earlyStreamResponse;\n const isFinal = !this.retriability(checkpoint.error);\n\n if (this.streamTools.activated && usingSseStream) {\n // SSE path: checkpoint the error, then close the stream.\n // The checkpoint triggers sendRedirectIfReady which starts\n // the (near-instant) redirect URL resolution. Chaining the\n // close as a continuation ensures the redirect event is\n // written first, without blocking the handler's return on\n // the checkpoint's retry budget.\n void (async () => {\n try {\n await this.checkpoint([\n {\n id: hashId(RUN_COMPLETE_STEP_ID),\n op: isFinal ? StepOpCode.StepFailed : StepOpCode.StepError,\n error: checkpoint.error,\n },\n ]);\n } catch (err) {\n this.options.client[internalLoggerSymbol].warn(\n { err },\n \"Failed to checkpoint function error\",\n );\n }\n\n if (isFinal) {\n await this.streamCloseFailed(errorMessage(checkpoint.error));\n } else {\n await this.streamEnd();\n }\n })();\n\n return this.transformOutput({ error: checkpoint.error });\n }\n\n // If the function throws during sync execution, we want to switch to\n // async mode so that we can retry. The exception is that we're already\n // at max attempts, in which case we do actually want to reject.\n if (isFinal) {\n return this.transformOutput({ error: checkpoint.error });\n }\n\n // Retryable — checkpoint the error and switch to async mode.\n // checkpointAndSwitchToAsync handles closing the stream.\n return this.checkpointAndSwitchToAsync([\n {\n id: hashId(RUN_COMPLETE_STEP_ID),\n op: StepOpCode.StepError,\n error: checkpoint.error,\n },\n ]);\n },\n\n \"step-not-found\": () => {\n return {\n type: \"function-rejected\",\n ctx: this.fnArg,\n error: new Error(\n \"Step not found when checkpointing; this should never happen\",\n ),\n ops: this.ops,\n retriable: false,\n };\n },\n\n \"steps-found\": async ({ steps }) => {\n // If we're entering parallelism or async mode, checkpoint and switch\n // to async.\n if (steps.length !== 1 || steps[0].mode !== StepMode.Sync) {\n return this.checkpointAndSwitchToAsync(\n steps.map((step) => ({ ...step, id: step.hashedId })),\n );\n }\n\n // Otherwise we're good to start executing things right now.\n const result = await this.executeStep(steps[0]);\n\n const transformed = await stepRanHandler(result);\n if (transformed.type !== \"step-ran\") {\n throw new Error(\n \"Unexpected checkpoint handler result type after running step in sync mode\",\n );\n }\n\n if (result.error) {\n return this.checkpointAndSwitchToAsync(\n [transformed.step],\n result.error,\n );\n }\n\n // Resume the step with original data for user code\n //\n // Note: We should likely also pass this through `transformOutput` and\n // then `transformInput` to mimic the entire middleware cycle, to ensure\n // that any transformations that purposefully skew the resulting type\n // are supported.\n const stepToResume = this.resumeStepWithResult(result);\n\n // Clear executingStep now that the step result has been processed.\n // Without this, the next step discovery would see stale state and\n // emit a false positive NESTING_STEPS warning.\n delete this.state.executingStep;\n\n // Checkpoint with transformed data from middleware\n const stepForCheckpoint = {\n ...stepToResume,\n data: transformed.step.data,\n };\n\n return void (await this.checkpoint([stepForCheckpoint]));\n },\n\n \"checkpointing-runtime-reached\": () => {\n return this.checkpointAndSwitchToAsync([\n {\n op: StepOpCode.DiscoveryRequest,\n\n // Append with time because we don't want Executor-side\n // idempotency to dedupe. There may have been a previous\n // discovery request.\n id: _internals.hashId(`discovery-request-${Date.now()}`),\n },\n ]);\n },\n\n \"checkpointing-buffer-interval-reached\": () => {\n return attemptCheckpointAndResume(undefined, false, true);\n },\n };\n\n const asyncHandlers: CheckpointHandlers[StepMode.Async] = {\n /**\n * Run for all checkpoints. Best used for logging or common actions.\n * Use other handlers to return values and interrupt the core loop.\n */\n \"\": commonCheckpointHandler,\n\n /**\n * The user's function has completed and returned a value.\n */\n \"function-resolved\": async ({ data }) => {\n let resultData: unknown = data;\n let sseResponse: SseResponse;\n if (data instanceof Response) {\n const body = await data.text();\n sseResponse = extractSseResponse(data, body);\n resultData = body;\n } else {\n sseResponse = defaultSseResponse(resultData);\n }\n\n // Check for unreported new steps (e.g. from `Promise.race` where\n // the winning branch completed before losing branches reported)\n // before closing the stream — once closed, no more events can be sent.\n const newStepsResult = await maybeReturnNewSteps();\n if (newStepsResult) {\n return newStepsResult;\n }\n\n // Close the stream with a terminal succeeded event.\n await this.streamCloseSucceeded(sseResponse);\n\n // If stream was never activated, start the POST now so the\n // client waiting at the GET endpoint gets the result event.\n if (!this.streamTools.activated) {\n this.postCheckpointStream();\n }\n\n // We need to do this even here for async, as we could be returning\n // data from an API endpoint, even if we were triggered async.\n if (this.options.createResponse) {\n data = await this.options.createResponse(jsonResponse(resultData));\n }\n\n return this.transformOutput({ data });\n },\n\n /**\n * The user's function has thrown an error.\n */\n \"function-rejected\": async (checkpoint) => {\n const isFinal = !this.retriability(checkpoint.error);\n\n if (isFinal) {\n await this.streamCloseFailed(errorMessage(checkpoint.error));\n } else {\n // Retryable error — suppress the result event; the run will retry.\n await this.streamEnd();\n }\n\n if (!this.streamTools.activated) {\n this.postCheckpointStream();\n }\n\n return this.transformOutput({ error: checkpoint.error });\n },\n\n /**\n * We've found one or more steps. Here we may want to run a step or report\n * them back to Inngest.\n */\n \"steps-found\": async ({ steps }) => {\n const stepResult = await this.tryExecuteStep(steps);\n if (stepResult) {\n return stepRanHandler(stepResult);\n }\n\n return maybeReturnNewSteps();\n },\n\n /**\n * While trying to find a step that Inngest has told us to run, we've\n * timed out or have otherwise decided that it doesn't exist.\n */\n \"step-not-found\": ({ step }) => {\n const { foundSteps, totalFoundSteps } = this.getStepNotFoundDetails();\n return {\n type: \"step-not-found\",\n ctx: this.fnArg,\n ops: this.ops,\n step,\n foundSteps,\n totalFoundSteps,\n };\n },\n\n \"checkpointing-runtime-reached\": () => {\n throw new Error(\n \"Checkpointing maximum runtime reached, but this is not in a checkpointing step mode. This is a bug in the Inngest SDK.\",\n );\n },\n\n \"checkpointing-buffer-interval-reached\": () => {\n throw new Error(\n \"Checkpointing maximum buffer interval reached, but this is not in a checkpointing step mode. This is a bug in the Inngest SDK.\",\n );\n },\n };\n\n const asyncCheckpointingHandlers: CheckpointHandlers[StepMode.AsyncCheckpointing] =\n {\n \"\": commonCheckpointHandler,\n \"function-resolved\": async (checkpoint, i) => {\n const output = await asyncHandlers[\"function-resolved\"](\n checkpoint,\n i,\n );\n if (output?.type === \"function-resolved\") {\n const steps = this.state.checkpointingStepBuffer.concat({\n op: StepOpCode.RunComplete,\n id: hashId(RUN_COMPLETE_STEP_ID),\n data: output.data,\n });\n\n if (isNonEmpty(steps)) {\n return {\n type: \"steps-found\",\n ctx: output.ctx,\n ops: output.ops,\n steps,\n };\n }\n }\n\n return;\n },\n \"function-rejected\": async (checkpoint) => {\n // If we have buffered steps, attempt checkpointing them first\n if (this.state.checkpointingStepBuffer.length) {\n const fallback = await attemptCheckpointAndResume(\n undefined,\n false,\n true,\n );\n if (fallback) {\n return fallback;\n }\n }\n\n return await this.transformOutput({ error: checkpoint.error });\n },\n \"step-not-found\": asyncHandlers[\"step-not-found\"],\n \"steps-found\": async ({ steps }) => {\n // Note that if we have a requested run step, we'll never be\n // checkpointing, as that's an async parallel execution mode.\n\n // Break found steps in to { stepsToResume, newSteps }\n const { stepsToResume, newSteps } = steps.reduce(\n (acc, step) => {\n if (!step.hasStepState) {\n acc.newSteps.push(step);\n } else if (!step.fulfilled) {\n acc.stepsToResume.push(step);\n }\n\n return acc;\n },\n { stepsToResume: [], newSteps: [] } as {\n stepsToResume: FoundStep[];\n newSteps: FoundStep[];\n },\n );\n\n this.devDebug(\"split found steps in to:\", {\n stepsToResume: stepsToResume.length,\n newSteps: newSteps.length,\n });\n\n // Got new steps? Exit early.\n if (!this.options.requestedRunStep && newSteps.length) {\n // If the checkpointing runtime has been exceeded, don't execute new\n // steps in-process. Flush any buffered steps and return the new\n // steps to the executor so it can schedule them.\n if (this.state.checkpointingRuntimeExceeded) {\n if (this.state.checkpointingStepBuffer.length) {\n const fallback = await attemptCheckpointAndResume(\n undefined,\n false,\n true,\n );\n if (fallback) {\n return fallback;\n }\n }\n\n return maybeReturnNewSteps();\n }\n\n const stepResult = await this.tryExecuteStep(newSteps);\n if (stepResult) {\n this.devDebug(`executed step \"${stepResult.id}\" successfully`);\n\n // We executed a step!\n //\n // We know that because we're in this mode, we're always free to\n // checkpoint and continue if we ran a step and it was successful.\n if (stepResult.error) {\n // Flush buffered steps before falling back to async,\n // so previously-successful steps aren't lost.\n if (this.state.checkpointingStepBuffer.length) {\n const fallback = await attemptCheckpointAndResume(\n undefined,\n false,\n true,\n );\n if (fallback) {\n return fallback;\n }\n }\n\n return stepRanHandler(stepResult);\n }\n\n // If we're here, we successfully ran a step, so we may now need\n // to checkpoint it depending on the step buffer configured.\n return await attemptCheckpointAndResume(stepResult);\n }\n\n // Flush any buffered checkpoint steps before returning\n // new steps to the executor. Without this, steps executed\n // in-process during AsyncCheckpointing but not yet\n // checkpointed would be lost. When the executor later calls\n // back with requestedRunStep, those steps would be missing\n // from stepState, causing \"step not found\" errors.\n if (this.state.checkpointingStepBuffer.length) {\n const fallback = await attemptCheckpointAndResume(\n undefined,\n false,\n true,\n );\n if (fallback) {\n return fallback;\n }\n }\n\n return maybeReturnNewSteps();\n }\n\n // If we have stepsToResume, resume as many as possible and resume execution\n if (stepsToResume.length) {\n this.devDebug(`resuming ${stepsToResume.length} steps`);\n\n for (const st of stepsToResume) {\n this.resumeStepWithResult({\n ...st,\n id: st.hashedId,\n });\n }\n }\n\n return;\n },\n \"checkpointing-runtime-reached\": async () => {\n // Don't return a DiscoveryRequest immediately. Instead, set a flag so\n // that the next \"steps-found\" checkpoint returns the step to the\n // executor rather than executing it in-process. This lets user code\n // between steps run to completion and avoids re-entering the function\n // from scratch for stepless functions. In other words, it avoids\n // duplicate execution requests.\n this.state.checkpointingRuntimeExceeded = true;\n return undefined;\n },\n\n \"checkpointing-buffer-interval-reached\": () => {\n return attemptCheckpointAndResume(undefined, false, true);\n },\n };\n\n return {\n [StepMode.Async]: asyncHandlers,\n [StepMode.Sync]: syncHandlers,\n [StepMode.AsyncCheckpointing]: asyncCheckpointingHandlers,\n };\n }\n\n private getCheckpointHandler(type: keyof CheckpointHandlers[StepMode]) {\n return this.checkpointHandlers[this.options.stepMode][type] as (\n checkpoint: Checkpoint,\n iteration: number,\n ) => MaybePromise<ExecutionResult | undefined>;\n }\n\n private async tryExecuteStep(\n steps: FoundStep[],\n ): Promise<OutgoingOp | undefined> {\n const hashedStepIdToRun =\n this.options.requestedRunStep || this.getEarlyExecRunStep(steps);\n if (!hashedStepIdToRun) {\n return;\n }\n\n const step = steps.find(\n (step) => step.hashedId === hashedStepIdToRun && step.fn,\n );\n\n if (step) {\n return await this.executeStep(step);\n }\n\n /**\n * Ensure we reset the timeout if we have a requested run step but couldn't\n * find it, but also that we don't reset if we found and executed it.\n */\n return void this.timeout?.reset();\n }\n\n /**\n * Given a list of outgoing ops, decide if we can execute an op early and\n * return the ID of the step to execute if we can.\n */\n private getEarlyExecRunStep(steps: FoundStep[]): string | undefined {\n /**\n * We may have been disabled due to parallelism, in which case we can't\n * immediately execute unless explicitly requested.\n */\n if (this.options.disableImmediateExecution) return;\n\n const unfulfilledSteps = steps.filter((step) => !step.fulfilled);\n if (unfulfilledSteps.length !== 1) return;\n\n const op = unfulfilledSteps[0];\n\n if (\n op &&\n op.op === StepOpCode.StepPlanned\n // TODO We must individually check properties here that we do not want to\n // execute on, such as retry counts. Nothing exists here that falls in to\n // this case, but should be accounted for when we add them.\n // && typeof op.opts === \"undefined\"\n ) {\n return op.hashedId;\n }\n\n return;\n }\n\n private async filterNewSteps(\n foundSteps: FoundStep[],\n ): Promise<[OutgoingOp, ...OutgoingOp[]] | undefined> {\n if (this.options.requestedRunStep) {\n return;\n }\n\n const newSteps = foundSteps.reduce((acc, step) => {\n if (!step.hasStepState) {\n acc.push(step);\n }\n\n return acc;\n }, [] as FoundStep[]);\n\n if (!newSteps.length) {\n return;\n }\n\n await this.middlewareManager.onMemoizationEnd();\n\n const stepList = newSteps.map<OutgoingOp>((step) => {\n return {\n displayName: step.displayName,\n op: step.op,\n id: step.hashedId,\n name: step.name,\n opts: step.opts,\n userland: step.userland,\n };\n });\n\n if (!isNonEmpty(stepList)) {\n throw new UnreachableError(\"stepList is empty\");\n }\n\n return stepList;\n }\n\n private async executeStep(foundStep: FoundStep): Promise<OutgoingOp> {\n const { id, name, opts, fn, displayName, userland, hashedId } = foundStep;\n const { stepInfo, wrappedHandler, setActualHandler } = foundStep.middleware;\n\n this.devDebug(`preparing to execute step \"${id}\"`);\n\n this.timeout?.clear();\n\n const outgoingOp: OutgoingOp = {\n id: hashedId,\n op: StepOpCode.StepRun,\n name,\n opts,\n displayName,\n userland,\n };\n this.state.executingStep = outgoingOp;\n\n const store = await getAsyncCtx();\n\n if (store?.execution) {\n store.execution.executingStep = {\n id,\n name: displayName,\n hashedId,\n };\n }\n\n this.devDebug(`executing step \"${id}\"`);\n\n if (this.rootSpanId && this.options.checkpointingConfig) {\n clientProcessorMap\n .get(this.options.client)\n ?.declareStepExecution(\n this.rootSpanId,\n userland.id ?? \"\",\n userland.index ?? 0,\n hashedId,\n this.options.data?.attempt ?? 0,\n );\n }\n\n let interval: GoInterval | undefined;\n\n // `fn` already has middleware-transformed args baked in via `fnArgs` (i.e.\n // the `transformStepInput` middleware hook already ran).\n const actualHandler = () => runAsPromise(fn);\n\n await this.middlewareManager.onMemoizationEnd();\n await this.middlewareManager.onStepStart(stepInfo);\n\n // If wrappedHandler hasn't been called yet (no deferred from discovery),\n // set one up so wrapStep's next() still blocks until memoization.\n if (!foundStep.memoizationDeferred) {\n const deferred = createDeferredPromise<unknown>();\n foundStep.memoizationDeferred = deferred;\n setActualHandler(() => deferred.promise);\n foundStep.transformedResultPromise = wrappedHandler();\n foundStep.transformedResultPromise.catch(() => {\n // Swallow — errors handled by handle()\n });\n }\n\n // Build wrapStepHandler chain around the actual handler\n const wrappedActualHandler =\n this.middlewareManager.buildWrapStepHandlerChain(actualHandler, stepInfo);\n\n return goIntervalTiming(() => wrappedActualHandler())\n .finally(() => {\n this.devDebug(`finished executing step \"${id}\"`);\n\n this.state.executingStep = undefined;\n\n if (this.rootSpanId && this.options.checkpointingConfig) {\n clientProcessorMap\n .get(this.options.client)\n ?.clearStepExecution(this.rootSpanId);\n }\n\n if (store?.execution) {\n delete store.execution.executingStep;\n }\n })\n .then<OutgoingOp>(async ({ resultPromise, interval: _interval }) => {\n interval = _interval;\n const metadata = this.state.metadata?.get(id);\n const serverData = await resultPromise;\n\n // Don't resolve memoizationDeferred here. wrapStep's next() must\n // block until the step is actually memoized (i.e. handle() fires\n // with confirmed data from the server). handle() resolves it.\n await this.middlewareManager.onStepComplete(stepInfo, serverData);\n\n // Emit inngest.commit — step data is finalized.\n this.streamTools.commit(hashedId);\n\n return {\n ...outgoingOp,\n data: serverData,\n ...(metadata && metadata.length > 0 ? { metadata: metadata } : {}),\n };\n })\n .catch<OutgoingOp>((error) => {\n // Don't reject memoizationDeferred — handle() will reject it when\n // the error is memoized.\n return this.buildStepErrorOp({\n error,\n id,\n outgoingOp,\n stepInfo,\n });\n })\n .then((op) => ({\n ...op,\n timing: interval,\n }));\n }\n\n /**\n * Starts execution of the user's function, including triggering checkpoints\n * and middleware hooks where appropriate.\n */\n private async startExecution(): Promise<void> {\n /**\n * Start the timer to time out the run if needed.\n */\n void this.timeout?.start();\n void this.checkpointingMaxRuntimeTimer?.start();\n void this.checkpointingMaxBufferIntervalTimer?.start();\n\n const fnInputResult = await this.middlewareManager.transformFunctionInput();\n this.applyFunctionInputMutations(fnInputResult);\n\n if (this.state.allStateUsed()) {\n await this.middlewareManager.onMemoizationEnd();\n }\n\n if (this.state.stepsToFulfill === 0 && this.fnArg.attempt === 0) {\n await this.middlewareManager.onRunStart();\n }\n\n const innerHandler: () => Promise<unknown> = async () => {\n await this.validateEventSchemas();\n return this.userFnToRun(this.fnArg);\n };\n\n const runHandler = this.middlewareManager.wrapRunHandler(innerHandler);\n\n runAsPromise(runHandler)\n .then(async (data) => {\n await this.middlewareManager.onRunComplete(data);\n this.state.setCheckpoint({ type: \"function-resolved\", data });\n })\n .catch(async (error) => {\n // Preserve Error instances; stringify non-Error throws (e.g. `throw {}`)\n let err: Error;\n if (error instanceof Error) {\n err = error;\n } else if (typeof error === \"object\") {\n err = new Error(JSON.stringify(error));\n } else {\n err = new Error(String(error));\n }\n\n await this.middlewareManager.onRunError(err, !this.retriability(err));\n this.state.setCheckpoint({ type: \"function-rejected\", error: err });\n });\n }\n\n /**\n * Determine whether the given error is retriable. Returns `false` when the\n * run should not be retried, a duration string for `RetryAfterError`, or\n * `true` for normal retry behavior.\n */\n private retriability(error: unknown): boolean | string {\n const areRetriesExhausted =\n this.fnArg.maxAttempts &&\n this.fnArg.maxAttempts - 1 === this.fnArg.attempt;\n if (areRetriesExhausted) {\n return false;\n }\n\n // TODO: Replace this fragile inheritance + name check. Maybe we should have\n // an \"~inngest\" field with an object that specifies \"isRetriable\".\n if (\n error instanceof NonRetriableError ||\n // biome-ignore lint/suspicious/noExplicitAny: instanceof fails across module boundaries\n (error as any)?.name === \"NonRetriableError\"\n ) {\n return false;\n }\n\n // If the function-level code did not change the error, then we don't want\n // to retry. The vast majority of the time this means there wasn't a `catch`\n // block.\n const isUncaughtStepError =\n error instanceof StepError &&\n error === this.state.recentlyRejectedStepError;\n if (isUncaughtStepError) {\n return false;\n }\n\n // TODO: Replace this fragile inheritance + name check. Maybe we should have\n // an \"~inngest\" field with an object that specifies \"retryAfter\".\n if (\n error instanceof RetryAfterError ||\n // biome-ignore lint/suspicious/noExplicitAny: instanceof fails across module boundaries\n (error as any)?.name === \"RetryAfterError\"\n ) {\n return (error as RetryAfterError).retryAfter;\n }\n\n return true;\n }\n\n /**\n * Build the OutgoingOp for a failed step, notifying middleware and choosing\n * retriable vs non-retriable opcode.\n */\n private async buildStepErrorOp({\n error,\n id,\n outgoingOp,\n stepInfo,\n }: {\n error: unknown;\n id: string;\n outgoingOp: OutgoingOp;\n stepInfo: Middleware.StepInfo;\n }): Promise<OutgoingOp> {\n const isFinal = !this.retriability(error);\n const metadata = this.state.metadata?.get(id);\n\n await this.middlewareManager.onStepError(\n stepInfo,\n error instanceof Error ? error : new Error(String(error)),\n isFinal,\n );\n\n // Step's stream should be rolled back\n this.streamTools.rollback(outgoingOp.id);\n\n // Serialize the error so it survives JSON.stringify (raw Error\n // objects have non-enumerable properties that get dropped).\n // This is critical for checkpoint requests where the error is\n // sent as JSON in the request body.\n const serialized = serializeError(error);\n\n return {\n ...outgoingOp,\n error: serialized,\n op: isFinal ? StepOpCode.StepFailed : StepOpCode.StepError,\n ...(metadata && metadata.length > 0 ? { metadata } : {}),\n };\n }\n\n /**\n * Validate event data against schemas defined in function triggers.\n */\n private async validateEventSchemas(): Promise<void> {\n if (this.options.isFailureHandler) {\n // Skip validation because the main function's triggers don't apply to its\n // `onFailure` handler. The `onFailure` handler is a separate Inngest\n // function that's implicitly triggered by the \"inngest/function.failed\"\n // event.\n return;\n }\n\n const triggers = this.options.fn.opts.triggers;\n if (!triggers || triggers.length === 0) return;\n\n const fnArgEvents = this.fnArg.events;\n if (!fnArgEvents || fnArgEvents.length === 0) return;\n\n const events = fnArgEvents.map((event) => ({\n name: event.name,\n data: event.data,\n }));\n\n await validateEvents(events, triggers);\n }\n\n /**\n * Using middleware, transform output before returning.\n */\n private transformOutput(dataOrError: {\n data?: unknown;\n error?: unknown;\n }): ExecutionResult {\n const { data, error } = dataOrError;\n\n if (typeof error !== \"undefined\") {\n const retriable = this.retriability(error);\n const serializedError = serializeError(error);\n\n return {\n type: \"function-rejected\",\n ctx: this.fnArg,\n ops: this.ops,\n error: serializedError,\n retriable,\n };\n }\n\n return {\n type: \"function-resolved\",\n ctx: this.fnArg,\n ops: this.ops,\n data: undefinedToNull(data),\n };\n }\n\n private createExecutionState(): ExecutionState {\n const d = createDeferredPromiseWithStack<Checkpoint>();\n let checkpointResolve = d.deferred.resolve;\n const checkpointResults = d.results;\n\n const loop: ExecutionState[\"loop\"] = (async function* (\n cleanUp?: () => void,\n ) {\n try {\n while (true) {\n const res = (await checkpointResults.next()).value;\n if (res) {\n yield res;\n }\n }\n } finally {\n cleanUp?.();\n }\n })(() => {\n this.timeout?.clear();\n this.checkpointingMaxRuntimeTimer?.clear();\n this.checkpointingMaxBufferIntervalTimer?.clear();\n void checkpointResults.return();\n });\n\n const stepsToFulfill = Object.keys(this.options.stepState).length;\n\n const state: ExecutionState = {\n stepState: this.options.stepState,\n stepsToFulfill,\n steps: new Map(),\n loop,\n hasSteps: Boolean(stepsToFulfill),\n stepCompletionOrder: [...this.options.stepCompletionOrder],\n remainingStepsToBeSeen: new Set(this.options.stepCompletionOrder),\n setCheckpoint: (checkpoint: Checkpoint) => {\n this.devDebug(\"setting checkpoint:\", checkpoint.type);\n\n ({ resolve: checkpointResolve } = checkpointResolve(checkpoint));\n },\n allStateUsed: () => {\n return this.state.remainingStepsToBeSeen.size === 0;\n },\n checkpointingStepBuffer: [],\n metadata: new Map(),\n };\n\n return state;\n }\n\n get ops(): Record<string, MemoizedOp> {\n return Object.fromEntries(this.state.steps);\n }\n\n private createFnArg(): Context.Any {\n const step = this.createStepTools();\n const experimentStepRun = (step as unknown as ExperimentStepTools)[\n experimentStepRunSymbol\n ];\n\n let fnArg = {\n ...(this.options.data as { event: EventPayload }),\n step,\n group: createGroupTools({ experimentStepRun }),\n } as Context.Any;\n\n /**\n * Handle use of the `onFailure` option by deserializing the error.\n */\n if (this.options.isFailureHandler) {\n const eventData = z\n .object({ error: jsonErrorSchema })\n .parse(fnArg.event?.data);\n\n (fnArg as Partial<Pick<FailureEventArgs, \"error\">>) = {\n ...fnArg,\n error: deserializeError(eventData.error),\n };\n }\n\n return this.options.transformCtx?.(fnArg) ?? fnArg;\n }\n\n /**\n * Apply mutations from `transformFunctionInput` back to execution state.\n * Allows middleware to modify event data, step tools, memoized step data,\n * and inject custom fields into the handler context.\n */\n private applyFunctionInputMutations(\n result: Middleware.TransformFunctionInputArgs,\n ): void {\n const { event, events, step, ...extensions } = result.ctx;\n\n // Mutate in place so the ALS store's reference to this.fnArg stays valid.\n if (event !== this.fnArg.event) {\n this.fnArg.event = event;\n }\n\n if (events !== this.fnArg.events) {\n this.fnArg.events = events;\n }\n\n if (step !== this.fnArg.step) {\n this.fnArg.step = step;\n }\n\n if (Object.keys(extensions).length > 0) {\n Object.assign(this.fnArg, extensions);\n }\n\n // Apply step data mutations\n for (const [hashedId, stepData] of Object.entries(result.steps)) {\n const existing = this.state.stepState[hashedId];\n if (\n existing &&\n stepData &&\n stepData.type === \"data\" &&\n stepData.data !== existing.data\n ) {\n this.state.stepState[hashedId] = { ...existing, data: stepData.data };\n }\n }\n }\n\n private createStepTools(): ReturnType<typeof createStepTools> {\n /**\n * A list of steps that have been found and are being rolled up before being\n * reported to the core loop.\n */\n const foundStepsToReport: Map<string, FoundStep> = new Map();\n\n /**\n * A map of the subset of found steps to report that have not yet been\n * handled. Used for fast access to steps that need to be handled in order.\n */\n const unhandledFoundStepsToReport: Map<string, FoundStep> = new Map();\n\n /**\n * A map of the latest sequential step indexes found for each step ID. Used\n * to ensure that we don't index steps in parallel.\n *\n * Note that these must be sequential; if we've seen or assigned `a:1`,\n * `a:2` and `a:4`, the latest sequential step index is `2`.\n *\n */\n const expectedNextStepIndexes: Map<string, number> = new Map();\n\n /**\n * An ordered list of step IDs that have yet to be handled in this\n * execution. Used to ensure that we handle steps in the order they were\n * found and based on the `stepCompletionOrder` in this execution's state.\n */\n const remainingStepCompletionOrder: string[] =\n this.state.stepCompletionOrder.slice();\n\n /**\n * A promise that's used to ensure that step reporting cannot be run more than\n * once in a given asynchronous time span.\n */\n let foundStepsReportPromise: Promise<void> | undefined;\n\n /**\n * A flag used to ensure that we only warn about parallel indexing once per\n * execution to avoid spamming the console.\n */\n let warnOfParallelIndexing = false;\n\n /**\n * Counts the number of times we've extended this tick.\n */\n let tickExtensionCount = 0;\n\n /**\n * Given a colliding step ID, maybe warn the user about parallel indexing.\n */\n const maybeWarnOfParallelIndexing = (userlandCollisionId: string) => {\n if (warnOfParallelIndexing) {\n return;\n }\n\n const hashedCollisionId = _internals.hashId(userlandCollisionId);\n\n const stepExists = this.state.steps.has(hashedCollisionId);\n if (stepExists) {\n const stepFoundThisTick = foundStepsToReport.has(hashedCollisionId);\n if (!stepFoundThisTick) {\n warnOfParallelIndexing = true;\n\n this.options.client[\"warnMetadata\"](\n { run_id: this.fnArg.runId },\n ErrCode.AUTOMATIC_PARALLEL_INDEXING,\n {\n message: `Duplicate step ID \"${userlandCollisionId}\" detected across parallel chains`,\n explanation:\n \"Using the same ID for steps in different parallel chains can cause unexpected behaviour. Your function is still running.\",\n action:\n \"Use a unique ID for each step, especially those in parallel.\",\n code: ErrCode.AUTOMATIC_PARALLEL_INDEXING,\n },\n );\n }\n }\n };\n\n /**\n * A helper used to report steps to the core loop. Used after adding an item\n * to `foundStepsToReport`.\n */\n const reportNextTick = () => {\n // Being explicit instead of using `??=` to appease TypeScript.\n if (foundStepsReportPromise) {\n return;\n }\n\n let extensionPromise: Promise<void>;\n if (++tickExtensionCount >= 10) {\n tickExtensionCount = 0;\n extensionPromise = resolveNextTick();\n } else {\n extensionPromise = resolveAfterPending();\n }\n\n foundStepsReportPromise = extensionPromise.then(() => {\n foundStepsReportPromise = undefined;\n\n for (let i = 0; i < remainingStepCompletionOrder.length; i++) {\n const nextStepId = remainingStepCompletionOrder[i];\n if (!nextStepId) {\n // Strange - skip this empty index\n continue;\n }\n\n const handled = unhandledFoundStepsToReport.get(nextStepId)?.handle();\n if (handled) {\n remainingStepCompletionOrder.splice(i, 1);\n unhandledFoundStepsToReport.delete(nextStepId);\n return void reportNextTick();\n }\n }\n\n // If we've handled no steps in this \"tick,\" roll up everything we've\n // found and report it.\n const steps = [...foundStepsToReport.values()];\n foundStepsToReport.clear();\n unhandledFoundStepsToReport.clear();\n\n if (!isNonEmpty(steps)) {\n return;\n }\n\n return void this.state.setCheckpoint({\n type: \"steps-found\",\n steps: steps,\n });\n });\n };\n\n /**\n * A helper used to push a step to the list of steps to report.\n */\n const pushStepToReport = (step: FoundStep) => {\n foundStepsToReport.set(step.hashedId, step);\n unhandledFoundStepsToReport.set(step.hashedId, step);\n reportNextTick();\n };\n\n const stepHandler: StepHandler = async ({\n args,\n matchOp,\n opts,\n }): Promise<unknown> => {\n const stepOptions = getStepOptions(args[0]);\n const opId = matchOp(stepOptions, ...args.slice(1));\n\n if (this.state.executingStep) {\n /**\n * If a step is found after asynchronous actions during another step's\n * execution, everything is fine. The problem here is if we've found\n * that a step nested inside another a step, which is something we don't\n * support at the time of writing.\n *\n * In this case, we could use something like Async Hooks to understand\n * how the step is being triggered, though this isn't available in all\n * environments.\n *\n * Therefore, we'll only show a warning here to indicate that this is\n * potentially an issue.\n */\n this.options.client[\"warnMetadata\"](\n { run_id: this.fnArg.runId },\n ErrCode.NESTING_STEPS,\n {\n message: `Nested step tooling detected in \"${opId.displayName ?? opId.id}\"`,\n explanation:\n \"Nesting step.* calls is not supported. This warning may also appear if steps are separated by regular async calls, which is fine.\",\n action:\n \"Avoid using step.* inside other step.* calls. Use a separate async function or promise chaining to compose steps.\",\n code: ErrCode.NESTING_STEPS,\n },\n );\n }\n\n // Apply middleware transformations (may change step ID, affecting\n // memoization lookup)\n const {\n hashedId,\n isFulfilled,\n setActualHandler,\n stepInfo,\n stepState,\n wrappedHandler,\n } = await this.applyMiddlewareToStep(\n opId,\n expectedNextStepIndexes,\n maybeWarnOfParallelIndexing,\n );\n\n const { promise, resolve, reject } = createDeferredPromise();\n\n let extraOpts: Record<string, unknown> | undefined;\n let fnArgs = [...args];\n\n if (\n typeof stepState?.input !== \"undefined\" &&\n Array.isArray(stepState.input)\n ) {\n switch (opId.op) {\n // `step.run()` has its function input affected\n case StepOpCode.StepPlanned: {\n fnArgs = [...args.slice(0, 2), ...stepState.input];\n\n extraOpts = { input: [...stepState.input] };\n break;\n }\n\n // `step.ai.infer()` has its body affected\n case StepOpCode.AiGateway: {\n extraOpts = {\n body: {\n ...(typeof opId.opts?.body === \"object\"\n ? { ...opId.opts.body }\n : {}),\n ...stepState.input[0],\n },\n };\n break;\n }\n }\n }\n\n // If transformStepInput middleware may have changed the input, update\n // `fnArgs` so `fn` uses the transformed values. Skip if replay already\n // set `extraOpts`.\n if (!extraOpts && Array.isArray(stepInfo.input)) {\n fnArgs = [...args.slice(0, 2), ...stepInfo.input];\n }\n\n const step: FoundStep = {\n ...opId,\n opts: { ...opId.opts, ...extraOpts },\n rawArgs: fnArgs,\n hashedId,\n input: stepState?.input,\n\n fn: opts?.fn ? () => opts.fn?.(this.fnArg, ...fnArgs) : undefined,\n promise,\n fulfilled: isFulfilled,\n hasStepState: Boolean(stepState),\n displayName: opId.displayName ?? opId.id,\n handled: false,\n\n // Middleware context for deferred handler pattern\n middleware: {\n wrappedHandler,\n stepInfo,\n setActualHandler,\n },\n\n handle: () => {\n if (step.handled) {\n return false;\n }\n\n this.devDebug(`handling step \"${hashedId}\"`);\n\n step.handled = true;\n\n // Refetch step state because it may have been changed since we found\n // the step. This could be due to checkpointing, where we run this\n // live and then return to the function.\n const result = this.state.stepState[hashedId];\n\n if (step.fulfilled && result) {\n result.fulfilled = true;\n\n // For some execution scenarios such as testing, `data`, `error`,\n // and `input` may be `Promises`. This could also be the case for\n // future middleware applications. For this reason, we'll make sure\n // the values are fully resolved before continuing.\n void Promise.all([result.data, result.error, result.input]).then(\n async () => {\n // If the wrapStep chain already ran during discovery in this\n // same request (checkpointing), reuse its result instead of\n // firing wrappedHandler() again. This prevents middleware from\n // seeing a duplicate wrapStep call per step per request.\n if (step.transformedResultPromise) {\n // Resolve the memoization deferred so wrapStep's next()\n // unblocks. The step data is now confirmed memoized.\n if (step.memoizationDeferred) {\n if (typeof result.data !== \"undefined\") {\n step.memoizationDeferred.resolve(await result.data);\n } else {\n const stepError = new StepError(opId.id, result.error);\n this.state.recentlyRejectedStepError = stepError;\n step.memoizationDeferred.reject(stepError);\n }\n }\n\n step.transformedResultPromise.then(resolve, reject);\n return;\n }\n\n // The wrapStep chain is about to fire again to resolve the\n // step promise through middleware (e.g. deserialization).\n // Mark the step as memoized so middleware can distinguish\n // this from the original execution call.\n //\n // This need for this change was discovered when checkpointing +\n // middleware's \"double `wrapStep` call\" behavior had `memoized:\n // false` on the 2nd call\n step.middleware.stepInfo.memoized = true;\n\n if (typeof result.data !== \"undefined\") {\n // Validate waitForEvent results against the schema if present\n // Skip validation if result.data is null (timeout case)\n if (\n opId.op === StepOpCode.WaitForEvent &&\n result.data !== null\n ) {\n const { event } = (step.rawArgs?.[1] ?? {}) as {\n event: unknown;\n };\n if (!event) {\n // Unreachable\n throw new Error(\"Missing event option in waitForEvent\");\n }\n try {\n await validateEvents(\n [result.data],\n\n // @ts-expect-error - This is a full event object at runtime\n [{ event }],\n );\n } catch (err) {\n this.state.recentlyRejectedStepError = new StepError(\n opId.id,\n err,\n );\n reject(this.state.recentlyRejectedStepError);\n return;\n }\n }\n\n // Set inner handler to return memoized data\n step.middleware.setActualHandler(() =>\n Promise.resolve(result.data),\n );\n\n step.middleware.wrappedHandler().then(resolve);\n } else {\n const stepError = new StepError(opId.id, result.error);\n this.state.recentlyRejectedStepError = stepError;\n\n // Set inner handler to reject with step error\n step.middleware.setActualHandler(() =>\n Promise.reject(stepError),\n );\n\n step.middleware.wrappedHandler().catch(reject);\n }\n },\n );\n }\n\n return true;\n },\n };\n\n this.state.steps.set(hashedId, step);\n this.state.hasSteps = true;\n\n const isNewStepWithHandler = !isFulfilled && !stepState && step.fn;\n if (isNewStepWithHandler) {\n // New, never-seen step with a handler (e.g. `step.run`). Kick off the\n // middleware wrapStep chain now so it runs during discovery, not later\n // in executeStep.\n //\n // This is necessary so that middleware can inject their own steps.\n // Reporting is deferred to the center of the onion so that if\n // middleware throws or injects prerequisites, the step is never\n // reported.\n const deferred = createDeferredPromise<unknown>();\n step.memoizationDeferred = deferred;\n\n setActualHandler(() => {\n pushStepToReport(step);\n return deferred.promise;\n });\n\n step.transformedResultPromise = wrappedHandler();\n step.transformedResultPromise.catch((error) => {\n reject(error);\n });\n } else {\n pushStepToReport(step);\n }\n\n return promise;\n };\n\n return createStepTools(this.options.client, this, stepHandler);\n }\n\n /**\n * Applies middleware transformations to a step, resolves ID collisions,\n * and performs memoization lookup.\n */\n private async applyMiddlewareToStep(\n opId: HashedOp,\n expectedNextStepIndexes: Map<string, number>,\n maybeWarnOfParallelIndexing: (userlandCollisionId: string) => void,\n ): Promise<MiddlewareApplicationResult> {\n // 1. Resolve initial collision with original ID\n const initialCollision = resolveStepIdCollision({\n baseId: opId.id,\n expectedIndexes: expectedNextStepIndexes,\n stepsMap: this.state.steps,\n });\n if (initialCollision.finalId !== opId.id) {\n maybeWarnOfParallelIndexing(opId.id);\n opId.id = initialCollision.finalId;\n if (initialCollision.index !== undefined) {\n opId.userland.index = initialCollision.index;\n }\n }\n\n const originalId = opId.userland.id;\n let hashedId = _internals.hashId(opId.id);\n\n // 2. Apply middleware (stepType, input extraction, deferred handler).\n // Pass preliminary memoization status so middleware sees it.\n const prepared = await this.middlewareManager.applyToStep({\n displayName: opId.displayName ?? opId.userland.id,\n hashedId,\n memoized:\n Boolean(this.state.stepState[hashedId]) &&\n typeof this.state.stepState[hashedId]?.input === \"undefined\",\n op: opId.op,\n opts: opId.opts,\n userlandId: opId.userland.id,\n });\n const { entryPoint, opName, opOpts, setActualHandler, stepInfo } = prepared;\n\n if (opName !== undefined) {\n opId.name = opName;\n }\n if (opOpts !== undefined) {\n opId.opts = opOpts;\n }\n\n // 3. If middleware changed the step ID, re-resolve collisions\n if (stepInfo.options.id !== originalId) {\n opId.id = stepInfo.options.id;\n opId.userland.id = stepInfo.options.id;\n\n const secondCollision = resolveStepIdCollision({\n baseId: stepInfo.options.id,\n expectedIndexes: expectedNextStepIndexes,\n stepsMap: this.state.steps,\n });\n if (secondCollision.finalId !== stepInfo.options.id) {\n opId.id = secondCollision.finalId;\n opId.userland.id = secondCollision.finalId;\n stepInfo.options.id = secondCollision.finalId;\n if (secondCollision.index !== undefined) {\n opId.userland.index = secondCollision.index;\n }\n }\n\n // Recompute hashedId with final ID\n hashedId = _internals.hashId(opId.id);\n stepInfo.hashedId = hashedId;\n }\n\n // 4. Final memoization lookup with potentially modified hashedId.\n // Also marks step as seen and may trigger onMemoizationEnd.\n const stepState = this.state.stepState[hashedId];\n let isFulfilled = false;\n if (stepState) {\n stepState.seen = true;\n this.state.remainingStepsToBeSeen.delete(hashedId);\n\n if (this.state.allStateUsed()) {\n await this.middlewareManager.onMemoizationEnd();\n }\n\n if (typeof stepState.input === \"undefined\") {\n isFulfilled = true;\n }\n stepInfo.memoized = isFulfilled;\n } else {\n stepInfo.memoized = false;\n }\n\n // 5. Build wrapStep chain after all mutations so middleware sees final values\n const wrappedHandler = this.middlewareManager.buildWrapStepChain(\n entryPoint,\n stepInfo,\n );\n\n return {\n hashedId,\n stepInfo,\n wrappedHandler,\n setActualHandler,\n stepState,\n isFulfilled,\n };\n }\n\n private resumeStepWithResult(resultOp: OutgoingOp, resume = true): FoundStep {\n const userlandStep = this.state.steps.get(resultOp.id);\n if (!userlandStep) {\n throw new Error(\n \"Step not found in memoization state during async checkpointing; this should never happen and is a bug in the Inngest SDK\",\n );\n }\n\n const data = undefinedToNull(resultOp.data);\n\n userlandStep.data = data;\n userlandStep.timing = resultOp.timing;\n userlandStep.op = resultOp.op;\n userlandStep.id = resultOp.id;\n userlandStep.metadata = resultOp.metadata;\n\n if (resume) {\n userlandStep.fulfilled = true;\n userlandStep.hasStepState = true;\n this.state.stepState[resultOp.id] = userlandStep;\n\n userlandStep.handle();\n }\n\n return userlandStep;\n }\n\n private getUserFnToRun(): Handler.Any {\n if (!this.options.isFailureHandler) {\n return this.options.fn[\"fn\"];\n }\n\n if (!this.options.fn[\"onFailureFn\"]) {\n /**\n * Somehow, we've ended up detecting that this is a failure handler but\n * doesn't have an `onFailure` function. This should never happen.\n */\n throw new Error(\"Cannot find function `onFailure` handler\");\n }\n\n return this.options.fn[\"onFailureFn\"];\n }\n\n private initializeTimer(state: ExecutionState): void {\n if (!this.options.requestedRunStep) {\n return;\n }\n\n this.timeout = createTimeoutPromise(this.timeoutDuration);\n\n void this.timeout.then(async () => {\n await this.middlewareManager.onMemoizationEnd();\n const { foundSteps, totalFoundSteps } = this.getStepNotFoundDetails();\n state.setCheckpoint({\n type: \"step-not-found\",\n step: {\n id: this.options.requestedRunStep as string,\n op: StepOpCode.StepNotFound,\n },\n foundSteps,\n totalFoundSteps,\n });\n });\n }\n\n private getStepNotFoundDetails(): {\n foundSteps: BasicFoundStep[];\n totalFoundSteps: number;\n } {\n const foundSteps = [...this.state.steps.values()]\n .filter((step) => !step.hasStepState)\n .map<BasicFoundStep>((step) => ({\n id: step.hashedId,\n name: step.name,\n displayName: step.displayName,\n }))\n .sort((a, b) => a.id.localeCompare(b.id));\n\n return {\n foundSteps: foundSteps.slice(0, STEP_NOT_FOUND_MAX_FOUND_STEPS),\n totalFoundSteps: foundSteps.length,\n };\n }\n\n private initializeCheckpointRuntimeTimer(state: ExecutionState): void {\n this.devDebug(\n \"initializing checkpointing runtime timers\",\n this.options.checkpointingConfig,\n );\n\n if (this.options.checkpointingConfig?.maxRuntime) {\n const maxRuntimeMs = Temporal.isTemporalDuration(\n this.options.checkpointingConfig.maxRuntime,\n )\n ? this.options.checkpointingConfig.maxRuntime.total({\n unit: \"milliseconds\",\n })\n : typeof this.options.checkpointingConfig.maxRuntime === \"string\"\n ? ms(this.options.checkpointingConfig.maxRuntime as StringValue) // type assertion to satisfy ms package\n : (this.options.checkpointingConfig.maxRuntime as number);\n\n // 0 or negative max runtime? Skip.\n if (Number.isFinite(maxRuntimeMs) && maxRuntimeMs > 0) {\n this.checkpointingMaxRuntimeTimer = createTimeoutPromise(maxRuntimeMs);\n\n void this.checkpointingMaxRuntimeTimer.then(async () => {\n await this.middlewareManager.onMemoizationEnd();\n state.setCheckpoint({\n type: \"checkpointing-runtime-reached\",\n });\n });\n }\n }\n\n if (this.options.checkpointingConfig?.maxInterval) {\n const maxIntervalMs = Temporal.isTemporalDuration(\n this.options.checkpointingConfig.maxInterval,\n )\n ? this.options.checkpointingConfig.maxInterval.total({\n unit: \"milliseconds\",\n })\n : typeof this.options.checkpointingConfig.maxInterval === \"string\"\n ? ms(this.options.checkpointingConfig.maxInterval as StringValue) // type assertion to satisfy ms package\n : (this.options.checkpointingConfig.maxInterval as number);\n\n // 0 or negative max interval? Skip.\n if (Number.isFinite(maxIntervalMs) && maxIntervalMs > 0) {\n this.checkpointingMaxBufferIntervalTimer =\n createTimeoutPromise(maxIntervalMs);\n\n void this.checkpointingMaxBufferIntervalTimer.then(async () => {\n // Note that this will not immediately run; it will be queued like all\n // other checkpoints so that we're never running multiple checkpoints\n // at the same time and it's easier to reason about those decision\n // points.\n //\n // A change in the future may be to make this particular checkpointing\n // action immediate and have the checkpoint action itself be\n // idempotent.\n state.setCheckpoint({\n type: \"checkpointing-buffer-interval-reached\",\n });\n\n this.checkpointingMaxBufferIntervalTimer?.reset();\n });\n }\n }\n }\n}\n\n/**\n * Types of checkpoints that can be reached during execution.\n */\nexport interface Checkpoints {\n \"steps-found\": { steps: [FoundStep, ...FoundStep[]] };\n \"function-rejected\": { error: unknown };\n \"function-resolved\": { data: unknown };\n \"step-not-found\": {\n step: OutgoingOp;\n foundSteps: BasicFoundStep[];\n totalFoundSteps: number;\n };\n \"checkpointing-runtime-reached\": {};\n \"checkpointing-buffer-interval-reached\": {};\n}\n\ntype Checkpoint = {\n [K in keyof Checkpoints]: Simplify<{ type: K } & Checkpoints[K]>;\n}[keyof Checkpoints];\n\ntype CheckpointHandlers = Record<\n StepMode,\n {\n [C in Checkpoint as C[\"type\"]]: (\n checkpoint: C,\n\n /**\n * This is the number of checkpoints that have been seen before this one was\n * triggered.\n *\n * The catch-all `\"\"` checkpoint does not increment this count.\n */\n i: number,\n ) => MaybePromise<ExecutionResult | undefined>;\n } & {\n \"\": (\n checkpoint: Checkpoint,\n\n /**\n * This is the number of checkpoints that have been seen before this one was\n * triggered.\n *\n * The catch-all `\"\"` checkpoint does not increment this count.\n */\n i: number,\n ) => MaybePromise<void>;\n }\n>;\n\nexport interface ExecutionState {\n /**\n * A value that indicates that we're executing this step. Can be used to\n * ensure steps are not accidentally nested until we support this across all\n * platforms.\n */\n executingStep?: Readonly<Omit<OutgoingOp, \"id\">>;\n\n /**\n * A map of step IDs to their data, used to fill previously-completed steps\n * with state from the executor.\n */\n stepState: Record<string, MemoizedOp>;\n\n /**\n * The number of steps we expect to fulfil based on the state passed from the\n * Executor.\n */\n stepsToFulfill: number;\n\n /**\n * A map of step IDs to their functions to run. The executor can request a\n * specific step to run, so we need to store the function to run here.\n */\n steps: Map<string, FoundStep>;\n\n /**\n * A flag which represents whether or not steps are understood to be used in\n * this function. This is used to determine whether or not we should run\n * some steps (such as `step.sendEvent`) inline as they are found.\n */\n hasSteps: boolean;\n\n /**\n * The core loop - a generator used to take an action upon finding the next\n * checkpoint. Manages the flow of execution and cleaning up after itself.\n */\n loop: AsyncGenerator<Checkpoint, void, void>;\n\n /**\n * A function that resolves the `Promise` returned by `waitForNextDecision`.\n */\n setCheckpoint: (data: Checkpoint) => void;\n\n /**\n * Returns whether or not all state passed from the executor has been used to\n * fulfill found steps.\n */\n allStateUsed: () => boolean;\n\n /**\n * An ordered list of step IDs that represents the order in which their\n * execution was completed.\n */\n stepCompletionOrder: string[];\n\n /**\n * An set of step IDs that have yet to be seen in this execution. Used to\n * decide when to trigger middleware based on the current state.\n */\n remainingStepsToBeSeen: Set<string>;\n\n /**\n * If defined, this is the error that purposefully thrown when memoizing step\n * state in order to support per-step errors.\n *\n * We use this so that if the function itself rejects with the same error, we\n * know that it was entirely uncaught (or at the very least rethrown), so we\n * should send a `NonRetriableError` to stop needless execution of a function\n * that will continue to fail.\n *\n * TODO This is imperfect, as this state is currently kept around for longer\n * than it needs to be. It should disappear as soon as we've seen that the\n * error did not immediately throw. It may need to be refactored to work a\n * little more smoothly with the core loop.\n */\n recentlyRejectedStepError?: StepError;\n\n /**\n * If defined, this indicates that we're running a checkpointed function run,\n * and contains the data needed to report progress back to Inngest.\n */\n checkpointedRun?: {\n fnId: string;\n appId: string;\n token?: string;\n realtimeToken: string;\n };\n\n /**\n * Set when the checkpointing max runtime has been reached. Rather than\n * immediately returning a DiscoveryRequest (which re-invokes user code\n * between steps), we defer until the next step boundary so the user's code\n * between steps can complete.\n */\n checkpointingRuntimeExceeded?: boolean;\n\n /**\n * A buffer of steps that are currently queued to be checkpointed.\n */\n checkpointingStepBuffer: OutgoingOp[];\n\n /**\n * Metadata collected during execution to be sent with outgoing ops.\n */\n metadata?: Map<string, Array<MetadataUpdate>>;\n}\n\nconst hashId = (id: string): string => {\n return sha1().update(id).digest(\"hex\");\n};\n\nconst hashOp = (op: OutgoingOp): OutgoingOp => {\n return {\n ...op,\n id: hashId(op.id),\n };\n};\n\n/**\n * Result of resolving a step ID collision.\n */\ninterface CollisionResolutionResult {\n /** The final ID to use (either original or with index suffix). */\n finalId: string;\n\n /** The index used, if collision was detected. */\n index?: number;\n}\n\n/** Result of applying middleware to a step. */\ninterface MiddlewareApplicationResult {\n hashedId: string;\n isFulfilled: boolean;\n setActualHandler: (handler: () => Promise<unknown>) => void;\n stepInfo: Middleware.StepInfo;\n stepState: MemoizedOp | undefined;\n wrappedHandler: () => Promise<unknown>;\n}\n\n/**\n * Resolves step ID collisions by appending an index suffix if needed.\n * Consolidates the duplicated collision detection logic.\n *\n * @param baseId - The original step ID\n * @param stepsMap - Map of existing steps (keyed by hashed ID)\n * @param expectedIndexes - Map tracking expected next index for each base ID\n * @returns The final ID to use and optional index\n */\nfunction resolveStepIdCollision({\n baseId,\n expectedIndexes,\n stepsMap,\n}: {\n baseId: string;\n expectedIndexes: Map<string, number>;\n stepsMap: Map<string, FoundStep>;\n}): CollisionResolutionResult {\n const hashedBaseId = hashId(baseId);\n\n // Check both stepsMap (steps added to state) and expectedIndexes (claimed by\n // concurrent in-progress step handlers that haven't been added to state yet).\n if (!stepsMap.has(hashedBaseId) && !expectedIndexes.has(baseId)) {\n // No collision. Claim this base ID so concurrent callers detect collision.\n expectedIndexes.set(baseId, 1);\n return { finalId: baseId };\n }\n\n // Collision detected. Find next available index\n const expectedNextIndex = expectedIndexes.get(baseId) ?? 1;\n const maxIndex = expectedNextIndex + stepsMap.size + 1;\n for (let i = expectedNextIndex; i < maxIndex; i++) {\n const indexedId = baseId + STEP_INDEXING_SUFFIX + i;\n const hashedIndexedId = hashId(indexedId);\n\n if (!stepsMap.has(hashedIndexedId)) {\n expectedIndexes.set(baseId, i + 1);\n return { finalId: indexedId, index: i };\n }\n }\n\n throw new UnreachableError(\n `Could not resolve step ID collision for \"${baseId}\" after ${stepsMap.size + 1} attempts`,\n );\n}\n\nfunction isNonEmpty<T>(arr: T[]): arr is [T, ...T[]] {\n return arr.length > 0;\n}\n\n/**\n * Exported for testing.\n */\nexport const _internals = { hashOp, hashId, resolveStepIdCollision };\n"],"mappings":"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"}