@temporalio/client 1.8.5 → 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.
@@ -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 { Next, Headers };
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
  }
@@ -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 { ServiceError, WorkflowContinuedAsNewError, WorkflowFailedError, isGrpcServiceError } from './errors';
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 WorkflowExecutionCancelledError
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 = interceptors.length ? composeInterceptors(interceptors, 'terminate', next) : next;
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 = interceptors.length ? composeInterceptors(interceptors, 'cancel', next) : next;
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 = interceptors.length ? composeInterceptors(interceptors, 'describe', next) : next;
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 = interceptors.length ? composeInterceptors(interceptors, 'signal', next) : next;
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 = interceptors.length ? composeInterceptors(interceptors, 'query', next) : next;
1178
+ const fn = composeInterceptors(interceptors, 'query', next);
896
1179
  return fn({
897
1180
  workflowExecution: { workflowId, runId },
898
1181
  queryRejectCondition: this.client.options.queryRejectCondition,
@@ -1,10 +1,7 @@
1
- import {
2
- CommonWorkflowOptions,
3
- SignalDefinition,
4
- WithCompiledWorkflowOptions,
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[]]