@temporalio/workflow
Version:
Temporal.io SDK Workflow sub-package
569 lines (499 loc) • 16.7 kB
text/typescript
import type { RawSourceMap } from 'source-map';
import {
RetryPolicy,
TemporalFailure,
CommonWorkflowOptions,
HandlerUnfinishedPolicy,
SearchAttributes,
SignalDefinition,
UpdateDefinition,
QueryDefinition,
Duration,
VersioningIntent,
} from '@temporalio/common';
import { SymbolBasedInstanceOfError } from '@temporalio/common/lib/type-helpers';
import { makeProtoEnumConverters } from '@temporalio/common/lib/internal-workflow/enums-helpers';
import type { coresdk } from '@temporalio/proto';
/**
* Workflow Execution information
*/
export interface WorkflowInfo {
/**
* ID of the Workflow, this can be set by the client during Workflow creation.
* A single Workflow may run multiple times e.g. when scheduled with cron.
*/
readonly workflowId: string;
/**
* ID of a single Workflow run
*/
readonly runId: string;
/**
* Workflow function's name
*/
readonly workflowType: string;
/**
* Indexed information attached to the Workflow Execution
*
* This value may change during the lifetime of an Execution.
*/
readonly searchAttributes: SearchAttributes;
/**
* Non-indexed information attached to the Workflow Execution
*/
readonly memo?: Record<string, unknown>;
/**
* Parent Workflow info (present if this is a Child Workflow)
*/
readonly parent?: ParentWorkflowInfo;
/**
* Result from the previous Run (present if this is a Cron Workflow or was Continued As New).
*
* An array of values, since other SDKs may return multiple values from a Workflow.
*/
readonly lastResult?: unknown;
/**
* Failure from the previous Run (present when this Run is a retry, or the last Run of a Cron Workflow failed)
*/
readonly lastFailure?: TemporalFailure;
/**
* Length of Workflow history up until the current Workflow Task.
*
* This value changes during the lifetime of an Execution.
*
* You may safely use this information to decide when to {@link continueAsNew}.
*/
readonly historyLength: number;
/**
* Size of Workflow history in bytes until the current Workflow Task.
*
* This value changes during the lifetime of an Execution.
*
* Supported only on Temporal Server 1.20+, always zero on older servers.
*
* You may safely use this information to decide when to {@link continueAsNew}.
*/
readonly historySize: number;
/**
* A hint provided by the current WorkflowTaskStarted event recommending whether to
* {@link continueAsNew}.
*
* This value changes during the lifetime of an Execution.
*
* Supported only on Temporal Server 1.20+, always `false` on older servers.
*/
readonly continueAsNewSuggested: boolean;
/**
* Task queue this Workflow is executing on
*/
readonly taskQueue: string;
/**
* Namespace this Workflow is executing in
*/
readonly namespace: string;
/**
* Run Id of the first Run in this Execution Chain
*/
readonly firstExecutionRunId: string;
/**
* The last Run Id in this Execution Chain
*/
readonly continuedFromExecutionRunId?: string;
/**
* Time at which this [Workflow Execution Chain](https://docs.temporal.io/workflows#workflow-execution-chain) was started
*/
readonly startTime: Date;
/**
* Time at which the current Workflow Run started
*/
readonly runStartTime: Date;
/**
* Milliseconds after which the Workflow Execution is automatically terminated by Temporal Server. Set via {@link WorkflowOptions.workflowExecutionTimeout}.
*/
readonly executionTimeoutMs?: number;
/**
* Time at which the Workflow Execution expires
*/
readonly executionExpirationTime?: Date;
/**
* Milliseconds after which the Workflow Run is automatically terminated by Temporal Server. Set via {@link WorkflowOptions.workflowRunTimeout}.
*/
readonly runTimeoutMs?: number;
/**
* Maximum execution time of a Workflow Task in milliseconds. Set via {@link WorkflowOptions.workflowTaskTimeout}.
*/
readonly taskTimeoutMs: number;
/**
* Retry Policy for this Execution. Set via {@link WorkflowOptions.retry}.
*/
readonly retryPolicy?: RetryPolicy;
/**
* Starts at 1 and increments for every retry if there is a `retryPolicy`
*/
readonly attempt: number;
/**
* Cron Schedule for this Execution. Set via {@link WorkflowOptions.cronSchedule}.
*/
readonly cronSchedule?: string;
/**
* Milliseconds between Cron Runs
*/
readonly cronScheduleToScheduleInterval?: number;
/**
* The Build ID of the worker which executed the current Workflow Task. May be undefined if the
* task was completed by a worker without a Build ID. If this worker is the one executing this
* task for the first time and has a Build ID set, then its ID will be used. This value may change
* over the lifetime of the workflow run, but is deterministic and safe to use for branching.
*/
readonly currentBuildId?: string;
readonly unsafe: UnsafeWorkflowInfo;
}
/**
* Unsafe information about the current Workflow Execution.
*
* Never rely on this information in Workflow logic as it will cause non-deterministic behavior.
*/
export interface UnsafeWorkflowInfo {
/**
* Current system time in milliseconds
*
* The safe version of time is `new Date()` and `Date.now()`, which are set on the first invocation of a Workflow
* Task and stay constant for the duration of the Task and during replay.
*/
readonly now: () => number;
readonly isReplaying: boolean;
}
/**
* Information about a workflow update.
*/
export interface UpdateInfo {
/**
* A workflow-unique identifier for this update.
*/
readonly id: string;
/**
* The update type name.
*/
readonly name: string;
}
export interface ParentWorkflowInfo {
workflowId: string;
runId: string;
namespace: string;
}
/**
* Not an actual error, used by the Workflow runtime to abort execution when {@link continueAsNew} is called
*/
@SymbolBasedInstanceOfError('ContinueAsNew')
export class ContinueAsNew extends Error {
constructor(public readonly command: coresdk.workflow_commands.IContinueAsNewWorkflowExecution) {
super('Workflow continued as new');
}
}
/**
* Options for continuing a Workflow as new
*/
export interface ContinueAsNewOptions {
/**
* A string representing the Workflow type name, e.g. the filename in the Node.js SDK or class name in Java
*/
workflowType?: string;
/**
* Task queue to continue the Workflow in
*/
taskQueue?: string;
/**
* Timeout for the entire Workflow run
* @format {@link https://www.npmjs.com/package/ms | ms-formatted string}
*/
workflowRunTimeout?: Duration;
/**
* Timeout for a single Workflow task
* @format {@link https://www.npmjs.com/package/ms | ms-formatted string}
*/
workflowTaskTimeout?: Duration;
/**
* Non-searchable attributes to attach to next Workflow run
*/
memo?: Record<string, unknown>;
/**
* Searchable attributes to attach to next Workflow run
*/
searchAttributes?: SearchAttributes;
/**
* When using the Worker Versioning feature, specifies whether this Workflow should
* Continue-as-New onto a worker with a compatible Build Id or not. See {@link VersioningIntent}.
*
* @default 'COMPATIBLE'
*
* @experimental
*/
versioningIntent?: VersioningIntent;
}
/**
* Specifies:
* - whether cancellation requests are sent to the Child
* - whether and when a {@link CanceledFailure} is thrown from {@link executeChild} or
* {@link ChildWorkflowHandle.result}
*
* @default {@link ChildWorkflowCancellationType.WAIT_CANCELLATION_COMPLETED}
*/
export type ChildWorkflowCancellationType =
(typeof ChildWorkflowCancellationType)[keyof typeof ChildWorkflowCancellationType];
export const ChildWorkflowCancellationType = {
/**
* Don't send a cancellation request to the Child.
*/
ABANDON: 'ABANDON',
/**
* Send a cancellation request to the Child. Immediately throw the error.
*/
TRY_CANCEL: 'TRY_CANCEL',
/**
* Send a cancellation request to the Child. The Child may respect cancellation, in which case an error will be thrown
* when cancellation has completed, and {@link isCancellation}(error) will be true. On the other hand, the Child may
* ignore the cancellation request, in which case an error might be thrown with a different cause, or the Child may
* complete successfully.
*
* @default
*/
WAIT_CANCELLATION_COMPLETED: 'WAIT_CANCELLATION_COMPLETED',
/**
* Send a cancellation request to the Child. Throw the error once the Server receives the Child cancellation request.
*/
WAIT_CANCELLATION_REQUESTED: 'WAIT_CANCELLATION_REQUESTED',
} as const;
// ts-prune-ignore-next
export const [encodeChildWorkflowCancellationType, decodeChildWorkflowCancellationType] = makeProtoEnumConverters<
coresdk.child_workflow.ChildWorkflowCancellationType,
typeof coresdk.child_workflow.ChildWorkflowCancellationType,
keyof typeof coresdk.child_workflow.ChildWorkflowCancellationType,
typeof ChildWorkflowCancellationType,
''
>(
{
[ChildWorkflowCancellationType.ABANDON]: 0,
[ChildWorkflowCancellationType.TRY_CANCEL]: 1,
[ChildWorkflowCancellationType.WAIT_CANCELLATION_COMPLETED]: 2,
[ChildWorkflowCancellationType.WAIT_CANCELLATION_REQUESTED]: 3,
} as const,
''
);
/**
* How a Child Workflow reacts to the Parent Workflow reaching a Closed state.
*
* @see {@link https://docs.temporal.io/concepts/what-is-a-parent-close-policy/ | Parent Close Policy}
*/
export type ParentClosePolicy = (typeof ParentClosePolicy)[keyof typeof ParentClosePolicy];
export const ParentClosePolicy = {
/**
* When the Parent is Closed, the Child is Terminated.
*
* @default
*/
TERMINATE: 'TERMINATE',
/**
* When the Parent is Closed, nothing is done to the Child.
*/
ABANDON: 'ABANDON',
/**
* When the Parent is Closed, the Child is Cancelled.
*/
REQUEST_CANCEL: 'REQUEST_CANCEL',
/// Anything below this line has been deprecated
/**
* If a `ParentClosePolicy` is set to this, or is not set at all, the server default value will be used.
*
* @deprecated Either leave property `undefined`, or set an explicit policy instead.
*/
PARENT_CLOSE_POLICY_UNSPECIFIED: undefined, // eslint-disable-line deprecation/deprecation
/**
* When the Parent is Closed, the Child is Terminated.
*
* @deprecated Use {@link ParentClosePolicy.TERMINATE} instead.
*/
PARENT_CLOSE_POLICY_TERMINATE: 'TERMINATE', // eslint-disable-line deprecation/deprecation
/**
* When the Parent is Closed, nothing is done to the Child.
*
* @deprecated Use {@link ParentClosePolicy.ABANDON} instead.
*/
PARENT_CLOSE_POLICY_ABANDON: 'ABANDON', // eslint-disable-line deprecation/deprecation
/**
* When the Parent is Closed, the Child is Cancelled.
*
* @deprecated Use {@link ParentClosePolicy.REQUEST_CANCEL} instead.
*/
PARENT_CLOSE_POLICY_REQUEST_CANCEL: 'REQUEST_CANCEL', // eslint-disable-line deprecation/deprecation
} as const;
// ts-prune-ignore-next
export const [encodeParentClosePolicy, decodeParentClosePolicy] = makeProtoEnumConverters<
coresdk.child_workflow.ParentClosePolicy,
typeof coresdk.child_workflow.ParentClosePolicy,
keyof typeof coresdk.child_workflow.ParentClosePolicy,
typeof ParentClosePolicy,
'PARENT_CLOSE_POLICY_'
>(
{
[ParentClosePolicy.TERMINATE]: 1,
[ParentClosePolicy.ABANDON]: 2,
[ParentClosePolicy.REQUEST_CANCEL]: 3,
UNSPECIFIED: 0,
} as const,
'PARENT_CLOSE_POLICY_'
);
export interface ChildWorkflowOptions extends CommonWorkflowOptions {
/**
* Workflow id to use when starting. If not specified a UUID is generated. Note that it is
* dangerous as in case of client side retries no deduplication will happen based on the
* generated id. So prefer assigning business meaningful ids if possible.
*/
workflowId?: string;
/**
* Task queue to use for Workflow tasks. It should match a task queue specified when creating a
* `Worker` that hosts the Workflow code.
*
* By default, a child is scheduled on the same Task Queue as the parent.
*/
taskQueue?: string;
/**
* Specifies:
* - whether cancellation requests are sent to the Child
* - whether and when an error is thrown from {@link executeChild} or
* {@link ChildWorkflowHandle.result}
*
* @default {@link ChildWorkflowCancellationType.WAIT_CANCELLATION_COMPLETED}
*/
cancellationType?: ChildWorkflowCancellationType;
/**
* Specifies how the Child reacts to the Parent Workflow reaching a Closed state.
*
* @default {@link ParentClosePolicy.PARENT_CLOSE_POLICY_TERMINATE}
*/
parentClosePolicy?: ParentClosePolicy;
/**
* When using the Worker Versioning feature, specifies whether this Child Workflow should run on
* a worker with a compatible Build Id or not. See {@link VersioningIntent}.
*
* @default 'COMPATIBLE'
*
* @experimental
*/
versioningIntent?: VersioningIntent;
}
export type RequiredChildWorkflowOptions = Required<Pick<ChildWorkflowOptions, 'workflowId' | 'cancellationType'>> & {
args: unknown[];
};
export type ChildWorkflowOptionsWithDefaults = ChildWorkflowOptions & RequiredChildWorkflowOptions;
export interface StackTraceSDKInfo {
name: string;
version: string;
}
/**
* Represents a slice of a file starting at lineOffset
*/
export interface StackTraceFileSlice {
/**
* Only used possible to trim the file without breaking syntax highlighting.
*/
line_offset: number;
/**
* slice of a file with `\n` (newline) line terminator.
*/
content: string;
}
/**
* A pointer to a location in a file
*/
export interface StackTraceFileLocation {
/**
* Path to source file (absolute or relative).
* When using a relative path, make sure all paths are relative to the same root.
*/
file_path?: string;
/**
* If possible, SDK should send this, required for displaying the code location.
*/
line?: number;
/**
* If possible, SDK should send this.
*/
column?: number;
/**
* Function name this line belongs to (if applicable).
* Used for falling back to stack trace view.
*/
function_name?: string;
/**
* Flag to mark this as internal SDK code and hide by default in the UI.
*/
internal_code: boolean;
}
export interface StackTrace {
locations: StackTraceFileLocation[];
}
/**
* Used as the result for the enhanced stack trace query
*/
export interface EnhancedStackTrace {
sdk: StackTraceSDKInfo;
/**
* Mapping of file path to file contents.
* SDK may choose to send no, some or all sources.
* Sources might be trimmed, and some time only the file(s) of the top element of the trace will be sent.
*/
sources: Record<string, StackTraceFileSlice[]>;
stacks: StackTrace[];
}
export interface WorkflowCreateOptions {
info: WorkflowInfo;
randomnessSeed: number[];
now: number;
showStackTraceSources: boolean;
}
export interface WorkflowCreateOptionsInternal extends WorkflowCreateOptions {
sourceMap: RawSourceMap;
registeredActivityNames: Set<string>;
getTimeOfDay(): bigint;
}
/**
* A handler function capable of accepting the arguments for a given UpdateDefinition, SignalDefinition or QueryDefinition.
*/
export type Handler<
Ret,
Args extends any[],
T extends UpdateDefinition<Ret, Args> | SignalDefinition<Args> | QueryDefinition<Ret, Args>,
> = T extends UpdateDefinition<infer R, infer A>
? (...args: A) => R | Promise<R>
: T extends SignalDefinition<infer A>
? (...args: A) => void | Promise<void>
: T extends QueryDefinition<infer R, infer A>
? (...args: A) => R
: never;
/**
* A handler function accepting signal calls for non-registered signal names.
*/
export type DefaultSignalHandler = (signalName: string, ...args: unknown[]) => void | Promise<void>;
/**
* A validation function capable of accepting the arguments for a given UpdateDefinition.
*/
export type UpdateValidator<Args extends any[]> = (...args: Args) => void;
/**
* A description of a query handler.
*/
export type QueryHandlerOptions = { description?: string };
/**
* A description of a signal handler.
*/
export type SignalHandlerOptions = { description?: string; unfinishedPolicy?: HandlerUnfinishedPolicy };
/**
* A validator and description of an update handler.
*/
export type UpdateHandlerOptions<Args extends any[]> = {
validator?: UpdateValidator<Args>;
description?: string;
unfinishedPolicy?: HandlerUnfinishedPolicy;
};
export interface ActivationCompletion {
commands: coresdk.workflow_commands.IWorkflowCommand[];
usedInternalFlags: number[];
}