import type { ExecutionID } from "./execution.js"; import type { FunctionBundleProps, FunctionRuntimeProps } from "./function-props.js"; import type { SendTaskFailureRequest, SendTaskSuccessRequest } from "./internal/eventual-service.js"; import { AsyncTokenSymbol, TaskSpec } from "./internal/task.js"; import type { DurationSchedule, Schedule } from "./schedule.js"; import type { SendTaskHeartbeatResponse } from "./service-client.js"; import { ServiceContext } from "./service.js"; /** * Heartbeat token request which has an optional task token. */ export interface SendTaskHeartbeatInternalRequest { taskToken?: string; } export type TaskRuntimeProps = FunctionRuntimeProps; /** * Task options available when invoked by a workflow. */ export interface TaskInvocationOptions { /** * A promise whose resolution (fulfillment or rejection) determines the timeout for a task. * * * Overrides any timeout configured on the task definition. * * ```ts * // times out after 10 minutes * myTask("someInput", { timeout: duration(10, "minutes") }); * // times out when myTimeoutTask resolves * myTask("someInput", { timeout: myTimeoutTask() }); * // times out when the value x is equal to 100 * myTask("someInput", { timeout: condition(() => x === 100) }); * // times out after 10 minutes, like the first example * myTask("someInput", { timeout: Schedule.duration(10, "minutes") }); * ``` * * @default - the configured task timeout or the workflow will await forever. */ timeout?: Promise | Schedule; /** * For long running tasks, it is suggested that they report back that they * are still in progress to avoid waiting forever or until a long timeout when * something goes wrong. * * When set to a positive number, the task must call {@link heartbeat} or * {@link EventualServiceClient.sendTaskHeartbeat} at least every heartbeatSeconds. * * If it fails to do so, the workflow will cancel the task and throw an error. */ heartbeatTimeout?: DurationSchedule; } /** * Task options available at definition time. */ export interface TaskOptions extends Omit, FunctionRuntimeProps, FunctionBundleProps { /** * How long the workflow will wait for the task to complete or fail. * * @default - workflow will wait forever. */ timeout?: DurationSchedule; } export type TaskArguments = [Input] extends [undefined] ? [input?: Input, options?: TaskInvocationOptions] : [input: Input, options?: TaskInvocationOptions]; export interface Task extends Omit, "name"> { kind: "Task"; (...args: TaskArguments): Promise>>; /** * Globally unique ID of this {@link Task}. */ name: Name; handler: TaskHandler; /** * Complete a task request by its {@link SendTaskSuccessRequest.taskToken}. * * This method is used in conjunction with {@link asyncResult} in a task * to perform asynchronous, long-running computations. For example: * * ```ts * const tokenEvent = event("token"); * * const asyncTask = task("async", () => { * return asyncResult(token => tokenEvent.emit({ token })); * }); * * tokenEvent.onEvent("onTokenEvent", async ({token}) => { * await asyncTask.sendTaskSuccess({ * taskToken: token, * result: "done" * }); * }) * ``` */ sendTaskSuccess(request: Omit>>, "type">): Promise; /** * Fail a task request by its {@link SendTaskFailureRequest.taskToken}. * * This method is used in conjunction with {@link asyncResult} in a task * to perform asynchronous, long-running computations. For example: * * ```ts * const tokenEvent = event("token"); * * const asyncTask = task("async", () => { * return asyncResult(token => tokenEvent.emit({ token })); * }); * * tokenEvent.onEvent("onTokenEvent", async ({token}) => { * await asyncTask.sendTaskFailure({ * taskToken: token, * error: "MyError", * message: "Something went wrong" * }); * }) * ``` */ sendTaskFailure(request: Omit): Promise; /** * Heartbeat a task request by its {@link SendTaskHeartbeatRequest.taskToken}. * * This method is used in conjunction with {@link asyncResult} in a task * to perform asynchronous, long-running computations. For example: * * ```ts * const tokenEvent = event("token"); * * const asyncTask = task("async", () => { * return asyncResult(token => tokenEvent.emit({ token })); * }); * * tokenEvent.onEvent("onTokenEvent", async ({token}) => { * await asyncTask.sendTaskFailure({ * taskToken: token * }); * }) * ``` */ sendTaskHeartbeat(request: SendTaskHeartbeatInternalRequest): Promise; } export interface TaskHandler { (input: Input, context: TaskContext): Promise> | Awaited | AsyncResult> | Promise>>; } export type UnwrapAsync = Output extends AsyncResult ? O : Output; export type TaskOutput> = A extends Task ? UnwrapAsync> : never; /** * When returned from a task, the task will become async, * allowing it to run "forever". The */ export interface AsyncResult { [AsyncTokenSymbol]: typeof AsyncTokenSymbol & Output; } /** * When returned from an {@link task}, tells the system to make the current * task async. This allows the task to defer sending a response from the * current function and instead complete the task with {@link WorkflowClient.sendTaskSuccess}. * * ```ts * const sqs = new SQSClient(); * task("myTask", () => { * // tells the system that the sendTaskSuccess function will be called later with a string result. * return asyncResult(async (taskToken) => { * // before exiting, send the taskToken to a sqs queue to be completed later * // you could invoke any service here * await sqs.send(new SendMessageCommand({ ..., message: JSONl.stringify({ taskToken }))); * }); * }) * ``` * * @param tokenContext is a callback which provides the taskToken. The task token is used * to sendTaskSuccess and sendTaskHeartbeat from outside of the * task. */ export declare function asyncResult(tokenContext: (token: string) => Promise | void): Promise>; /** * Registers a function as a task. * * @param taskID a string that uniquely identifies the Task within a single workflow context. * @param handler the function that handles the task */ export declare function task(taskID: Name, handler: TaskHandler): Task; export declare function task(taskID: Name, opts: TaskOptions, handler: TaskHandler): Task; export interface TaskExecutionContext { id: ExecutionID; workflowName: string; } export interface TaskDefinitionContext { name: string; } export interface TaskInvocationContext { /** * A token used to complete or heartbeat a task when running async. */ token: string; /** * ISO 8601 timestamp when the task was first scheduled. */ scheduledTime: string; /** * Current retry count, starting at 0. */ retry: number; } export interface TaskContext { /** * Workflow execution which started the task. */ execution: TaskExecutionContext; /** * Information about the task being invoked. */ task: TaskDefinitionContext; /** * Information about this specific invocation of the execution. */ invocation: TaskInvocationContext; /** *Information about the containing service. */ service: ServiceContext; } //# sourceMappingURL=task.d.ts.map