@temporalio/client 1.8.6 → 1.9.0-rc.0
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/base-client.d.ts +11 -0
- package/lib/base-client.js +13 -0
- package/lib/base-client.js.map +1 -1
- package/lib/connection.d.ts +59 -10
- package/lib/connection.js +40 -13
- package/lib/connection.js.map +1 -1
- package/lib/errors.d.ts +8 -0
- package/lib/errors.js +15 -1
- package/lib/errors.js.map +1 -1
- package/lib/interceptors.d.ts +23 -2
- package/lib/types.d.ts +9 -0
- package/lib/workflow-client.d.ts +104 -6
- package/lib/workflow-client.js +127 -5
- package/lib/workflow-client.js.map +1 -1
- package/lib/workflow-options.d.ts +20 -1
- package/lib/workflow-options.js +13 -0
- package/lib/workflow-options.js.map +1 -1
- package/package.json +4 -4
- package/src/base-client.ts +14 -0
- package/src/connection.ts +86 -21
- package/src/errors.ts +11 -0
- package/src/interceptors.ts +28 -2
- package/src/types.ts +10 -0
- package/src/workflow-client.ts +292 -9
- package/src/workflow-options.ts +37 -7
package/src/interceptors.ts
CHANGED
|
@@ -13,9 +13,9 @@ import {
|
|
|
13
13
|
TerminateWorkflowExecutionResponse,
|
|
14
14
|
WorkflowExecution,
|
|
15
15
|
} from './types';
|
|
16
|
-
import { CompiledWorkflowOptions } from './workflow-options';
|
|
16
|
+
import { CompiledWorkflowOptions, WorkflowUpdateOptions } from './workflow-options';
|
|
17
17
|
|
|
18
|
-
export {
|
|
18
|
+
export { Headers, Next };
|
|
19
19
|
|
|
20
20
|
/** Input for WorkflowClientInterceptor.start */
|
|
21
21
|
export interface WorkflowStartInput {
|
|
@@ -25,6 +25,23 @@ export interface WorkflowStartInput {
|
|
|
25
25
|
readonly options: CompiledWorkflowOptions;
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
+
/** Input for WorkflowClientInterceptor.update */
|
|
29
|
+
export interface WorkflowStartUpdateInput {
|
|
30
|
+
readonly updateName: string;
|
|
31
|
+
readonly args: unknown[];
|
|
32
|
+
readonly workflowExecution: WorkflowExecution;
|
|
33
|
+
readonly firstExecutionRunId?: string;
|
|
34
|
+
readonly headers: Headers;
|
|
35
|
+
readonly options: WorkflowUpdateOptions;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/** Output for WorkflowClientInterceptor.startUpdate */
|
|
39
|
+
export interface WorkflowStartUpdateOutput {
|
|
40
|
+
readonly updateId: string;
|
|
41
|
+
readonly workflowRunId: string;
|
|
42
|
+
readonly outcome?: temporal.api.update.v1.IOutcome;
|
|
43
|
+
}
|
|
44
|
+
|
|
28
45
|
/** Input for WorkflowClientInterceptor.signal */
|
|
29
46
|
export interface WorkflowSignalInput {
|
|
30
47
|
readonly signalName: string;
|
|
@@ -81,6 +98,15 @@ export interface WorkflowClientInterceptor {
|
|
|
81
98
|
* {@link signalWithStart} most likely needs to be implemented too
|
|
82
99
|
*/
|
|
83
100
|
start?: (input: WorkflowStartInput, next: Next<this, 'start'>) => Promise<string /* runId */>;
|
|
101
|
+
/**
|
|
102
|
+
* Intercept a service call to updateWorkflowExecution
|
|
103
|
+
*
|
|
104
|
+
* @experimental Update is an experimental feature.
|
|
105
|
+
*/
|
|
106
|
+
startUpdate?: (
|
|
107
|
+
input: WorkflowStartUpdateInput,
|
|
108
|
+
next: Next<this, 'startUpdate'>
|
|
109
|
+
) => Promise<WorkflowStartUpdateOutput>;
|
|
84
110
|
/**
|
|
85
111
|
* Intercept a service call to signalWorkflowExecution
|
|
86
112
|
*
|
package/src/types.ts
CHANGED
|
@@ -82,6 +82,8 @@ export interface CallContext {
|
|
|
82
82
|
* Metadata to set on gRPC requests
|
|
83
83
|
*/
|
|
84
84
|
metadata?: Metadata;
|
|
85
|
+
|
|
86
|
+
abortSignal?: AbortSignal;
|
|
85
87
|
}
|
|
86
88
|
|
|
87
89
|
/**
|
|
@@ -105,4 +107,12 @@ export interface ConnectionLike {
|
|
|
105
107
|
* @returns returned value of `fn`
|
|
106
108
|
*/
|
|
107
109
|
withMetadata<R>(metadata: Metadata, fn: () => Promise<R>): Promise<R>;
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Set an {@link https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal | `AbortSignal`} that, when aborted,
|
|
113
|
+
* cancels any ongoing requests executed in `fn`'s scope.
|
|
114
|
+
*
|
|
115
|
+
* @returns value returned from `fn`
|
|
116
|
+
*/
|
|
117
|
+
withAbortSignal<R>(abortSignal: AbortSignal, fn: () => Promise<R>): Promise<R>;
|
|
108
118
|
}
|
package/src/workflow-client.ts
CHANGED
|
@@ -10,6 +10,7 @@ import {
|
|
|
10
10
|
RetryState,
|
|
11
11
|
searchAttributePayloadConverter,
|
|
12
12
|
SignalDefinition,
|
|
13
|
+
UpdateDefinition,
|
|
13
14
|
TerminatedFailure,
|
|
14
15
|
TimeoutFailure,
|
|
15
16
|
TimeoutType,
|
|
@@ -32,7 +33,13 @@ import {
|
|
|
32
33
|
filterNullAndUndefined,
|
|
33
34
|
} from '@temporalio/common/lib/internal-non-workflow';
|
|
34
35
|
import { temporal } from '@temporalio/proto';
|
|
35
|
-
import {
|
|
36
|
+
import {
|
|
37
|
+
ServiceError,
|
|
38
|
+
WorkflowContinuedAsNewError,
|
|
39
|
+
WorkflowFailedError,
|
|
40
|
+
WorkflowUpdateFailedError,
|
|
41
|
+
isGrpcServiceError,
|
|
42
|
+
} from './errors';
|
|
36
43
|
import {
|
|
37
44
|
WorkflowCancelInput,
|
|
38
45
|
WorkflowClientInterceptor,
|
|
@@ -43,6 +50,8 @@ import {
|
|
|
43
50
|
WorkflowSignalWithStartInput,
|
|
44
51
|
WorkflowStartInput,
|
|
45
52
|
WorkflowTerminateInput,
|
|
53
|
+
WorkflowStartUpdateInput,
|
|
54
|
+
WorkflowStartUpdateOutput,
|
|
46
55
|
} from './interceptors';
|
|
47
56
|
import {
|
|
48
57
|
DescribeWorkflowExecutionResponse,
|
|
@@ -60,6 +69,7 @@ import {
|
|
|
60
69
|
WorkflowOptions,
|
|
61
70
|
WorkflowSignalWithStartOptions,
|
|
62
71
|
WorkflowStartOptions,
|
|
72
|
+
WorkflowUpdateOptions,
|
|
63
73
|
} from './workflow-options';
|
|
64
74
|
import { executionInfoFromRaw, rethrowKnownErrorTypes } from './helpers';
|
|
65
75
|
import {
|
|
@@ -77,8 +87,9 @@ import { mapAsyncIterable } from './iterators-utils';
|
|
|
77
87
|
*
|
|
78
88
|
* Given the following Workflow definition:
|
|
79
89
|
* ```ts
|
|
80
|
-
* export const incrementSignal = defineSignal('increment');
|
|
90
|
+
* export const incrementSignal = defineSignal<[number]>('increment');
|
|
81
91
|
* export const getValueQuery = defineQuery<number>('getValue');
|
|
92
|
+
* export const incrementAndGetValueUpdate = defineUpdate<number, [number]>('incrementAndGetValue');
|
|
82
93
|
* export async function counterWorkflow(initialValue: number): Promise<void>;
|
|
83
94
|
* ```
|
|
84
95
|
*
|
|
@@ -92,12 +103,76 @@ import { mapAsyncIterable } from './iterators-utils';
|
|
|
92
103
|
* taskQueue: 'tutorial',
|
|
93
104
|
* });
|
|
94
105
|
* await handle.signal(incrementSignal, 2);
|
|
95
|
-
* await handle.query(getValueQuery); // 4
|
|
106
|
+
* const queryResult = await handle.query(getValueQuery); // 4
|
|
107
|
+
* const firstUpdateResult = await handle.executeUpdate(incrementAndGetValueUpdate, { args: [2] }); // 6
|
|
108
|
+
* const secondUpdateHandle = await handle.startUpdate(incrementAndGetValueUpdate, { args: [2] });
|
|
109
|
+
* const secondUpdateResult = await secondUpdateHandle.result(); // 8
|
|
96
110
|
* await handle.cancel();
|
|
97
|
-
* await handle.result(); // throws
|
|
111
|
+
* await handle.result(); // throws a WorkflowFailedError with `cause` set to a CancelledFailure.
|
|
98
112
|
* ```
|
|
99
113
|
*/
|
|
100
114
|
export interface WorkflowHandle<T extends Workflow = Workflow> extends BaseWorkflowHandle<T> {
|
|
115
|
+
/**
|
|
116
|
+
* Start an Update and wait for the result.
|
|
117
|
+
*
|
|
118
|
+
* @experimental Update is an experimental feature.
|
|
119
|
+
*
|
|
120
|
+
* @throws {@link WorkflowUpdateFailedError} if Update validation fails or if ApplicationFailure is thrown in the Update handler.
|
|
121
|
+
*
|
|
122
|
+
* @param def an Update definition as returned from {@link defineUpdate}
|
|
123
|
+
* @param options Update arguments
|
|
124
|
+
*
|
|
125
|
+
* @example
|
|
126
|
+
* ```ts
|
|
127
|
+
* const updateResult = await handle.executeUpdate(incrementAndGetValueUpdate, { args: [2] });
|
|
128
|
+
* ```
|
|
129
|
+
*/
|
|
130
|
+
executeUpdate<Ret, Args extends [any, ...any[]], Name extends string = string>(
|
|
131
|
+
def: UpdateDefinition<Ret, Args, Name> | string,
|
|
132
|
+
options: WorkflowUpdateOptions & { args: Args }
|
|
133
|
+
): Promise<Ret>;
|
|
134
|
+
|
|
135
|
+
executeUpdate<Ret, Args extends [], Name extends string = string>(
|
|
136
|
+
def: UpdateDefinition<Ret, Args, Name> | string,
|
|
137
|
+
options?: WorkflowUpdateOptions & { args?: Args }
|
|
138
|
+
): Promise<Ret>;
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Start an Update and receive a handle to the Update.
|
|
142
|
+
* The Update validator (if present) is run before the handle is returned.
|
|
143
|
+
*
|
|
144
|
+
* @experimental Update is an experimental feature.
|
|
145
|
+
*
|
|
146
|
+
* @throws {@link WorkflowUpdateFailedError} if Update validation fails.
|
|
147
|
+
*
|
|
148
|
+
* @param def an Update definition as returned from {@link defineUpdate}
|
|
149
|
+
* @param options Update arguments
|
|
150
|
+
*
|
|
151
|
+
* @example
|
|
152
|
+
* ```ts
|
|
153
|
+
* const updateHandle = await handle.startUpdate(incrementAndGetValueUpdate, { args: [2] });
|
|
154
|
+
* const updateResult = await updateHandle.result();
|
|
155
|
+
* ```
|
|
156
|
+
*/
|
|
157
|
+
startUpdate<Ret, Args extends [any, ...any[]], Name extends string = string>(
|
|
158
|
+
def: UpdateDefinition<Ret, Args, Name> | string,
|
|
159
|
+
options: WorkflowUpdateOptions & { args: Args }
|
|
160
|
+
): Promise<WorkflowUpdateHandle<Ret>>;
|
|
161
|
+
|
|
162
|
+
startUpdate<Ret, Args extends [], Name extends string = string>(
|
|
163
|
+
def: UpdateDefinition<Ret, Args, Name> | string,
|
|
164
|
+
options?: WorkflowUpdateOptions & { args?: Args }
|
|
165
|
+
): Promise<WorkflowUpdateHandle<Ret>>;
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* Get a handle to an Update.
|
|
169
|
+
*/
|
|
170
|
+
getUpdateHandle<Ret>(
|
|
171
|
+
updateId: string,
|
|
172
|
+
workflowId: string,
|
|
173
|
+
options?: GetWorkflowUpdateHandleOptions
|
|
174
|
+
): WorkflowUpdateHandle<Ret>;
|
|
175
|
+
|
|
101
176
|
/**
|
|
102
177
|
* Query a running or completed Workflow.
|
|
103
178
|
*
|
|
@@ -230,6 +305,9 @@ export interface WorkflowResultOptions {
|
|
|
230
305
|
followRuns?: boolean;
|
|
231
306
|
}
|
|
232
307
|
|
|
308
|
+
/**
|
|
309
|
+
* Options for {@link WorkflowClient.getHandle}
|
|
310
|
+
*/
|
|
233
311
|
export interface GetWorkflowHandleOptions extends WorkflowResultOptions {
|
|
234
312
|
/**
|
|
235
313
|
* ID of the first execution in the Workflow execution chain.
|
|
@@ -268,6 +346,42 @@ export interface AsyncWorkflowListIterable extends AsyncIterable<WorkflowExecuti
|
|
|
268
346
|
intoHistories: (intoHistoriesOptions?: IntoHistoriesOptions) => AsyncIterable<HistoryAndWorkflowId>;
|
|
269
347
|
}
|
|
270
348
|
|
|
349
|
+
/**
|
|
350
|
+
* A client-side handle to an Update.
|
|
351
|
+
*/
|
|
352
|
+
export interface WorkflowUpdateHandle<Ret> {
|
|
353
|
+
/**
|
|
354
|
+
* The ID of this Update request.
|
|
355
|
+
*/
|
|
356
|
+
updateId: string;
|
|
357
|
+
|
|
358
|
+
/**
|
|
359
|
+
* The ID of the Workflow being targeted by this Update request.
|
|
360
|
+
*/
|
|
361
|
+
workflowId: string;
|
|
362
|
+
|
|
363
|
+
/**
|
|
364
|
+
* The ID of the Run of the Workflow being targeted by this Update request.
|
|
365
|
+
*/
|
|
366
|
+
workflowRunId?: string;
|
|
367
|
+
|
|
368
|
+
/**
|
|
369
|
+
* Return the result of the Update.
|
|
370
|
+
* @throws {@link WorkflowUpdateFailedError} if ApplicationFailure is thrown in the Update handler.
|
|
371
|
+
*/
|
|
372
|
+
result(): Promise<Ret>;
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
/**
|
|
376
|
+
* Options for {@link WorkflowHandle.getUpdateHandle}
|
|
377
|
+
*/
|
|
378
|
+
export interface GetWorkflowUpdateHandleOptions {
|
|
379
|
+
/**
|
|
380
|
+
* The ID of the Run of the Workflow targeted by the Update.
|
|
381
|
+
*/
|
|
382
|
+
workflowRunId?: string;
|
|
383
|
+
}
|
|
384
|
+
|
|
271
385
|
/**
|
|
272
386
|
* Options for {@link WorkflowClient.list}
|
|
273
387
|
*/
|
|
@@ -640,6 +754,116 @@ export class WorkflowClient extends BaseClient {
|
|
|
640
754
|
return await decodeFromPayloadsAtIndex(this.dataConverter, 0, response.queryResult?.payloads);
|
|
641
755
|
}
|
|
642
756
|
|
|
757
|
+
/**
|
|
758
|
+
* Start the Update.
|
|
759
|
+
*
|
|
760
|
+
* Used as the final function of the interceptor chain during startUpdate and executeUpdate.
|
|
761
|
+
*/
|
|
762
|
+
protected async _startUpdateHandler(
|
|
763
|
+
waitForStage: temporal.api.enums.v1.UpdateWorkflowExecutionLifecycleStage,
|
|
764
|
+
input: WorkflowStartUpdateInput
|
|
765
|
+
): Promise<WorkflowStartUpdateOutput> {
|
|
766
|
+
const updateId = input.options?.updateId ?? uuid4();
|
|
767
|
+
const req: temporal.api.workflowservice.v1.IUpdateWorkflowExecutionRequest = {
|
|
768
|
+
namespace: this.options.namespace,
|
|
769
|
+
workflowExecution: input.workflowExecution,
|
|
770
|
+
firstExecutionRunId: input.firstExecutionRunId,
|
|
771
|
+
waitPolicy: { lifecycleStage: waitForStage },
|
|
772
|
+
request: {
|
|
773
|
+
meta: {
|
|
774
|
+
updateId,
|
|
775
|
+
identity: this.options.identity,
|
|
776
|
+
},
|
|
777
|
+
input: {
|
|
778
|
+
header: { fields: input.headers },
|
|
779
|
+
name: input.updateName,
|
|
780
|
+
args: { payloads: await encodeToPayloads(this.dataConverter, ...input.args) },
|
|
781
|
+
},
|
|
782
|
+
},
|
|
783
|
+
};
|
|
784
|
+
let response: temporal.api.workflowservice.v1.UpdateWorkflowExecutionResponse;
|
|
785
|
+
|
|
786
|
+
try {
|
|
787
|
+
response = await this.workflowService.updateWorkflowExecution(req);
|
|
788
|
+
} catch (err) {
|
|
789
|
+
this.rethrowGrpcError(err, 'Workflow Update failed', input.workflowExecution);
|
|
790
|
+
}
|
|
791
|
+
return {
|
|
792
|
+
updateId,
|
|
793
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
794
|
+
workflowRunId: response.updateRef!.workflowExecution!.runId!,
|
|
795
|
+
outcome: response.outcome ?? undefined,
|
|
796
|
+
};
|
|
797
|
+
}
|
|
798
|
+
|
|
799
|
+
protected createWorkflowUpdateHandle<Ret>(
|
|
800
|
+
updateId: string,
|
|
801
|
+
workflowId: string,
|
|
802
|
+
options?: GetWorkflowUpdateHandleOptions,
|
|
803
|
+
outcome?: temporal.api.update.v1.IOutcome
|
|
804
|
+
): WorkflowUpdateHandle<Ret> {
|
|
805
|
+
const workflowRunId = options?.workflowRunId;
|
|
806
|
+
return {
|
|
807
|
+
updateId,
|
|
808
|
+
workflowId,
|
|
809
|
+
workflowRunId,
|
|
810
|
+
result: async () => {
|
|
811
|
+
const completedOutcome =
|
|
812
|
+
outcome ?? (await this._pollForUpdateOutcome(updateId, { workflowId, runId: workflowRunId }));
|
|
813
|
+
if (completedOutcome.failure) {
|
|
814
|
+
throw new WorkflowUpdateFailedError(
|
|
815
|
+
'Workflow Update failed',
|
|
816
|
+
await decodeOptionalFailureToOptionalError(this.dataConverter, completedOutcome.failure)
|
|
817
|
+
);
|
|
818
|
+
} else {
|
|
819
|
+
return await decodeFromPayloadsAtIndex<Ret>(this.dataConverter, 0, completedOutcome.success?.payloads);
|
|
820
|
+
}
|
|
821
|
+
},
|
|
822
|
+
};
|
|
823
|
+
}
|
|
824
|
+
|
|
825
|
+
/**
|
|
826
|
+
* Poll Update until a response with an outcome is received; return that outcome.
|
|
827
|
+
* This is used directly; no interceptor is available.
|
|
828
|
+
*/
|
|
829
|
+
protected async _pollForUpdateOutcome(
|
|
830
|
+
updateId: string,
|
|
831
|
+
workflowExecution: temporal.api.common.v1.IWorkflowExecution
|
|
832
|
+
): Promise<temporal.api.update.v1.IOutcome> {
|
|
833
|
+
const req: temporal.api.workflowservice.v1.IPollWorkflowExecutionUpdateRequest = {
|
|
834
|
+
namespace: this.options.namespace,
|
|
835
|
+
updateRef: { workflowExecution, updateId },
|
|
836
|
+
identity: this.options.identity,
|
|
837
|
+
waitPolicy: {
|
|
838
|
+
lifecycleStage:
|
|
839
|
+
temporal.api.enums.v1.UpdateWorkflowExecutionLifecycleStage
|
|
840
|
+
.UPDATE_WORKFLOW_EXECUTION_LIFECYCLE_STAGE_COMPLETED,
|
|
841
|
+
},
|
|
842
|
+
};
|
|
843
|
+
|
|
844
|
+
// TODO: Users should be able to use client.withDeadline(timestamp) with a
|
|
845
|
+
// Date (as opposed to a duration) to control the total amount of time
|
|
846
|
+
// allowed for polling. However, this requires a server change such that the
|
|
847
|
+
// server swallows the gRPC timeout and instead responds with a well-formed
|
|
848
|
+
// PollWorkflowExecutionUpdateResponse, indicating that the requested
|
|
849
|
+
// lifecycle stage has not yet been reached at the time of the deadline
|
|
850
|
+
// expiry. See https://github.com/temporalio/temporal/issues/4742
|
|
851
|
+
|
|
852
|
+
// TODO: When temporal#4742 is released, stop catching DEADLINE_EXCEEDED.
|
|
853
|
+
for (;;) {
|
|
854
|
+
try {
|
|
855
|
+
const response = await this.workflowService.pollWorkflowExecutionUpdate(req);
|
|
856
|
+
if (response.outcome) {
|
|
857
|
+
return response.outcome;
|
|
858
|
+
}
|
|
859
|
+
} catch (err) {
|
|
860
|
+
if (!(isGrpcServiceError(err) && err.code === grpcStatus.DEADLINE_EXCEEDED)) {
|
|
861
|
+
throw err;
|
|
862
|
+
}
|
|
863
|
+
}
|
|
864
|
+
}
|
|
865
|
+
}
|
|
866
|
+
|
|
643
867
|
/**
|
|
644
868
|
* Uses given input to make a signalWorkflowExecution call to the service
|
|
645
869
|
*
|
|
@@ -688,6 +912,7 @@ export class WorkflowClient extends BaseClient {
|
|
|
688
912
|
workflowExecutionTimeout: options.workflowExecutionTimeout,
|
|
689
913
|
workflowRunTimeout: options.workflowRunTimeout,
|
|
690
914
|
workflowTaskTimeout: options.workflowTaskTimeout,
|
|
915
|
+
workflowStartDelay: options.startDelay,
|
|
691
916
|
retryPolicy: options.retry ? compileRetryPolicy(options.retry) : undefined,
|
|
692
917
|
memo: options.memo ? { fields: await encodeMapToPayloads(this.dataConverter, options.memo) } : undefined,
|
|
693
918
|
searchAttributes: options.searchAttributes
|
|
@@ -735,6 +960,7 @@ export class WorkflowClient extends BaseClient {
|
|
|
735
960
|
workflowExecutionTimeout: opts.workflowExecutionTimeout,
|
|
736
961
|
workflowRunTimeout: opts.workflowRunTimeout,
|
|
737
962
|
workflowTaskTimeout: opts.workflowTaskTimeout,
|
|
963
|
+
workflowStartDelay: opts.startDelay,
|
|
738
964
|
retryPolicy: opts.retry ? compileRetryPolicy(opts.retry) : undefined,
|
|
739
965
|
memo: opts.memo ? { fields: await encodeMapToPayloads(this.dataConverter, opts.memo) } : undefined,
|
|
740
966
|
searchAttributes: opts.searchAttributes
|
|
@@ -829,6 +1055,33 @@ export class WorkflowClient extends BaseClient {
|
|
|
829
1055
|
runIdForResult,
|
|
830
1056
|
...resultOptions
|
|
831
1057
|
}: WorkflowHandleOptions): WorkflowHandle<T> {
|
|
1058
|
+
// TODO (dan): Convert to class with this as a protected method
|
|
1059
|
+
const _startUpdate = async <Ret, Args extends unknown[]>(
|
|
1060
|
+
def: UpdateDefinition<Ret, Args> | string,
|
|
1061
|
+
waitForStage: temporal.api.enums.v1.UpdateWorkflowExecutionLifecycleStage,
|
|
1062
|
+
options?: WorkflowUpdateOptions & { args?: Args }
|
|
1063
|
+
): Promise<WorkflowUpdateHandle<Ret>> => {
|
|
1064
|
+
const next = this._startUpdateHandler.bind(this, waitForStage);
|
|
1065
|
+
const fn = composeInterceptors(interceptors, 'startUpdate', next);
|
|
1066
|
+
const { args, ...opts } = options ?? {};
|
|
1067
|
+
const input = {
|
|
1068
|
+
workflowExecution: { workflowId, runId },
|
|
1069
|
+
firstExecutionRunId,
|
|
1070
|
+
updateName: typeof def === 'string' ? def : def.name,
|
|
1071
|
+
args: args ?? [],
|
|
1072
|
+
waitForStage,
|
|
1073
|
+
headers: {},
|
|
1074
|
+
options: opts,
|
|
1075
|
+
};
|
|
1076
|
+
const output = await fn(input);
|
|
1077
|
+
return this.createWorkflowUpdateHandle<Ret>(
|
|
1078
|
+
output.updateId,
|
|
1079
|
+
input.workflowExecution.workflowId,
|
|
1080
|
+
{ workflowRunId: output.workflowRunId },
|
|
1081
|
+
output.outcome
|
|
1082
|
+
);
|
|
1083
|
+
};
|
|
1084
|
+
|
|
832
1085
|
return {
|
|
833
1086
|
client: this,
|
|
834
1087
|
workflowId,
|
|
@@ -837,7 +1090,7 @@ export class WorkflowClient extends BaseClient {
|
|
|
837
1090
|
},
|
|
838
1091
|
async terminate(reason?: string) {
|
|
839
1092
|
const next = this.client._terminateWorkflowHandler.bind(this.client);
|
|
840
|
-
const fn =
|
|
1093
|
+
const fn = composeInterceptors(interceptors, 'terminate', next);
|
|
841
1094
|
return await fn({
|
|
842
1095
|
workflowExecution: { workflowId, runId },
|
|
843
1096
|
reason,
|
|
@@ -846,7 +1099,7 @@ export class WorkflowClient extends BaseClient {
|
|
|
846
1099
|
},
|
|
847
1100
|
async cancel() {
|
|
848
1101
|
const next = this.client._cancelWorkflowHandler.bind(this.client);
|
|
849
|
-
const fn =
|
|
1102
|
+
const fn = composeInterceptors(interceptors, 'cancel', next);
|
|
850
1103
|
return await fn({
|
|
851
1104
|
workflowExecution: { workflowId, runId },
|
|
852
1105
|
firstExecutionRunId,
|
|
@@ -854,7 +1107,7 @@ export class WorkflowClient extends BaseClient {
|
|
|
854
1107
|
},
|
|
855
1108
|
async describe() {
|
|
856
1109
|
const next = this.client._describeWorkflowHandler.bind(this.client);
|
|
857
|
-
const fn =
|
|
1110
|
+
const fn = composeInterceptors(interceptors, 'describe', next);
|
|
858
1111
|
const raw = await fn({
|
|
859
1112
|
workflowExecution: { workflowId, runId },
|
|
860
1113
|
});
|
|
@@ -880,9 +1133,39 @@ export class WorkflowClient extends BaseClient {
|
|
|
880
1133
|
}
|
|
881
1134
|
return temporal.api.history.v1.History.create({ events });
|
|
882
1135
|
},
|
|
1136
|
+
async startUpdate<Ret, Args extends any[]>(
|
|
1137
|
+
def: UpdateDefinition<Ret, Args> | string,
|
|
1138
|
+
options?: WorkflowUpdateOptions & { args?: Args }
|
|
1139
|
+
): Promise<WorkflowUpdateHandle<Ret>> {
|
|
1140
|
+
return await _startUpdate(
|
|
1141
|
+
def,
|
|
1142
|
+
temporal.api.enums.v1.UpdateWorkflowExecutionLifecycleStage
|
|
1143
|
+
.UPDATE_WORKFLOW_EXECUTION_LIFECYCLE_STAGE_ACCEPTED,
|
|
1144
|
+
options
|
|
1145
|
+
);
|
|
1146
|
+
},
|
|
1147
|
+
async executeUpdate<Ret, Args extends any[]>(
|
|
1148
|
+
def: UpdateDefinition<Ret, Args> | string,
|
|
1149
|
+
options?: WorkflowUpdateOptions & { args?: Args }
|
|
1150
|
+
): Promise<Ret> {
|
|
1151
|
+
const handle = await _startUpdate(
|
|
1152
|
+
def,
|
|
1153
|
+
temporal.api.enums.v1.UpdateWorkflowExecutionLifecycleStage
|
|
1154
|
+
.UPDATE_WORKFLOW_EXECUTION_LIFECYCLE_STAGE_COMPLETED,
|
|
1155
|
+
options
|
|
1156
|
+
);
|
|
1157
|
+
return await handle.result();
|
|
1158
|
+
},
|
|
1159
|
+
getUpdateHandle<Ret>(
|
|
1160
|
+
updateId: string,
|
|
1161
|
+
workflowId: string,
|
|
1162
|
+
options?: GetWorkflowUpdateHandleOptions
|
|
1163
|
+
): WorkflowUpdateHandle<Ret> {
|
|
1164
|
+
return this.client.createWorkflowUpdateHandle(updateId, workflowId, options);
|
|
1165
|
+
},
|
|
883
1166
|
async signal<Args extends any[]>(def: SignalDefinition<Args> | string, ...args: Args): Promise<void> {
|
|
884
1167
|
const next = this.client._signalWorkflowHandler.bind(this.client);
|
|
885
|
-
const fn =
|
|
1168
|
+
const fn = composeInterceptors(interceptors, 'signal', next);
|
|
886
1169
|
await fn({
|
|
887
1170
|
workflowExecution: { workflowId, runId },
|
|
888
1171
|
signalName: typeof def === 'string' ? def : def.name,
|
|
@@ -892,7 +1175,7 @@ export class WorkflowClient extends BaseClient {
|
|
|
892
1175
|
},
|
|
893
1176
|
async query<Ret, Args extends any[]>(def: QueryDefinition<Ret, Args> | string, ...args: Args): Promise<Ret> {
|
|
894
1177
|
const next = this.client._queryWorkflowHandler.bind(this.client);
|
|
895
|
-
const fn =
|
|
1178
|
+
const fn = composeInterceptors(interceptors, 'query', next);
|
|
896
1179
|
return fn({
|
|
897
1180
|
workflowExecution: { workflowId, runId },
|
|
898
1181
|
queryRejectCondition: this.client.options.queryRejectCondition,
|
package/src/workflow-options.ts
CHANGED
|
@@ -1,10 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
WithWorkflowArgs,
|
|
6
|
-
Workflow,
|
|
7
|
-
} from '@temporalio/common';
|
|
1
|
+
import { CommonWorkflowOptions, SignalDefinition, WithWorkflowArgs, Workflow } from '@temporalio/common';
|
|
2
|
+
import { Duration, msOptionalToTs } from '@temporalio/common/lib/time';
|
|
3
|
+
import { Replace } from '@temporalio/common/lib/type-helpers';
|
|
4
|
+
import { google } from '@temporalio/proto';
|
|
8
5
|
|
|
9
6
|
export * from '@temporalio/common/lib/workflow-options';
|
|
10
7
|
|
|
@@ -37,6 +34,39 @@ export interface WorkflowOptions extends CommonWorkflowOptions {
|
|
|
37
34
|
* @default true
|
|
38
35
|
*/
|
|
39
36
|
followRuns?: boolean;
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Amount of time to wait before starting the workflow.
|
|
40
|
+
*
|
|
41
|
+
* @experimental
|
|
42
|
+
*/
|
|
43
|
+
startDelay?: Duration;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export type WithCompiledWorkflowOptions<T extends WorkflowOptions> = Replace<
|
|
47
|
+
T,
|
|
48
|
+
{
|
|
49
|
+
workflowExecutionTimeout?: google.protobuf.IDuration;
|
|
50
|
+
workflowRunTimeout?: google.protobuf.IDuration;
|
|
51
|
+
workflowTaskTimeout?: google.protobuf.IDuration;
|
|
52
|
+
startDelay?: google.protobuf.IDuration;
|
|
53
|
+
}
|
|
54
|
+
>;
|
|
55
|
+
|
|
56
|
+
export function compileWorkflowOptions<T extends WorkflowOptions>(options: T): WithCompiledWorkflowOptions<T> {
|
|
57
|
+
const { workflowExecutionTimeout, workflowRunTimeout, workflowTaskTimeout, startDelay, ...rest } = options;
|
|
58
|
+
|
|
59
|
+
return {
|
|
60
|
+
...rest,
|
|
61
|
+
workflowExecutionTimeout: msOptionalToTs(workflowExecutionTimeout),
|
|
62
|
+
workflowRunTimeout: msOptionalToTs(workflowRunTimeout),
|
|
63
|
+
workflowTaskTimeout: msOptionalToTs(workflowTaskTimeout),
|
|
64
|
+
startDelay: msOptionalToTs(startDelay),
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export interface WorkflowUpdateOptions {
|
|
69
|
+
readonly updateId?: string;
|
|
40
70
|
}
|
|
41
71
|
|
|
42
72
|
export type WorkflowSignalWithStartOptions<SignalArgs extends any[] = []> = SignalArgs extends [any, ...any[]]
|