@temporalio/client
Version:
Temporal.io SDK Client sub-package
138 lines • 7.11 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.executionInfoFromRaw = executionInfoFromRaw;
exports.decodeCountWorkflowExecutionsResponse = decodeCountWorkflowExecutionsResponse;
exports.rethrowKnownErrorTypes = rethrowKnownErrorTypes;
const grpc_js_1 = require("@grpc/grpc-js");
const common_1 = require("@temporalio/common");
const payload_search_attributes_1 = require("@temporalio/common/lib/converter/payload-search-attributes");
const time_1 = require("@temporalio/common/lib/time");
const codec_helpers_1 = require("@temporalio/common/lib/internal-non-workflow/codec-helpers");
const proto_1 = require("@temporalio/proto");
function workflowStatusCodeToName(code) {
return workflowStatusCodeToNameInternal(code) ?? 'UNKNOWN';
}
/**
* Intentionally leave out `default` branch to get compilation errors when new values are added
*/
function workflowStatusCodeToNameInternal(code) {
switch (code) {
case proto_1.temporal.api.enums.v1.WorkflowExecutionStatus.WORKFLOW_EXECUTION_STATUS_UNSPECIFIED:
return 'UNSPECIFIED';
case proto_1.temporal.api.enums.v1.WorkflowExecutionStatus.WORKFLOW_EXECUTION_STATUS_RUNNING:
return 'RUNNING';
case proto_1.temporal.api.enums.v1.WorkflowExecutionStatus.WORKFLOW_EXECUTION_STATUS_FAILED:
return 'FAILED';
case proto_1.temporal.api.enums.v1.WorkflowExecutionStatus.WORKFLOW_EXECUTION_STATUS_TIMED_OUT:
return 'TIMED_OUT';
case proto_1.temporal.api.enums.v1.WorkflowExecutionStatus.WORKFLOW_EXECUTION_STATUS_CANCELED:
return 'CANCELLED';
case proto_1.temporal.api.enums.v1.WorkflowExecutionStatus.WORKFLOW_EXECUTION_STATUS_TERMINATED:
return 'TERMINATED';
case proto_1.temporal.api.enums.v1.WorkflowExecutionStatus.WORKFLOW_EXECUTION_STATUS_COMPLETED:
return 'COMPLETED';
case proto_1.temporal.api.enums.v1.WorkflowExecutionStatus.WORKFLOW_EXECUTION_STATUS_CONTINUED_AS_NEW:
return 'CONTINUED_AS_NEW';
}
}
async function executionInfoFromRaw(raw, dataConverter, rawDataToEmbed) {
return {
/* eslint-disable @typescript-eslint/no-non-null-assertion */
type: raw.type.name,
workflowId: raw.execution.workflowId,
runId: raw.execution.runId,
taskQueue: raw.taskQueue,
status: {
code: raw.status,
name: workflowStatusCodeToName(raw.status),
},
// Safe to convert to number, max history length is 50k, which is much less than Number.MAX_SAFE_INTEGER
historyLength: raw.historyLength.toNumber(),
// Exact truncation for multi-petabyte histories
// historySize === 0 means WFT was generated by pre-1.20.0 server, and the history size is unknown
historySize: raw.historySizeBytes?.toNumber() || undefined,
startTime: (0, time_1.requiredTsToDate)(raw.startTime, 'startTime'),
executionTime: (0, time_1.optionalTsToDate)(raw.executionTime),
closeTime: (0, time_1.optionalTsToDate)(raw.closeTime),
memo: await (0, codec_helpers_1.decodeMapFromPayloads)(dataConverter, raw.memo?.fields),
searchAttributes: (0, payload_search_attributes_1.decodeSearchAttributes)(raw.searchAttributes?.indexedFields),
typedSearchAttributes: (0, payload_search_attributes_1.decodeTypedSearchAttributes)(raw.searchAttributes?.indexedFields),
parentExecution: raw.parentExecution
? {
workflowId: raw.parentExecution.workflowId,
runId: raw.parentExecution.runId,
}
: undefined,
rootExecution: raw.rootExecution
? {
workflowId: raw.rootExecution.workflowId,
runId: raw.rootExecution.runId,
}
: undefined,
raw: rawDataToEmbed,
priority: (0, common_1.decodePriority)(raw.priority),
};
}
function decodeCountWorkflowExecutionsResponse(raw) {
return {
// Note: lossy conversion of Long to number
count: raw.count.toNumber(),
groups: raw.groups.map((group) => {
return {
// Note: lossy conversion of Long to number
count: group.count.toNumber(),
groupValues: group.groupValues.map((value) => payload_search_attributes_1.searchAttributePayloadConverter.fromPayload(value)),
};
}),
};
}
/**
* If the error type can be determined based on embedded grpc error details,
* then rethrow the appropriate TypeScript error. Otherwise do nothing.
*
* This function should be used before falling back to generic error handling
* based on grpc error code. Very few error types are currently supported, but
* this function will be expanded over time as more server error types are added.
*/
function rethrowKnownErrorTypes(err) {
// We really don't expect multiple error details, but this really is an array, so just in case...
for (const entry of getGrpcStatusDetails(err) ?? []) {
if (!entry.type_url || !entry.value)
continue;
const type = entry.type_url.replace(/^type.googleapis.com\//, '');
switch (type) {
case 'temporal.api.errordetails.v1.NamespaceNotFoundFailure': {
const { namespace } = proto_1.temporal.api.errordetails.v1.NamespaceNotFoundFailure.decode(entry.value);
throw new common_1.NamespaceNotFoundError(namespace);
}
case 'temporal.api.errordetails.v1.MultiOperationExecutionFailure': {
// MultiOperationExecutionFailure contains error statuses for multiple
// operations. A MultiOperationExecutionAborted error status means that
// the corresponding operation was aborted due to an error in one of the
// other operations. We rethrow the first operation error that is not
// MultiOperationExecutionAborted.
const { statuses } = proto_1.temporal.api.errordetails.v1.MultiOperationExecutionFailure.decode(entry.value);
for (const status of statuses) {
const detail = status.details?.[0];
const statusType = detail?.type_url?.replace(/^type.googleapis.com\//, '');
if (statusType === 'temporal.api.failure.v1.MultiOperationExecutionAborted' ||
status.code === grpc_js_1.status.OK) {
continue;
}
err.message = status.message ?? err.message;
err.code = status.code || err.code;
err.details = detail?.value?.toString() || err.details;
throw err;
}
}
}
}
}
function getGrpcStatusDetails(err) {
const statusBuffer = err.metadata.get('grpc-status-details-bin')?.[0];
if (!statusBuffer || typeof statusBuffer === 'string') {
return undefined;
}
return proto_1.google.rpc.Status.decode(statusBuffer).details;
}
//# sourceMappingURL=helpers.js.map