UNPKG

@temporalio/common

Version:

Common library for code that's used across the Client, Worker, and/or Workflow

396 lines 17.8 kB
"use strict"; var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; var _a, _b, _c; Object.defineProperty(exports, "__esModule", { value: true }); exports.WorkflowExecutionAlreadyStartedError = exports.NexusOperationFailure = exports.ChildWorkflowFailure = exports.ActivityFailure = exports.TimeoutFailure = exports.TerminatedFailure = exports.CancelledFailure = exports.ApplicationFailure = exports.ServerFailure = exports.TemporalFailure = exports.decodeApplicationFailureCategory = exports.encodeApplicationFailureCategory = exports.ApplicationFailureCategory = exports.decodeRetryState = exports.encodeRetryState = exports.RetryState = exports.decodeTimeoutType = exports.encodeTimeoutType = exports.TimeoutType = exports.FAILURE_SOURCE = void 0; exports.ensureApplicationFailure = ensureApplicationFailure; exports.ensureTemporalFailure = ensureTemporalFailure; exports.rootCause = rootCause; const type_helpers_1 = require("./type-helpers"); const internal_workflow_1 = require("./internal-workflow"); exports.FAILURE_SOURCE = 'TypeScriptSDK'; exports.TimeoutType = { START_TO_CLOSE: 'START_TO_CLOSE', SCHEDULE_TO_START: 'SCHEDULE_TO_START', SCHEDULE_TO_CLOSE: 'SCHEDULE_TO_CLOSE', HEARTBEAT: 'HEARTBEAT', /** @deprecated Use {@link START_TO_CLOSE} instead. */ TIMEOUT_TYPE_START_TO_CLOSE: 'START_TO_CLOSE', /** @deprecated Use {@link SCHEDULE_TO_START} instead. */ TIMEOUT_TYPE_SCHEDULE_TO_START: 'SCHEDULE_TO_START', /** @deprecated Use {@link SCHEDULE_TO_CLOSE} instead. */ TIMEOUT_TYPE_SCHEDULE_TO_CLOSE: 'SCHEDULE_TO_CLOSE', /** @deprecated Use {@link HEARTBEAT} instead. */ TIMEOUT_TYPE_HEARTBEAT: 'HEARTBEAT', /** @deprecated Use `undefined` instead. */ TIMEOUT_TYPE_UNSPECIFIED: undefined, }; _a = (0, internal_workflow_1.makeProtoEnumConverters)({ [exports.TimeoutType.START_TO_CLOSE]: 1, [exports.TimeoutType.SCHEDULE_TO_START]: 2, [exports.TimeoutType.SCHEDULE_TO_CLOSE]: 3, [exports.TimeoutType.HEARTBEAT]: 4, UNSPECIFIED: 0, }, 'TIMEOUT_TYPE_'), exports.encodeTimeoutType = _a[0], exports.decodeTimeoutType = _a[1]; exports.RetryState = { IN_PROGRESS: 'IN_PROGRESS', NON_RETRYABLE_FAILURE: 'NON_RETRYABLE_FAILURE', TIMEOUT: 'TIMEOUT', MAXIMUM_ATTEMPTS_REACHED: 'MAXIMUM_ATTEMPTS_REACHED', RETRY_POLICY_NOT_SET: 'RETRY_POLICY_NOT_SET', INTERNAL_SERVER_ERROR: 'INTERNAL_SERVER_ERROR', CANCEL_REQUESTED: 'CANCEL_REQUESTED', /** @deprecated Use {@link IN_PROGRESS} instead. */ RETRY_STATE_IN_PROGRESS: 'IN_PROGRESS', /** @deprecated Use {@link NON_RETRYABLE_FAILURE} instead. */ RETRY_STATE_NON_RETRYABLE_FAILURE: 'NON_RETRYABLE_FAILURE', /** @deprecated Use {@link TIMEOUT} instead. */ RETRY_STATE_TIMEOUT: 'TIMEOUT', /** @deprecated Use {@link MAXIMUM_ATTEMPTS_REACHED} instead. */ RETRY_STATE_MAXIMUM_ATTEMPTS_REACHED: 'MAXIMUM_ATTEMPTS_REACHED', /** @deprecated Use {@link RETRY_POLICY_NOT_SET} instead. */ RETRY_STATE_RETRY_POLICY_NOT_SET: 'RETRY_POLICY_NOT_SET', /** @deprecated Use {@link INTERNAL_SERVER_ERROR} instead. */ RETRY_STATE_INTERNAL_SERVER_ERROR: 'INTERNAL_SERVER_ERROR', /** @deprecated Use {@link CANCEL_REQUESTED} instead. */ RETRY_STATE_CANCEL_REQUESTED: 'CANCEL_REQUESTED', /** @deprecated Use `undefined` instead. */ RETRY_STATE_UNSPECIFIED: undefined, }; _b = (0, internal_workflow_1.makeProtoEnumConverters)({ [exports.RetryState.IN_PROGRESS]: 1, [exports.RetryState.NON_RETRYABLE_FAILURE]: 2, [exports.RetryState.TIMEOUT]: 3, [exports.RetryState.MAXIMUM_ATTEMPTS_REACHED]: 4, [exports.RetryState.RETRY_POLICY_NOT_SET]: 5, [exports.RetryState.INTERNAL_SERVER_ERROR]: 6, [exports.RetryState.CANCEL_REQUESTED]: 7, UNSPECIFIED: 0, }, 'RETRY_STATE_'), exports.encodeRetryState = _b[0], exports.decodeRetryState = _b[1]; /** * A category to describe the severity and change the observability behavior of an application failure. * * Currently, observability behavior changes are limited to: * - activities that fail due to a BENIGN application failure emit DEBUG level logs and do not record metrics * * @experimental Category is a new feature and may be subject to change. */ exports.ApplicationFailureCategory = { BENIGN: 'BENIGN', }; _c = (0, internal_workflow_1.makeProtoEnumConverters)({ [exports.ApplicationFailureCategory.BENIGN]: 1, UNSPECIFIED: 0, }, 'APPLICATION_ERROR_CATEGORY_'), exports.encodeApplicationFailureCategory = _c[0], exports.decodeApplicationFailureCategory = _c[1]; /** * Represents failures that can cross Workflow and Activity boundaries. * * **Never extend this class or any of its children.** * * The only child class you should ever throw from your code is {@link ApplicationFailure}. */ let TemporalFailure = class TemporalFailure extends Error { cause; /** * The original failure that constructed this error. * * Only present if this error was generated from an external operation. */ failure; constructor(message, cause) { super(message ?? undefined); this.cause = cause; } }; exports.TemporalFailure = TemporalFailure; exports.TemporalFailure = TemporalFailure = __decorate([ (0, type_helpers_1.SymbolBasedInstanceOfError)('TemporalFailure') ], TemporalFailure); /** Exceptions originated at the Temporal service. */ let ServerFailure = class ServerFailure extends TemporalFailure { nonRetryable; constructor(message, nonRetryable, cause) { super(message, cause); this.nonRetryable = nonRetryable; } }; exports.ServerFailure = ServerFailure; exports.ServerFailure = ServerFailure = __decorate([ (0, type_helpers_1.SymbolBasedInstanceOfError)('ServerFailure') ], ServerFailure); /** * `ApplicationFailure`s are used to communicate application-specific failures in Workflows and Activities. * * The {@link type} property is matched against {@link RetryPolicy.nonRetryableErrorTypes} to determine if an instance * of this error is retryable. Another way to avoid retrying is by setting the {@link nonRetryable} flag to `true`. * * In Workflows, if you throw a non-`ApplicationFailure`, the Workflow Task will fail and be retried. If you throw an * `ApplicationFailure`, the Workflow Execution will fail. * * In Activities, you can either throw an `ApplicationFailure` or another `Error` to fail the Activity Task. In the * latter case, the `Error` will be converted to an `ApplicationFailure`. The conversion is done as following: * * - `type` is set to `error.constructor?.name ?? error.name` * - `message` is set to `error.message` * - `nonRetryable` is set to false * - `details` are set to null * - stack trace is copied from the original error * * When an {@link https://docs.temporal.io/concepts/what-is-an-activity-execution | Activity Execution} fails, the * `ApplicationFailure` from the last Activity Task will be the `cause` of the {@link ActivityFailure} thrown in the * Workflow. */ let ApplicationFailure = class ApplicationFailure extends TemporalFailure { type; nonRetryable; details; nextRetryDelay; category; /** * Alternatively, use {@link fromError} or {@link create}. */ constructor(message, type, nonRetryable, details, cause, nextRetryDelay, category) { super(message, cause); this.type = type; this.nonRetryable = nonRetryable; this.details = details; this.nextRetryDelay = nextRetryDelay; this.category = category; } /** * Create a new `ApplicationFailure` from an Error object. * * First calls {@link ensureApplicationFailure | `ensureApplicationFailure(error)`} and then overrides any fields * provided in `overrides`. */ static fromError(error, overrides) { const failure = ensureApplicationFailure(error); Object.assign(failure, overrides); return failure; } /** * Create a new `ApplicationFailure`. * * By default, will be retryable (unless its `type` is included in {@link RetryPolicy.nonRetryableErrorTypes}). */ static create(options) { const { message, type, nonRetryable = false, details, nextRetryDelay, cause, category } = options; return new this(message, type, nonRetryable, details, cause, nextRetryDelay, category); } /** * Get a new `ApplicationFailure` with the {@link nonRetryable} flag set to false. Note that this error will still * not be retried if its `type` is included in {@link RetryPolicy.nonRetryableErrorTypes}. * * @param message Optional error message * @param type Optional error type (used by {@link RetryPolicy.nonRetryableErrorTypes}) * @param details Optional details about the failure. Serialized by the Worker's {@link PayloadConverter}. */ static retryable(message, type, ...details) { return new this(message, type ?? 'Error', false, details); } /** * Get a new `ApplicationFailure` with the {@link nonRetryable} flag set to true. * * When thrown from an Activity or Workflow, the Activity or Workflow will not be retried (even if `type` is not * listed in {@link RetryPolicy.nonRetryableErrorTypes}). * * @param message Optional error message * @param type Optional error type * @param details Optional details about the failure. Serialized by the Worker's {@link PayloadConverter}. */ static nonRetryable(message, type, ...details) { return new this(message, type ?? 'Error', true, details); } }; exports.ApplicationFailure = ApplicationFailure; exports.ApplicationFailure = ApplicationFailure = __decorate([ (0, type_helpers_1.SymbolBasedInstanceOfError)('ApplicationFailure') ], ApplicationFailure); /** * This error is thrown when Cancellation has been requested. To allow Cancellation to happen, let it propagate. To * ignore Cancellation, catch it and continue executing. Note that Cancellation can only be requested a single time, so * your Workflow/Activity Execution will not receive further Cancellation requests. * * When a Workflow or Activity has been successfully cancelled, a `CancelledFailure` will be the `cause`. */ let CancelledFailure = class CancelledFailure extends TemporalFailure { details; constructor(message, details = [], cause) { super(message, cause); this.details = details; } }; exports.CancelledFailure = CancelledFailure; exports.CancelledFailure = CancelledFailure = __decorate([ (0, type_helpers_1.SymbolBasedInstanceOfError)('CancelledFailure') ], CancelledFailure); /** * Used as the `cause` when a Workflow has been terminated */ let TerminatedFailure = class TerminatedFailure extends TemporalFailure { constructor(message, cause) { super(message, cause); } }; exports.TerminatedFailure = TerminatedFailure; exports.TerminatedFailure = TerminatedFailure = __decorate([ (0, type_helpers_1.SymbolBasedInstanceOfError)('TerminatedFailure') ], TerminatedFailure); /** * Used to represent timeouts of Activities and Workflows */ let TimeoutFailure = class TimeoutFailure extends TemporalFailure { lastHeartbeatDetails; timeoutType; constructor(message, lastHeartbeatDetails, timeoutType) { super(message); this.lastHeartbeatDetails = lastHeartbeatDetails; this.timeoutType = timeoutType; } }; exports.TimeoutFailure = TimeoutFailure; exports.TimeoutFailure = TimeoutFailure = __decorate([ (0, type_helpers_1.SymbolBasedInstanceOfError)('TimeoutFailure') ], TimeoutFailure); /** * Contains information about an Activity failure. Always contains the original reason for the failure as its `cause`. * For example, if an Activity timed out, the cause will be a {@link TimeoutFailure}. * * This exception is expected to be thrown only by the framework code. */ let ActivityFailure = class ActivityFailure extends TemporalFailure { activityType; activityId; retryState; identity; constructor(message, activityType, activityId, retryState, identity, cause) { super(message, cause); this.activityType = activityType; this.activityId = activityId; this.retryState = retryState; this.identity = identity; } }; exports.ActivityFailure = ActivityFailure; exports.ActivityFailure = ActivityFailure = __decorate([ (0, type_helpers_1.SymbolBasedInstanceOfError)('ActivityFailure') ], ActivityFailure); /** * Contains information about a Child Workflow failure. Always contains the reason for the failure as its {@link cause}. * For example, if the Child was Terminated, the `cause` is a {@link TerminatedFailure}. * * This exception is expected to be thrown only by the framework code. */ let ChildWorkflowFailure = class ChildWorkflowFailure extends TemporalFailure { namespace; execution; workflowType; retryState; constructor(namespace, execution, workflowType, retryState, cause) { super('Child Workflow execution failed', cause); this.namespace = namespace; this.execution = execution; this.workflowType = workflowType; this.retryState = retryState; } }; exports.ChildWorkflowFailure = ChildWorkflowFailure; exports.ChildWorkflowFailure = ChildWorkflowFailure = __decorate([ (0, type_helpers_1.SymbolBasedInstanceOfError)('ChildWorkflowFailure') ], ChildWorkflowFailure); /** * Thrown when a Nexus Operation executed inside a Workflow fails. * * @experimental Nexus support in Temporal SDK is experimental. */ let NexusOperationFailure = class NexusOperationFailure extends TemporalFailure { scheduledEventId; endpoint; service; operation; operationToken; constructor(message, scheduledEventId, endpoint, service, operation, operationToken, cause) { super(message, cause); this.scheduledEventId = scheduledEventId; this.endpoint = endpoint; this.service = service; this.operation = operation; this.operationToken = operationToken; } }; exports.NexusOperationFailure = NexusOperationFailure; exports.NexusOperationFailure = NexusOperationFailure = __decorate([ (0, type_helpers_1.SymbolBasedInstanceOfError)('NexusOperationFailure') ], NexusOperationFailure); // TODO(nexus/error): Maybe add a NexusHandlerFailure class here, once we've decided on error handling. /** * This exception is thrown in the following cases: * - Workflow with the same Workflow ID is currently running and the {@link WorkflowOptions.workflowIdConflictPolicy} is `WORKFLOW_ID_CONFLICT_POLICY_FAIL` * - There is a closed Workflow with the same Workflow Id and the {@link WorkflowOptions.workflowIdReusePolicy} * is `WORKFLOW_ID_REUSE_POLICY_REJECT_DUPLICATE` * - There is closed Workflow in the `Completed` state with the same Workflow Id and the {@link WorkflowOptions.workflowIdReusePolicy} * is `WORKFLOW_ID_REUSE_POLICY_ALLOW_DUPLICATE_FAILED_ONLY` */ let WorkflowExecutionAlreadyStartedError = class WorkflowExecutionAlreadyStartedError extends TemporalFailure { workflowId; workflowType; constructor(message, workflowId, workflowType) { super(message); this.workflowId = workflowId; this.workflowType = workflowType; } }; exports.WorkflowExecutionAlreadyStartedError = WorkflowExecutionAlreadyStartedError; exports.WorkflowExecutionAlreadyStartedError = WorkflowExecutionAlreadyStartedError = __decorate([ (0, type_helpers_1.SymbolBasedInstanceOfError)('WorkflowExecutionAlreadyStartedError') ], WorkflowExecutionAlreadyStartedError); /** * If `error` is already an `ApplicationFailure`, returns `error`. * * Otherwise, converts `error` into an `ApplicationFailure` with: * * - `message`: `error.message` or `String(error)` * - `type`: `error.constructor.name` or `error.name` * - `stack`: `error.stack` or `''` */ function ensureApplicationFailure(error) { if (error instanceof ApplicationFailure) { return error; } const message = ((0, type_helpers_1.isRecord)(error) && String(error.message)) || String(error); const type = ((0, type_helpers_1.isRecord)(error) && (error.constructor?.name ?? error.name)) || undefined; const failure = ApplicationFailure.create({ message, type, nonRetryable: false }); failure.stack = ((0, type_helpers_1.isRecord)(error) && String(error.stack)) || ''; return failure; } /** * If `err` is an Error it is turned into an `ApplicationFailure`. * * If `err` was already a `TemporalFailure`, returns the original error. * * Otherwise returns an `ApplicationFailure` with `String(err)` as the message. */ function ensureTemporalFailure(err) { if (err instanceof TemporalFailure) { return err; } return ensureApplicationFailure(err); } /** * Get the root cause message of given `error`. * * In case `error` is a {@link TemporalFailure}, recurse the `cause` chain and return the root `cause.message`. * Otherwise, return `error.message`. */ function rootCause(error) { if (error instanceof TemporalFailure) { return error.cause ? rootCause(error.cause) : error.message; } return (0, type_helpers_1.errorMessage)(error); } //# sourceMappingURL=failure.js.map