@temporalio/common 1.3.0 → 1.4.1
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.
- package/lib/activity-options.d.ts +138 -0
- package/lib/activity-options.js +15 -0
- package/lib/activity-options.js.map +1 -0
- package/lib/converter/data-converter.d.ts +20 -1
- package/lib/converter/data-converter.js +14 -3
- package/lib/converter/data-converter.js.map +1 -1
- package/lib/converter/failure-converter.d.ts +75 -0
- package/lib/converter/failure-converter.js +239 -0
- package/lib/converter/failure-converter.js.map +1 -0
- package/lib/converter/payload-codec.d.ts +1 -1
- package/lib/converter/payload-converter.d.ts +85 -1
- package/lib/converter/payload-converter.js +210 -1
- package/lib/converter/payload-converter.js.map +1 -1
- package/lib/converter/protobuf-payload-converters.d.ts +3 -3
- package/lib/converter/protobuf-payload-converters.js +20 -19
- package/lib/converter/protobuf-payload-converters.js.map +1 -1
- package/lib/converter/types.d.ts +0 -6
- package/lib/converter/types.js +7 -18
- package/lib/converter/types.js.map +1 -1
- package/lib/deprecated-time.d.ts +52 -0
- package/lib/deprecated-time.js +106 -0
- package/lib/deprecated-time.js.map +1 -0
- package/lib/{converter/encoding.d.ts → encoding.d.ts} +8 -0
- package/lib/{converter/encoding.js → encoding.js} +15 -1
- package/lib/encoding.js.map +1 -0
- package/lib/errors.d.ts +47 -0
- package/lib/errors.js +68 -0
- package/lib/errors.js.map +1 -0
- package/lib/failure.d.ts +0 -27
- package/lib/failure.js +9 -205
- package/lib/failure.js.map +1 -1
- package/lib/index.d.ts +39 -8
- package/lib/index.js +64 -7
- package/lib/index.js.map +1 -1
- package/lib/interceptors.d.ts +18 -0
- package/lib/interceptors.js +24 -0
- package/lib/interceptors.js.map +1 -0
- package/lib/interfaces.d.ts +52 -0
- package/lib/interfaces.js +3 -0
- package/lib/interfaces.js.map +1 -0
- package/lib/internal-non-workflow/codec-helpers.d.ts +82 -0
- package/lib/internal-non-workflow/codec-helpers.js +295 -0
- package/lib/internal-non-workflow/codec-helpers.js.map +1 -0
- package/lib/internal-non-workflow/codec-types.d.ts +22 -0
- package/lib/internal-non-workflow/codec-types.js +3 -0
- package/lib/internal-non-workflow/codec-types.js.map +1 -0
- package/lib/internal-non-workflow/data-converter-helpers.d.ts +11 -0
- package/lib/internal-non-workflow/data-converter-helpers.js +66 -0
- package/lib/internal-non-workflow/data-converter-helpers.js.map +1 -0
- package/lib/internal-non-workflow/index.d.ts +10 -0
- package/lib/internal-non-workflow/index.js +27 -0
- package/lib/internal-non-workflow/index.js.map +1 -0
- package/lib/internal-non-workflow/tls-config.d.ts +32 -0
- package/lib/internal-non-workflow/tls-config.js +11 -0
- package/lib/internal-non-workflow/tls-config.js.map +1 -0
- package/lib/internal-non-workflow/utils.d.ts +4 -0
- package/lib/internal-non-workflow/utils.js +11 -0
- package/lib/internal-non-workflow/utils.js.map +1 -0
- package/lib/otel.d.ts +1 -1
- package/lib/otel.js +2 -2
- package/lib/otel.js.map +1 -1
- package/lib/retry-policy.d.ts +48 -0
- package/lib/retry-policy.js +62 -0
- package/lib/retry-policy.js.map +1 -0
- package/lib/time.d.ts +18 -0
- package/lib/time.js +79 -0
- package/lib/time.js.map +1 -0
- package/lib/type-helpers.d.ts +21 -0
- package/lib/type-helpers.js +46 -0
- package/lib/type-helpers.js.map +1 -0
- package/lib/workflow-handle.d.ts +27 -0
- package/lib/workflow-handle.js +3 -0
- package/lib/workflow-handle.js.map +1 -0
- package/lib/workflow-options.d.ts +118 -0
- package/lib/workflow-options.js +53 -0
- package/lib/workflow-options.js.map +1 -0
- package/package.json +5 -4
- package/src/activity-options.ts +159 -0
- package/src/converter/data-converter.ts +24 -3
- package/src/converter/failure-converter.ts +355 -0
- package/src/converter/payload-codec.ts +1 -1
- package/src/converter/payload-converter.ts +246 -1
- package/src/converter/protobuf-payload-converters.ts +14 -25
- package/src/converter/types.ts +6 -19
- package/src/deprecated-time.ts +80 -0
- package/src/{converter/encoding.ts → encoding.ts} +14 -0
- package/src/errors.ts +55 -0
- package/src/failure.ts +1 -251
- package/src/index.ts +55 -8
- package/src/interceptors.ts +32 -0
- package/src/interfaces.ts +64 -0
- package/src/internal-non-workflow/codec-helpers.ts +348 -0
- package/src/internal-non-workflow/codec-types.ts +34 -0
- package/src/internal-non-workflow/data-converter-helpers.ts +81 -0
- package/src/internal-non-workflow/index.ts +10 -0
- package/src/internal-non-workflow/tls-config.ts +35 -0
- package/src/internal-non-workflow/utils.ts +6 -0
- package/src/otel.ts +2 -2
- package/src/retry-policy.ts +101 -0
- package/src/time.ts +79 -0
- package/src/type-helpers.ts +64 -0
- package/src/workflow-handle.ts +30 -0
- package/src/workflow-options.ts +156 -0
- package/lib/converter/encoding.js.map +0 -1
- package/lib/converter/json-payload-converter.d.ts +0 -10
- package/lib/converter/json-payload-converter.js +0 -39
- package/lib/converter/json-payload-converter.js.map +0 -1
- package/lib/converter/payload-converters.d.ts +0 -67
- package/lib/converter/payload-converters.js +0 -124
- package/lib/converter/payload-converters.js.map +0 -1
- package/lib/converter/search-attribute-payload-converter.d.ts +0 -12
- package/lib/converter/search-attribute-payload-converter.js +0 -64
- package/lib/converter/search-attribute-payload-converter.js.map +0 -1
- package/src/converter/json-payload-converter.ts +0 -37
- package/src/converter/payload-converters.ts +0 -148
- package/src/converter/search-attribute-payload-converter.ts +0 -71
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
import type { coresdk } from '@temporalio/proto';
|
|
2
|
+
import { RetryPolicy } from './retry-policy';
|
|
3
|
+
import { checkExtends } from './type-helpers';
|
|
4
|
+
|
|
5
|
+
// Avoid importing the proto implementation to reduce workflow bundle size
|
|
6
|
+
// Copied from coresdk.workflow_commands.ActivityCancellationType
|
|
7
|
+
export enum ActivityCancellationType {
|
|
8
|
+
TRY_CANCEL = 0,
|
|
9
|
+
WAIT_CANCELLATION_COMPLETED = 1,
|
|
10
|
+
ABANDON = 2,
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
checkExtends<coresdk.workflow_commands.ActivityCancellationType, ActivityCancellationType>();
|
|
14
|
+
checkExtends<ActivityCancellationType, coresdk.workflow_commands.ActivityCancellationType>();
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Options for remote activity invocation
|
|
18
|
+
*/
|
|
19
|
+
export interface ActivityOptions {
|
|
20
|
+
/**
|
|
21
|
+
* Identifier to use for tracking the activity in Workflow history.
|
|
22
|
+
* The `activityId` can be accessed by the activity function.
|
|
23
|
+
* Does not need to be unique.
|
|
24
|
+
*
|
|
25
|
+
* @default an incremental sequence number
|
|
26
|
+
*/
|
|
27
|
+
activityId?: string;
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Task queue name.
|
|
31
|
+
*
|
|
32
|
+
* @default current worker task queue
|
|
33
|
+
*/
|
|
34
|
+
taskQueue?: string;
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Heartbeat interval. Activity must heartbeat before this interval passes after a last heartbeat or activity start.
|
|
38
|
+
* @format number of milliseconds or {@link https://www.npmjs.com/package/ms | ms-formatted string}
|
|
39
|
+
*/
|
|
40
|
+
heartbeatTimeout?: string | number;
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* RetryPolicy that define how activity is retried in case of failure. If this is not set, then the server-defined default activity retry policy will be used. To ensure zero retries, set maximum attempts to 1.
|
|
44
|
+
*/
|
|
45
|
+
retry?: RetryPolicy;
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Maximum time of a single Activity execution attempt.
|
|
49
|
+
Note that the Temporal Server doesn't detect Worker process failures directly. It relies on this timeout to detect that an Activity that didn't complete on time. So this timeout should be as short as the longest possible execution of the Activity body. Potentially long running Activities must specify {@link heartbeatTimeout} and call {@link activity.Context.heartbeat} periodically for timely failure detection.
|
|
50
|
+
|
|
51
|
+
* Either this option or {@link scheduleToCloseTimeout} is required.
|
|
52
|
+
* @format number of milliseconds or {@link https://www.npmjs.com/package/ms | ms-formatted string}
|
|
53
|
+
*/
|
|
54
|
+
startToCloseTimeout?: string | number;
|
|
55
|
+
/**
|
|
56
|
+
* Time that the Activity Task can stay in the Task Queue before it is picked up by a Worker. Do not specify this timeout unless using host specific Task Queues for Activity Tasks are being used for routing.
|
|
57
|
+
* `scheduleToStartTimeout` is always non-retryable. Retrying after this timeout doesn't make sense as it would just put the Activity Task back into the same Task Queue.
|
|
58
|
+
* @default unlimited
|
|
59
|
+
* @format number of milliseconds or {@link https://www.npmjs.com/package/ms | ms-formatted string}
|
|
60
|
+
*/
|
|
61
|
+
scheduleToStartTimeout?: string | number;
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Total time that a workflow is willing to wait for Activity to complete.
|
|
65
|
+
* `scheduleToCloseTimeout` limits the total time of an Activity's execution including retries (use {@link startToCloseTimeout} to limit the time of a single attempt).
|
|
66
|
+
*
|
|
67
|
+
* Either this option or {@link startToCloseTimeout} is required
|
|
68
|
+
* @default unlimited
|
|
69
|
+
* @format number of milliseconds or {@link https://www.npmjs.com/package/ms | ms-formatted string}
|
|
70
|
+
*/
|
|
71
|
+
scheduleToCloseTimeout?: string | number;
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Determines what the SDK does when the Activity is cancelled.
|
|
75
|
+
* - `TRY_CANCEL` - Initiate a cancellation request and immediately report cancellation to the workflow.
|
|
76
|
+
* - `WAIT_CANCELLATION_COMPLETED` - Wait for activity cancellation completion. Note that activity must heartbeat to receive a
|
|
77
|
+
* cancellation notification. This can block the cancellation for a long time if activity doesn't
|
|
78
|
+
* heartbeat or chooses to ignore the cancellation request.
|
|
79
|
+
* - `ABANDON` - Do not request cancellation of the activity and immediately report cancellation to the workflow.
|
|
80
|
+
*/
|
|
81
|
+
cancellationType?: ActivityCancellationType;
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Eager dispatch is an optimization that improves the throughput and load on the server for scheduling Activities.
|
|
85
|
+
* When used, the server will hand out Activity tasks back to the Worker when it completes a Workflow task.
|
|
86
|
+
* It is available from server version 1.17 behind the `system.enableActivityEagerExecution` feature flag.
|
|
87
|
+
*
|
|
88
|
+
* Eager dispatch will only be used if `allowEagerDispatch` is enabled (the default) and {@link taskQueue} is either
|
|
89
|
+
* omitted or the same as the current Workflow.
|
|
90
|
+
*
|
|
91
|
+
* @default true
|
|
92
|
+
*/
|
|
93
|
+
allowEagerDispatch?: boolean;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Options for local activity invocation
|
|
98
|
+
*/
|
|
99
|
+
export interface LocalActivityOptions {
|
|
100
|
+
/**
|
|
101
|
+
* RetryPolicy that defines how an activity is retried in case of failure. If this is not set, then the SDK-defined default activity retry policy will be used.
|
|
102
|
+
* Note that local activities are always executed at least once, even if maximum attempts is set to 1 due to Workflow task retries.
|
|
103
|
+
*/
|
|
104
|
+
retry?: RetryPolicy;
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Maximum time the local activity is allowed to execute after the task is dispatched. This
|
|
108
|
+
* timeout is always retryable.
|
|
109
|
+
*
|
|
110
|
+
* Either this option or {@link scheduleToCloseTimeout} is required.
|
|
111
|
+
* If set, this must be <= {@link scheduleToCloseTimeout}, otherwise, it will be clamped down.
|
|
112
|
+
*
|
|
113
|
+
* @format number of milliseconds or {@link https://www.npmjs.com/package/ms | ms-formatted string}
|
|
114
|
+
*/
|
|
115
|
+
startToCloseTimeout?: string | number;
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Limits time the local activity can idle internally before being executed. That can happen if
|
|
119
|
+
* the worker is currently at max concurrent local activity executions. This timeout is always
|
|
120
|
+
* non retryable as all a retry would achieve is to put it back into the same queue. Defaults
|
|
121
|
+
* to {@link scheduleToCloseTimeout} if not specified and that is set. Must be <=
|
|
122
|
+
* {@link scheduleToCloseTimeout} when set, otherwise, it will be clamped down.
|
|
123
|
+
*
|
|
124
|
+
* @default unlimited
|
|
125
|
+
* @format number of milliseconds or {@link https://www.npmjs.com/package/ms | ms-formatted string}
|
|
126
|
+
*/
|
|
127
|
+
scheduleToStartTimeout?: string | number;
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Indicates how long the caller is willing to wait for local activity completion. Limits how
|
|
131
|
+
* long retries will be attempted. When not specified defaults to the workflow execution
|
|
132
|
+
* timeout (which may be unset).
|
|
133
|
+
*
|
|
134
|
+
* Either this option or {@link startToCloseTimeout} is required.
|
|
135
|
+
*
|
|
136
|
+
* @default unlimited
|
|
137
|
+
* @format number of milliseconds or {@link https://www.npmjs.com/package/ms | ms-formatted string}
|
|
138
|
+
*/
|
|
139
|
+
scheduleToCloseTimeout?: string | number;
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* If the activity is retrying and backoff would exceed this value, a server side timer will be scheduled for the next attempt.
|
|
143
|
+
* Otherwise, backoff will happen internally in the SDK.
|
|
144
|
+
*
|
|
145
|
+
* @default 1 minute
|
|
146
|
+
* @format number of milliseconds or {@link https://www.npmjs.com/package/ms | ms-formatted string}
|
|
147
|
+
**/
|
|
148
|
+
localRetryThreshold?: string | number;
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* Determines what the SDK does when the Activity is cancelled.
|
|
152
|
+
* - `TRY_CANCEL` - Initiate a cancellation request and immediately report cancellation to the workflow.
|
|
153
|
+
* - `WAIT_CANCELLATION_COMPLETED` - Wait for activity cancellation completion. Note that activity must heartbeat to receive a
|
|
154
|
+
* cancellation notification. This can block the cancellation for a long time if activity doesn't
|
|
155
|
+
* heartbeat or chooses to ignore the cancellation request.
|
|
156
|
+
* - `ABANDON` - Do not request cancellation of the activity and immediately report cancellation to the workflow.
|
|
157
|
+
*/
|
|
158
|
+
cancellationType?: coresdk.workflow_commands.ActivityCancellationType;
|
|
159
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
+
import { DefaultFailureConverter, FailureConverter } from './failure-converter';
|
|
1
2
|
import { PayloadCodec } from './payload-codec';
|
|
2
|
-
import { PayloadConverter } from './payload-converter';
|
|
3
|
-
import { defaultPayloadConverter } from './payload-converters';
|
|
3
|
+
import { defaultPayloadConverter, PayloadConverter } from './payload-converter';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* When your data (arguments and return values) is sent over the wire and stored by Temporal Server, it is encoded in
|
|
@@ -29,11 +29,20 @@ import { defaultPayloadConverter } from './payload-converters';
|
|
|
29
29
|
export interface DataConverter {
|
|
30
30
|
/**
|
|
31
31
|
* Path of a file that has a `payloadConverter` named export.
|
|
32
|
-
* `payloadConverter` should be an
|
|
32
|
+
* `payloadConverter` should be an object that implements {@link PayloadConverter}.
|
|
33
33
|
* If no path is provided, {@link defaultPayloadConverter} is used.
|
|
34
34
|
*/
|
|
35
35
|
payloadConverterPath?: string;
|
|
36
36
|
|
|
37
|
+
/**
|
|
38
|
+
* Path of a file that has a `failureConverter` named export.
|
|
39
|
+
* `failureConverter` should be an object that implements {@link FailureConverter}.
|
|
40
|
+
* If no path is provided, {@link defaultFailureConverter} is used.
|
|
41
|
+
*
|
|
42
|
+
* @experimental
|
|
43
|
+
*/
|
|
44
|
+
failureConverterPath?: string;
|
|
45
|
+
|
|
37
46
|
/**
|
|
38
47
|
* An array of {@link PayloadCodec} instances.
|
|
39
48
|
*
|
|
@@ -49,10 +58,22 @@ export interface DataConverter {
|
|
|
49
58
|
*/
|
|
50
59
|
export interface LoadedDataConverter {
|
|
51
60
|
payloadConverter: PayloadConverter;
|
|
61
|
+
failureConverter: FailureConverter;
|
|
52
62
|
payloadCodecs: PayloadCodec[];
|
|
53
63
|
}
|
|
54
64
|
|
|
65
|
+
/**
|
|
66
|
+
* The default {@link FailureConverter} used by the SDK.
|
|
67
|
+
*
|
|
68
|
+
* Error messages and stack traces are serizalized as plain text.
|
|
69
|
+
*/
|
|
70
|
+
export const defaultFailureConverter: FailureConverter = new DefaultFailureConverter();
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* A "loaded" data converter that uses the default set of failure and payload converters.
|
|
74
|
+
*/
|
|
55
75
|
export const defaultDataConverter: LoadedDataConverter = {
|
|
56
76
|
payloadConverter: defaultPayloadConverter,
|
|
77
|
+
failureConverter: defaultFailureConverter,
|
|
57
78
|
payloadCodecs: [],
|
|
58
79
|
};
|
|
@@ -0,0 +1,355 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ActivityFailure,
|
|
3
|
+
ApplicationFailure,
|
|
4
|
+
CancelledFailure,
|
|
5
|
+
ChildWorkflowFailure,
|
|
6
|
+
FAILURE_SOURCE,
|
|
7
|
+
ProtoFailure,
|
|
8
|
+
RetryState,
|
|
9
|
+
ServerFailure,
|
|
10
|
+
TemporalFailure,
|
|
11
|
+
TerminatedFailure,
|
|
12
|
+
TimeoutFailure,
|
|
13
|
+
TimeoutType,
|
|
14
|
+
} from '../failure';
|
|
15
|
+
import { hasOwnProperties, isRecord } from '../type-helpers';
|
|
16
|
+
import {
|
|
17
|
+
arrayFromPayloads,
|
|
18
|
+
defaultPayloadConverter,
|
|
19
|
+
fromPayloadsAtIndex,
|
|
20
|
+
PayloadConverter,
|
|
21
|
+
toPayloads,
|
|
22
|
+
} from './payload-converter';
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Stack traces will be cutoff when on of these patterns is matched
|
|
26
|
+
*/
|
|
27
|
+
const CUTOFF_STACK_PATTERNS = [
|
|
28
|
+
/** Activity execution */
|
|
29
|
+
/\s+at Activity\.execute \(.*[\\/]worker[\\/](?:src|lib)[\\/]activity\.[jt]s:\d+:\d+\)/,
|
|
30
|
+
/** Workflow activation */
|
|
31
|
+
/\s+at Activator\.\S+NextHandler \(.*[\\/]workflow[\\/](?:src|lib)[\\/]internals\.[jt]s:\d+:\d+\)/,
|
|
32
|
+
/** Workflow run anything in context */
|
|
33
|
+
/\s+at Script\.runInContext \((?:node:vm|vm\.js):\d+:\d+\)/,
|
|
34
|
+
];
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Cuts out the framework part of a stack trace, leaving only user code entries
|
|
38
|
+
*/
|
|
39
|
+
export function cutoffStackTrace(stack?: string): string {
|
|
40
|
+
const lines = (stack ?? '').split(/\r?\n/);
|
|
41
|
+
const acc = Array<string>();
|
|
42
|
+
lineLoop: for (const line of lines) {
|
|
43
|
+
for (const pattern of CUTOFF_STACK_PATTERNS) {
|
|
44
|
+
if (pattern.test(line)) break lineLoop;
|
|
45
|
+
}
|
|
46
|
+
acc.push(line);
|
|
47
|
+
}
|
|
48
|
+
return acc.join('\n');
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* A `FailureConverter` is responsible to convert from proto `Failure` instances to JS `Errors` and back.
|
|
53
|
+
*
|
|
54
|
+
* It is recommended to use the {@link DefaultFailureConverter} and not attempt to customize the default implementation
|
|
55
|
+
* in order to maintain cross language failure serialization compatibility.
|
|
56
|
+
*
|
|
57
|
+
* @experimental
|
|
58
|
+
*/
|
|
59
|
+
export interface FailureConverter {
|
|
60
|
+
/**
|
|
61
|
+
* Converts a caught error to a Failure proto message.
|
|
62
|
+
*/
|
|
63
|
+
errorToFailure(err: unknown): ProtoFailure;
|
|
64
|
+
/**
|
|
65
|
+
* Converts a Failure proto message to a JS Error object.
|
|
66
|
+
*/
|
|
67
|
+
failureToError(err: ProtoFailure): TemporalFailure;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* The "shape" of the attributes set as the {@link ProtoFailure.encodedAttributes} payload in case
|
|
72
|
+
* {@link DefaultEncodedFailureAttributes.encodeCommonAttributes} is set to `true`.
|
|
73
|
+
*/
|
|
74
|
+
export interface DefaultEncodedFailureAttributes {
|
|
75
|
+
message: string;
|
|
76
|
+
stack_trace: string;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Options for the {@link DefaultFailureConverter} constructor.
|
|
81
|
+
*/
|
|
82
|
+
export interface DefaultFailureConverterOptions {
|
|
83
|
+
/**
|
|
84
|
+
* The {@link PayloadConverter} to use for converting failure attributes.
|
|
85
|
+
*/
|
|
86
|
+
payloadConverter: PayloadConverter;
|
|
87
|
+
/**
|
|
88
|
+
* Whether to encode error messages and stack traces (for encrypting these attributes use a {@link PayloadCodec}).
|
|
89
|
+
*/
|
|
90
|
+
encodeCommonAttributes: boolean;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Default cross language compatible failure converter.
|
|
95
|
+
*
|
|
96
|
+
* By default, it will leave error messages and stack traces as plain text. In order to encrypt those, set
|
|
97
|
+
* `encodeCommonAttributes` to `true` in the constructor options and make sure to use a {@link PayloadCodec} that can
|
|
98
|
+
* encrypt / decrypt payloads in your Worker and Client options.
|
|
99
|
+
*
|
|
100
|
+
* @experimental
|
|
101
|
+
*/
|
|
102
|
+
export class DefaultFailureConverter implements FailureConverter {
|
|
103
|
+
public readonly options: DefaultFailureConverterOptions;
|
|
104
|
+
|
|
105
|
+
constructor(options?: Partial<DefaultFailureConverterOptions>) {
|
|
106
|
+
const { encodeCommonAttributes, payloadConverter } = options ?? {};
|
|
107
|
+
this.options = {
|
|
108
|
+
encodeCommonAttributes: encodeCommonAttributes ?? false,
|
|
109
|
+
payloadConverter: payloadConverter ?? defaultPayloadConverter,
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Converts a Failure proto message to a JS Error object.
|
|
115
|
+
*
|
|
116
|
+
* Does not set common properties, that is done in {@link failureToError}.
|
|
117
|
+
*/
|
|
118
|
+
failureToErrorInner(failure: ProtoFailure): TemporalFailure {
|
|
119
|
+
if (failure.applicationFailureInfo) {
|
|
120
|
+
return new ApplicationFailure(
|
|
121
|
+
failure.message ?? undefined,
|
|
122
|
+
failure.applicationFailureInfo.type,
|
|
123
|
+
Boolean(failure.applicationFailureInfo.nonRetryable),
|
|
124
|
+
arrayFromPayloads(this.options.payloadConverter, failure.applicationFailureInfo.details?.payloads),
|
|
125
|
+
this.optionalFailureToOptionalError(failure.cause)
|
|
126
|
+
);
|
|
127
|
+
}
|
|
128
|
+
if (failure.serverFailureInfo) {
|
|
129
|
+
return new ServerFailure(
|
|
130
|
+
failure.message ?? undefined,
|
|
131
|
+
Boolean(failure.serverFailureInfo.nonRetryable),
|
|
132
|
+
this.optionalFailureToOptionalError(failure.cause)
|
|
133
|
+
);
|
|
134
|
+
}
|
|
135
|
+
if (failure.timeoutFailureInfo) {
|
|
136
|
+
return new TimeoutFailure(
|
|
137
|
+
failure.message ?? undefined,
|
|
138
|
+
fromPayloadsAtIndex(
|
|
139
|
+
this.options.payloadConverter,
|
|
140
|
+
0,
|
|
141
|
+
failure.timeoutFailureInfo.lastHeartbeatDetails?.payloads
|
|
142
|
+
),
|
|
143
|
+
failure.timeoutFailureInfo.timeoutType ?? TimeoutType.TIMEOUT_TYPE_UNSPECIFIED
|
|
144
|
+
);
|
|
145
|
+
}
|
|
146
|
+
if (failure.terminatedFailureInfo) {
|
|
147
|
+
return new TerminatedFailure(failure.message ?? undefined, this.optionalFailureToOptionalError(failure.cause));
|
|
148
|
+
}
|
|
149
|
+
if (failure.canceledFailureInfo) {
|
|
150
|
+
return new CancelledFailure(
|
|
151
|
+
failure.message ?? undefined,
|
|
152
|
+
arrayFromPayloads(this.options.payloadConverter, failure.canceledFailureInfo.details?.payloads),
|
|
153
|
+
this.optionalFailureToOptionalError(failure.cause)
|
|
154
|
+
);
|
|
155
|
+
}
|
|
156
|
+
if (failure.resetWorkflowFailureInfo) {
|
|
157
|
+
return new ApplicationFailure(
|
|
158
|
+
failure.message ?? undefined,
|
|
159
|
+
'ResetWorkflow',
|
|
160
|
+
false,
|
|
161
|
+
arrayFromPayloads(
|
|
162
|
+
this.options.payloadConverter,
|
|
163
|
+
failure.resetWorkflowFailureInfo.lastHeartbeatDetails?.payloads
|
|
164
|
+
),
|
|
165
|
+
this.optionalFailureToOptionalError(failure.cause)
|
|
166
|
+
);
|
|
167
|
+
}
|
|
168
|
+
if (failure.childWorkflowExecutionFailureInfo) {
|
|
169
|
+
const { namespace, workflowType, workflowExecution, retryState } = failure.childWorkflowExecutionFailureInfo;
|
|
170
|
+
if (!(workflowType?.name && workflowExecution)) {
|
|
171
|
+
throw new TypeError('Missing attributes on childWorkflowExecutionFailureInfo');
|
|
172
|
+
}
|
|
173
|
+
return new ChildWorkflowFailure(
|
|
174
|
+
namespace ?? undefined,
|
|
175
|
+
workflowExecution,
|
|
176
|
+
workflowType.name,
|
|
177
|
+
retryState ?? RetryState.RETRY_STATE_UNSPECIFIED,
|
|
178
|
+
this.optionalFailureToOptionalError(failure.cause)
|
|
179
|
+
);
|
|
180
|
+
}
|
|
181
|
+
if (failure.activityFailureInfo) {
|
|
182
|
+
if (!failure.activityFailureInfo.activityType?.name) {
|
|
183
|
+
throw new TypeError('Missing activityType?.name on activityFailureInfo');
|
|
184
|
+
}
|
|
185
|
+
return new ActivityFailure(
|
|
186
|
+
failure.activityFailureInfo.activityType.name,
|
|
187
|
+
failure.activityFailureInfo.activityId ?? undefined,
|
|
188
|
+
failure.activityFailureInfo.retryState ?? RetryState.RETRY_STATE_UNSPECIFIED,
|
|
189
|
+
failure.activityFailureInfo.identity ?? undefined,
|
|
190
|
+
this.optionalFailureToOptionalError(failure.cause)
|
|
191
|
+
);
|
|
192
|
+
}
|
|
193
|
+
return new TemporalFailure(failure.message ?? undefined, this.optionalFailureToOptionalError(failure.cause));
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
failureToError(failure: ProtoFailure): TemporalFailure {
|
|
197
|
+
if (failure.encodedAttributes) {
|
|
198
|
+
const attrs = this.options.payloadConverter.fromPayload<DefaultEncodedFailureAttributes>(
|
|
199
|
+
failure.encodedAttributes
|
|
200
|
+
);
|
|
201
|
+
// Don't apply encodedAttributes unless they conform to an expected schema
|
|
202
|
+
if (typeof attrs === 'object' && attrs !== null) {
|
|
203
|
+
const { message, stack_trace } = attrs;
|
|
204
|
+
// Avoid mutating the argument
|
|
205
|
+
failure = { ...failure };
|
|
206
|
+
if (typeof message === 'string') {
|
|
207
|
+
failure.message = message;
|
|
208
|
+
}
|
|
209
|
+
if (typeof stack_trace === 'string') {
|
|
210
|
+
failure.stackTrace = stack_trace;
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
const err = this.failureToErrorInner(failure);
|
|
215
|
+
err.stack = failure.stackTrace ?? '';
|
|
216
|
+
err.failure = failure;
|
|
217
|
+
return err;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
errorToFailure(err: unknown): ProtoFailure {
|
|
221
|
+
const failure = this.errorToFailureInner(err);
|
|
222
|
+
if (this.options.encodeCommonAttributes) {
|
|
223
|
+
const { message, stackTrace } = failure;
|
|
224
|
+
failure.message = 'Encoded failure';
|
|
225
|
+
failure.stackTrace = '';
|
|
226
|
+
failure.encodedAttributes = this.options.payloadConverter.toPayload({ message, stack_trace: stackTrace });
|
|
227
|
+
}
|
|
228
|
+
return failure;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
errorToFailureInner(err: unknown): ProtoFailure {
|
|
232
|
+
if (err instanceof TemporalFailure) {
|
|
233
|
+
if (err.failure) return err.failure;
|
|
234
|
+
const base = {
|
|
235
|
+
message: err.message,
|
|
236
|
+
stackTrace: cutoffStackTrace(err.stack),
|
|
237
|
+
cause: this.optionalErrorToOptionalFailure(err.cause),
|
|
238
|
+
source: FAILURE_SOURCE,
|
|
239
|
+
};
|
|
240
|
+
|
|
241
|
+
if (err instanceof ActivityFailure) {
|
|
242
|
+
return {
|
|
243
|
+
...base,
|
|
244
|
+
activityFailureInfo: {
|
|
245
|
+
...err,
|
|
246
|
+
activityType: { name: err.activityType },
|
|
247
|
+
},
|
|
248
|
+
};
|
|
249
|
+
}
|
|
250
|
+
if (err instanceof ChildWorkflowFailure) {
|
|
251
|
+
return {
|
|
252
|
+
...base,
|
|
253
|
+
childWorkflowExecutionFailureInfo: {
|
|
254
|
+
...err,
|
|
255
|
+
workflowExecution: err.execution,
|
|
256
|
+
workflowType: { name: err.workflowType },
|
|
257
|
+
},
|
|
258
|
+
};
|
|
259
|
+
}
|
|
260
|
+
if (err instanceof ApplicationFailure) {
|
|
261
|
+
return {
|
|
262
|
+
...base,
|
|
263
|
+
applicationFailureInfo: {
|
|
264
|
+
type: err.type,
|
|
265
|
+
nonRetryable: err.nonRetryable,
|
|
266
|
+
details:
|
|
267
|
+
err.details && err.details.length
|
|
268
|
+
? { payloads: toPayloads(this.options.payloadConverter, ...err.details) }
|
|
269
|
+
: undefined,
|
|
270
|
+
},
|
|
271
|
+
};
|
|
272
|
+
}
|
|
273
|
+
if (err instanceof CancelledFailure) {
|
|
274
|
+
return {
|
|
275
|
+
...base,
|
|
276
|
+
canceledFailureInfo: {
|
|
277
|
+
details:
|
|
278
|
+
err.details && err.details.length
|
|
279
|
+
? { payloads: toPayloads(this.options.payloadConverter, ...err.details) }
|
|
280
|
+
: undefined,
|
|
281
|
+
},
|
|
282
|
+
};
|
|
283
|
+
}
|
|
284
|
+
if (err instanceof TimeoutFailure) {
|
|
285
|
+
return {
|
|
286
|
+
...base,
|
|
287
|
+
timeoutFailureInfo: {
|
|
288
|
+
timeoutType: err.timeoutType,
|
|
289
|
+
lastHeartbeatDetails: err.lastHeartbeatDetails
|
|
290
|
+
? { payloads: toPayloads(this.options.payloadConverter, err.lastHeartbeatDetails) }
|
|
291
|
+
: undefined,
|
|
292
|
+
},
|
|
293
|
+
};
|
|
294
|
+
}
|
|
295
|
+
if (err instanceof TerminatedFailure) {
|
|
296
|
+
return {
|
|
297
|
+
...base,
|
|
298
|
+
terminatedFailureInfo: {},
|
|
299
|
+
};
|
|
300
|
+
}
|
|
301
|
+
if (err instanceof ServerFailure) {
|
|
302
|
+
return {
|
|
303
|
+
...base,
|
|
304
|
+
serverFailureInfo: { nonRetryable: err.nonRetryable },
|
|
305
|
+
};
|
|
306
|
+
}
|
|
307
|
+
// Just a TemporalFailure
|
|
308
|
+
return base;
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
const base = {
|
|
312
|
+
source: FAILURE_SOURCE,
|
|
313
|
+
};
|
|
314
|
+
|
|
315
|
+
if (isRecord(err) && hasOwnProperties(err, ['message', 'stack'])) {
|
|
316
|
+
return {
|
|
317
|
+
...base,
|
|
318
|
+
message: String(err.message) ?? '',
|
|
319
|
+
stackTrace: cutoffStackTrace(String(err.stack)),
|
|
320
|
+
cause: this.optionalErrorToOptionalFailure(err.cause),
|
|
321
|
+
};
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
const recommendation = ` [A non-Error value was thrown from your code. We recommend throwing Error objects so that we can provide a stack trace]`;
|
|
325
|
+
|
|
326
|
+
if (typeof err === 'string') {
|
|
327
|
+
return { ...base, message: err + recommendation };
|
|
328
|
+
}
|
|
329
|
+
if (typeof err === 'object') {
|
|
330
|
+
let message = '';
|
|
331
|
+
try {
|
|
332
|
+
message = JSON.stringify(err);
|
|
333
|
+
} catch (_err) {
|
|
334
|
+
message = String(err);
|
|
335
|
+
}
|
|
336
|
+
return { ...base, message: message + recommendation };
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
return { ...base, message: String(err) + recommendation };
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
/**
|
|
343
|
+
* Converts a Failure proto message to a JS Error object if defined or returns undefined.
|
|
344
|
+
*/
|
|
345
|
+
optionalFailureToOptionalError(failure: ProtoFailure | undefined | null): TemporalFailure | undefined {
|
|
346
|
+
return failure ? this.failureToError(failure) : undefined;
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
/**
|
|
350
|
+
* Converts an error to a Failure proto message if defined or returns undefined
|
|
351
|
+
*/
|
|
352
|
+
optionalErrorToOptionalFailure(err: unknown): ProtoFailure | undefined {
|
|
353
|
+
return err ? this.errorToFailure(err) : undefined;
|
|
354
|
+
}
|
|
355
|
+
}
|