@temporalio/client 1.11.3 → 1.11.5

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.
Files changed (59) hide show
  1. package/lib/async-completion-client.js +4 -4
  2. package/lib/async-completion-client.js.map +1 -1
  3. package/lib/base-client.d.ts +2 -3
  4. package/lib/base-client.js +4 -4
  5. package/lib/base-client.js.map +1 -1
  6. package/lib/build-id-types.js +1 -2
  7. package/lib/build-id-types.js.map +1 -1
  8. package/lib/client.d.ts +3 -4
  9. package/lib/client.js +1 -0
  10. package/lib/client.js.map +1 -1
  11. package/lib/connection.d.ts +2 -4
  12. package/lib/connection.js +5 -5
  13. package/lib/connection.js.map +1 -1
  14. package/lib/errors.d.ts +15 -0
  15. package/lib/errors.js +36 -2
  16. package/lib/errors.js.map +1 -1
  17. package/lib/grpc-retry.js +4 -5
  18. package/lib/grpc-retry.js.map +1 -1
  19. package/lib/helpers.js +2 -3
  20. package/lib/helpers.js.map +1 -1
  21. package/lib/iterators-utils.js +1 -2
  22. package/lib/iterators-utils.js.map +1 -1
  23. package/lib/schedule-client.js +7 -5
  24. package/lib/schedule-client.js.map +1 -1
  25. package/lib/schedule-helpers.d.ts +1 -3
  26. package/lib/schedule-helpers.js +14 -27
  27. package/lib/schedule-helpers.js.map +1 -1
  28. package/lib/schedule-types.d.ts +17 -14
  29. package/lib/schedule-types.js +27 -18
  30. package/lib/schedule-types.js.map +1 -1
  31. package/lib/task-queue-client.d.ts +12 -1
  32. package/lib/task-queue-client.js +23 -38
  33. package/lib/task-queue-client.js.map +1 -1
  34. package/lib/types.d.ts +17 -3
  35. package/lib/types.js +22 -1
  36. package/lib/types.js.map +1 -1
  37. package/lib/workflow-client.d.ts +6 -6
  38. package/lib/workflow-client.js +20 -36
  39. package/lib/workflow-client.js.map +1 -1
  40. package/lib/workflow-options.d.ts +2 -1
  41. package/lib/workflow-options.js +1 -2
  42. package/lib/workflow-options.js.map +1 -1
  43. package/lib/workflow-update-stage.d.ts +12 -8
  44. package/lib/workflow-update-stage.js +18 -17
  45. package/lib/workflow-update-stage.js.map +1 -1
  46. package/package.json +4 -4
  47. package/src/async-completion-client.ts +4 -5
  48. package/src/base-client.ts +2 -2
  49. package/src/client.ts +4 -4
  50. package/src/connection.ts +2 -2
  51. package/src/errors.ts +34 -1
  52. package/src/schedule-client.ts +7 -6
  53. package/src/schedule-helpers.ts +2 -17
  54. package/src/schedule-types.ts +35 -22
  55. package/src/task-queue-client.ts +37 -38
  56. package/src/types.ts +38 -2
  57. package/src/workflow-client.ts +35 -28
  58. package/src/workflow-options.ts +2 -1
  59. package/src/workflow-update-stage.ts +29 -21
package/src/errors.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { ServiceError as GrpcServiceError } from '@grpc/grpc-js';
1
+ import { ServiceError as GrpcServiceError, status } from '@grpc/grpc-js';
2
2
  import { RetryState, TemporalFailure } from '@temporalio/common';
3
3
  import { isError, isRecord, SymbolBasedInstanceOfError } from '@temporalio/common/lib/type-helpers';
4
4
 
@@ -79,6 +79,9 @@ export class WorkflowContinuedAsNewError extends Error {
79
79
  }
80
80
  }
81
81
 
82
+ /**
83
+ * Returns true if the provided error is a {@link GrpcServiceError}.
84
+ */
82
85
  export function isGrpcServiceError(err: unknown): err is GrpcServiceError {
83
86
  return (
84
87
  isError(err) &&
@@ -87,6 +90,36 @@ export function isGrpcServiceError(err: unknown): err is GrpcServiceError {
87
90
  );
88
91
  }
89
92
 
93
+ /**
94
+ * Returns true if the provided error or its cause is a {@link GrpcServiceError} with code DEADLINE_EXCEEDED.
95
+ *
96
+ * @see {@link Connection.withDeadline}
97
+ */
98
+ export function isGrpcDeadlineError(err: unknown): err is Error {
99
+ while (isError(err)) {
100
+ if (isGrpcServiceError(err) && (err as GrpcServiceError).code === status.DEADLINE_EXCEEDED) {
101
+ return true;
102
+ }
103
+ err = (err as any).cause;
104
+ }
105
+ return false;
106
+ }
107
+
108
+ /**
109
+ * Returns true if the provided error or its cause is a {@link GrpcServiceError} with code CANCELLED.
110
+ *
111
+ * @see {@link Connection.withAbortSignal}
112
+ */
113
+ export function isGrpcCancelledError(err: unknown): err is Error {
114
+ while (isError(err)) {
115
+ if (isGrpcServiceError(err) && (err as GrpcServiceError).code === status.CANCELLED) {
116
+ return true;
117
+ }
118
+ err = (err as any).cause;
119
+ }
120
+ return false;
121
+ }
122
+
90
123
  /**
91
124
  * @deprecated Use `isGrpcServiceError` instead
92
125
  */
@@ -29,17 +29,17 @@ import {
29
29
  ScheduleUpdateOptions,
30
30
  ScheduleOptionsAction,
31
31
  ScheduleOptionsStartWorkflowAction,
32
+ encodeScheduleOverlapPolicy,
33
+ decodeScheduleOverlapPolicy,
32
34
  } from './schedule-types';
33
35
  import {
34
36
  compileScheduleOptions,
35
37
  compileUpdatedScheduleOptions,
36
- decodeOverlapPolicy,
37
38
  decodeScheduleAction,
38
39
  decodeScheduleRecentActions,
39
40
  decodeScheduleRunningActions,
40
41
  decodeScheduleSpec,
41
42
  decodeSearchAttributes,
42
- encodeOverlapPolicy,
43
43
  encodeScheduleAction,
44
44
  encodeSchedulePolicies,
45
45
  encodeScheduleSpec,
@@ -251,7 +251,7 @@ export class ScheduleClient extends BaseClient {
251
251
  ? opts.state.backfill.map((x) => ({
252
252
  startTime: optionalDateToTs(x.start),
253
253
  endTime: optionalDateToTs(x.end),
254
- overlapPolicy: x.overlap ? encodeOverlapPolicy(x.overlap) : undefined,
254
+ overlapPolicy: x.overlap ? encodeScheduleOverlapPolicy(x.overlap) : undefined,
255
255
  }))
256
256
  : undefined,
257
257
  },
@@ -427,7 +427,8 @@ export class ScheduleClient extends BaseClient {
427
427
  memo: await decodeMapFromPayloads(this.client.dataConverter, raw.memo?.fields),
428
428
  searchAttributes: decodeSearchAttributes(raw.searchAttributes),
429
429
  policies: {
430
- overlap: decodeOverlapPolicy(raw.schedule.policies?.overlapPolicy),
430
+ // 'overlap' should never be missing on describe, as the server will replace UNSPECIFIED by an actual value
431
+ overlap: decodeScheduleOverlapPolicy(raw.schedule.policies?.overlapPolicy) ?? ScheduleOverlapPolicy.SKIP,
431
432
  catchupWindow: optionalTsToMs(raw.schedule.policies?.catchupWindow) ?? 60_000,
432
433
  pauseOnFailure: raw.schedule.policies?.pauseOnFailure === true,
433
434
  },
@@ -485,7 +486,7 @@ export class ScheduleClient extends BaseClient {
485
486
  await this.client._patchSchedule(this.scheduleId, {
486
487
  triggerImmediately: {
487
488
  overlapPolicy: overlap
488
- ? encodeOverlapPolicy(overlap)
489
+ ? encodeScheduleOverlapPolicy(overlap)
489
490
  : temporal.api.enums.v1.ScheduleOverlapPolicy.SCHEDULE_OVERLAP_POLICY_ALLOW_ALL,
490
491
  },
491
492
  });
@@ -497,7 +498,7 @@ export class ScheduleClient extends BaseClient {
497
498
  backfillRequest: backfills.map((x) => ({
498
499
  startTime: optionalDateToTs(x.start),
499
500
  endTime: optionalDateToTs(x.end),
500
- overlapPolicy: x.overlap ? encodeOverlapPolicy(x.overlap) : undefined,
501
+ overlapPolicy: x.overlap ? encodeScheduleOverlapPolicy(x.overlap) : undefined,
501
502
  })),
502
503
  });
503
504
  },
@@ -32,7 +32,6 @@ import {
32
32
  CompiledScheduleUpdateOptions,
33
33
  Range,
34
34
  ScheduleOptions,
35
- ScheduleOverlapPolicy,
36
35
  ScheduleUpdateOptions,
37
36
  DayOfWeek,
38
37
  DAYS_OF_WEEK,
@@ -47,6 +46,7 @@ import {
47
46
  ScheduleExecutionActionResult,
48
47
  ScheduleExecutionResult,
49
48
  ScheduleExecutionStartWorkflowActionResult,
49
+ encodeScheduleOverlapPolicy,
50
50
  } from './schedule-types';
51
51
 
52
52
  const [encodeSecond, decodeSecond] = makeCalendarSpecFieldCoders(
@@ -192,21 +192,6 @@ export function decodeOptionalStructuredCalendarSpecs(
192
192
  );
193
193
  }
194
194
 
195
- export function encodeOverlapPolicy(input: ScheduleOverlapPolicy): temporal.api.enums.v1.ScheduleOverlapPolicy {
196
- return temporal.api.enums.v1.ScheduleOverlapPolicy[
197
- `SCHEDULE_OVERLAP_POLICY_${ScheduleOverlapPolicy[input] as keyof typeof ScheduleOverlapPolicy}`
198
- ];
199
- }
200
-
201
- export function decodeOverlapPolicy(input?: temporal.api.enums.v1.ScheduleOverlapPolicy | null): ScheduleOverlapPolicy {
202
- if (!input) return ScheduleOverlapPolicy.UNSPECIFIED;
203
- const encodedPolicyName = temporal.api.enums.v1.ScheduleOverlapPolicy[input];
204
- const decodedPolicyName = encodedPolicyName.substring(
205
- 'SCHEDULE_OVERLAP_POLICY_'.length
206
- ) as keyof typeof ScheduleOverlapPolicy;
207
- return ScheduleOverlapPolicy[decodedPolicyName];
208
- }
209
-
210
195
  export function compileScheduleOptions(options: ScheduleOptions): CompiledScheduleOptions {
211
196
  const workflowTypeOrFunc = options.action.workflowType;
212
197
  const workflowType = extractWorkflowType(workflowTypeOrFunc);
@@ -290,7 +275,7 @@ export function encodeSchedulePolicies(
290
275
  ): temporal.api.schedule.v1.ISchedulePolicies {
291
276
  return {
292
277
  catchupWindow: msOptionalToTs(policies?.catchupWindow),
293
- overlapPolicy: policies?.overlap ? encodeOverlapPolicy(policies.overlap) : undefined,
278
+ overlapPolicy: policies?.overlap ? encodeScheduleOverlapPolicy(policies.overlap) : undefined,
294
279
  pauseOnFailure: policies?.pauseOnFailure,
295
280
  };
296
281
  }
@@ -1,5 +1,6 @@
1
1
  import { checkExtends, Replace } from '@temporalio/common/lib/type-helpers';
2
2
  import { Duration, SearchAttributes, Workflow } from '@temporalio/common';
3
+ import { makeProtoEnumConverters } from '@temporalio/common/lib/internal-workflow';
3
4
  import type { temporal } from '@temporalio/proto';
4
5
  import { WorkflowStartOptions } from './workflow-options';
5
6
 
@@ -795,57 +796,69 @@ export type CompiledScheduleAction = Replace<
795
796
  /**
796
797
  * Policy for overlapping Actions.
797
798
  */
798
- export enum ScheduleOverlapPolicy {
799
- /**
800
- * Use server default (currently SKIP).
801
- *
802
- * FIXME: remove this field if this issue is implemented: https://github.com/temporalio/temporal/issues/3240
803
- */
804
- UNSPECIFIED = 0,
805
-
799
+ export const ScheduleOverlapPolicy = {
806
800
  /**
807
801
  * Don't start a new Action.
802
+ * @default
808
803
  */
809
- SKIP,
804
+ SKIP: 'SKIP',
810
805
 
811
806
  /**
812
807
  * Start another Action as soon as the current Action completes, but only buffer one Action in this way. If another
813
808
  * Action is supposed to start, but one Action is running and one is already buffered, then only the buffered one will
814
809
  * be started after the running Action finishes.
815
810
  */
816
- BUFFER_ONE,
811
+ BUFFER_ONE: 'BUFFER_ONE',
817
812
 
818
813
  /**
819
814
  * Allows an unlimited number of Actions to buffer. They are started sequentially.
820
815
  */
821
- BUFFER_ALL,
816
+ BUFFER_ALL: 'BUFFER_ALL',
822
817
 
823
818
  /**
824
819
  * Cancels the running Action, and then starts the new Action once the cancelled one completes.
825
820
  */
826
- CANCEL_OTHER,
821
+ CANCEL_OTHER: 'CANCEL_OTHER',
827
822
 
828
823
  /**
829
824
  * Terminate the running Action and start the new Action immediately.
830
825
  */
831
- TERMINATE_OTHER,
826
+ TERMINATE_OTHER: 'TERMINATE_OTHER',
832
827
 
833
828
  /**
834
829
  * Allow any number of Actions to start immediately.
835
830
  *
836
831
  * This is the only policy under which multiple Actions can run concurrently.
837
832
  */
838
- ALLOW_ALL,
839
- }
833
+ ALLOW_ALL: 'ALLOW_ALL',
840
834
 
841
- checkExtends<
835
+ /**
836
+ * Use server default (currently SKIP).
837
+ *
838
+ * @deprecated Either leave property `undefined`, or use {@link SKIP} instead.
839
+ */
840
+ UNSPECIFIED: undefined, // eslint-disable-line deprecation/deprecation
841
+ } as const;
842
+ export type ScheduleOverlapPolicy = (typeof ScheduleOverlapPolicy)[keyof typeof ScheduleOverlapPolicy];
843
+
844
+ export const [encodeScheduleOverlapPolicy, decodeScheduleOverlapPolicy] = makeProtoEnumConverters<
845
+ temporal.api.enums.v1.ScheduleOverlapPolicy,
846
+ typeof temporal.api.enums.v1.ScheduleOverlapPolicy,
842
847
  keyof typeof temporal.api.enums.v1.ScheduleOverlapPolicy,
843
- `SCHEDULE_OVERLAP_POLICY_${keyof typeof ScheduleOverlapPolicy}`
844
- >();
845
- checkExtends<
846
- `SCHEDULE_OVERLAP_POLICY_${keyof typeof ScheduleOverlapPolicy}`,
847
- keyof typeof temporal.api.enums.v1.ScheduleOverlapPolicy
848
- >();
848
+ typeof ScheduleOverlapPolicy,
849
+ 'SCHEDULE_OVERLAP_POLICY_'
850
+ >(
851
+ {
852
+ [ScheduleOverlapPolicy.SKIP]: 1,
853
+ [ScheduleOverlapPolicy.BUFFER_ONE]: 2,
854
+ [ScheduleOverlapPolicy.BUFFER_ALL]: 3,
855
+ [ScheduleOverlapPolicy.CANCEL_OTHER]: 4,
856
+ [ScheduleOverlapPolicy.TERMINATE_OTHER]: 5,
857
+ [ScheduleOverlapPolicy.ALLOW_ALL]: 6,
858
+ UNSPECIFIED: 0,
859
+ } as const,
860
+ 'SCHEDULE_OVERLAP_POLICY_'
861
+ );
849
862
 
850
863
  export interface Backfill {
851
864
  /**
@@ -1,6 +1,7 @@
1
1
  import { status } from '@grpc/grpc-js';
2
2
  import { filterNullAndUndefined } from '@temporalio/common/lib/internal-non-workflow';
3
3
  import { assertNever, SymbolBasedInstanceOfError, RequireAtLeastOne } from '@temporalio/common/lib/type-helpers';
4
+ import { makeProtoEnumConverters } from '@temporalio/common/lib/internal-workflow';
4
5
  import { temporal } from '@temporalio/proto';
5
6
  import { BaseClient, BaseClientOptions, defaultBaseClientOptions, LoadedWithDefaults } from './base-client';
6
7
  import { WorkflowService } from './types';
@@ -148,7 +149,7 @@ export class TaskQueueClient extends BaseClient {
148
149
  namespace: this.options.namespace,
149
150
  taskQueues: options.taskQueues,
150
151
  buildIds,
151
- reachability: reachabilityTypeToProto(options.reachability),
152
+ reachability: encodeTaskReachability(options.reachability),
152
153
  });
153
154
  } catch (e) {
154
155
  this.rethrowGrpcError(e, 'Unexpected error fetching Build Id reachability');
@@ -173,6 +174,20 @@ export class TaskQueueClient extends BaseClient {
173
174
  */
174
175
  export type ReachabilityOptions = RequireAtLeastOne<BaseReachabilityOptions, 'buildIds' | 'taskQueues'>;
175
176
 
177
+ export const ReachabilityType = {
178
+ /** The Build Id might be used by new workflows. */
179
+ NEW_WORKFLOWS: 'NEW_WORKFLOWS',
180
+
181
+ /** The Build Id might be used by open workflows and/or closed workflows. */
182
+ EXISTING_WORKFLOWS: 'EXISTING_WORKFLOWS',
183
+
184
+ /** The Build Id might be used by open workflows. */
185
+ OPEN_WORKFLOWS: 'OPEN_WORKFLOWS',
186
+
187
+ /** The Build Id might be used by closed workflows. */
188
+ CLOSED_WORKFLOWS: 'CLOSED_WORKFLOWS',
189
+ } as const;
190
+
176
191
  /**
177
192
  * There are different types of reachability:
178
193
  * - `NEW_WORKFLOWS`: The Build Id might be used by new workflows
@@ -180,7 +195,24 @@ export type ReachabilityOptions = RequireAtLeastOne<BaseReachabilityOptions, 'bu
180
195
  * - `OPEN_WORKFLOWS` The Build Id might be used by open workflows
181
196
  * - `CLOSED_WORKFLOWS` The Build Id might be used by closed workflows
182
197
  */
183
- export type ReachabilityType = 'NEW_WORKFLOWS' | 'EXISTING_WORKFLOWS' | 'OPEN_WORKFLOWS' | 'CLOSED_WORKFLOWS';
198
+ export type ReachabilityType = (typeof ReachabilityType)[keyof typeof ReachabilityType];
199
+
200
+ export const [encodeTaskReachability, decodeTaskReachability] = makeProtoEnumConverters<
201
+ temporal.api.enums.v1.TaskReachability,
202
+ typeof temporal.api.enums.v1.TaskReachability,
203
+ keyof typeof temporal.api.enums.v1.TaskReachability,
204
+ typeof ReachabilityType,
205
+ 'TASK_REACHABILITY_'
206
+ >(
207
+ {
208
+ [ReachabilityType.NEW_WORKFLOWS]: 1,
209
+ [ReachabilityType.EXISTING_WORKFLOWS]: 2,
210
+ [ReachabilityType.OPEN_WORKFLOWS]: 3,
211
+ [ReachabilityType.CLOSED_WORKFLOWS]: 4,
212
+ UNSPECIFIED: 0,
213
+ } as const,
214
+ 'TASK_REACHABILITY_'
215
+ );
184
216
 
185
217
  /**
186
218
  * See {@link ReachabilityOptions}
@@ -215,24 +247,6 @@ export interface BuildIdReachability {
215
247
  taskQueueReachability: Record<string, ReachabilityTypeResponse[]>;
216
248
  }
217
249
 
218
- function reachabilityTypeToProto(type: ReachabilityType | undefined | null): temporal.api.enums.v1.TaskReachability {
219
- switch (type) {
220
- case null:
221
- case undefined:
222
- return temporal.api.enums.v1.TaskReachability.TASK_REACHABILITY_UNSPECIFIED;
223
- case 'NEW_WORKFLOWS':
224
- return temporal.api.enums.v1.TaskReachability.TASK_REACHABILITY_NEW_WORKFLOWS;
225
- case 'EXISTING_WORKFLOWS':
226
- return temporal.api.enums.v1.TaskReachability.TASK_REACHABILITY_EXISTING_WORKFLOWS;
227
- case 'OPEN_WORKFLOWS':
228
- return temporal.api.enums.v1.TaskReachability.TASK_REACHABILITY_OPEN_WORKFLOWS;
229
- case 'CLOSED_WORKFLOWS':
230
- return temporal.api.enums.v1.TaskReachability.TASK_REACHABILITY_CLOSED_WORKFLOWS;
231
- default:
232
- assertNever('Unknown Build Id reachability operation', type);
233
- }
234
- }
235
-
236
250
  export function reachabilityResponseFromProto(resp: GetWorkerTaskReachabilityResponse): ReachabilityResponse {
237
251
  return {
238
252
  buildIdReachability: Object.fromEntries(
@@ -247,7 +261,9 @@ export function reachabilityResponseFromProto(resp: GetWorkerTaskReachabilityRes
247
261
  taskQueueReachability[tqr.taskQueue] = [];
248
262
  continue;
249
263
  }
250
- taskQueueReachability[tqr.taskQueue] = tqr.reachability.map(reachabilityTypeFromProto);
264
+ taskQueueReachability[tqr.taskQueue] = tqr.reachability.map(
265
+ (x) => decodeTaskReachability(x) ?? 'NOT_FETCHED'
266
+ );
251
267
  }
252
268
  }
253
269
  let bid: string | UnversionedBuildIdType;
@@ -262,23 +278,6 @@ export function reachabilityResponseFromProto(resp: GetWorkerTaskReachabilityRes
262
278
  };
263
279
  }
264
280
 
265
- function reachabilityTypeFromProto(rtype: temporal.api.enums.v1.TaskReachability): ReachabilityTypeResponse {
266
- switch (rtype) {
267
- case temporal.api.enums.v1.TaskReachability.TASK_REACHABILITY_UNSPECIFIED:
268
- return 'NOT_FETCHED';
269
- case temporal.api.enums.v1.TaskReachability.TASK_REACHABILITY_NEW_WORKFLOWS:
270
- return 'NEW_WORKFLOWS';
271
- case temporal.api.enums.v1.TaskReachability.TASK_REACHABILITY_EXISTING_WORKFLOWS:
272
- return 'EXISTING_WORKFLOWS';
273
- case temporal.api.enums.v1.TaskReachability.TASK_REACHABILITY_OPEN_WORKFLOWS:
274
- return 'OPEN_WORKFLOWS';
275
- case temporal.api.enums.v1.TaskReachability.TASK_REACHABILITY_CLOSED_WORKFLOWS:
276
- return 'CLOSED_WORKFLOWS';
277
- default:
278
- return assertNever('Unknown Build Id reachability operation', rtype);
279
- }
280
- }
281
-
282
281
  /**
283
282
  * Thrown when one or more Build Ids are not found while using the {@link TaskQueueClient}.
284
283
  *
package/src/types.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  import type * as grpc from '@grpc/grpc-js';
2
2
  import type { SearchAttributes } from '@temporalio/common';
3
+ import { makeProtoEnumConverters } from '@temporalio/common/lib/internal-workflow';
3
4
  import * as proto from '@temporalio/proto';
4
5
  import { Replace } from '@temporalio/common/lib/type-helpers';
5
6
 
@@ -102,7 +103,7 @@ export interface ConnectionLike {
102
103
  *
103
104
  * The deadline is a point in time after which any pending gRPC request will be considered as failed;
104
105
  * this will locally result in the request call throwing a {@link grpc.ServiceError|ServiceError}
105
- * with code {@link grpc.status.DEADLINE_EXCEEDED|DEADLINE_EXCEEDED}.
106
+ * with code {@link grpc.status.DEADLINE_EXCEEDED|DEADLINE_EXCEEDED}; see {@link isGrpcDeadlineError}.
106
107
  *
107
108
  * It is stronly recommended to explicitly set deadlines. If no deadline is set, then it is
108
109
  * possible for the client to end up waiting forever for a response.
@@ -127,7 +128,7 @@ export interface ConnectionLike {
127
128
  /**
128
129
  * Set an {@link AbortSignal} that, when aborted, cancels any ongoing service requests executed in
129
130
  * `fn`'s scope. This will locally result in the request call throwing a {@link grpc.ServiceError|ServiceError}
130
- * with code {@link grpc.status.CANCELLED|CANCELLED}.
131
+ * with code {@link grpc.status.CANCELLED|CANCELLED}; see {@link isGrpcCancelledError}.
131
132
  *
132
133
  * @returns value returned from `fn`
133
134
  *
@@ -135,3 +136,38 @@ export interface ConnectionLike {
135
136
  */
136
137
  withAbortSignal<R>(abortSignal: AbortSignal, fn: () => Promise<R>): Promise<R>;
137
138
  }
139
+
140
+ export const QueryRejectCondition = {
141
+ NONE: 'NONE',
142
+ NOT_OPEN: 'NOT_OPEN',
143
+ NOT_COMPLETED_CLEANLY: 'NOT_COMPLETED_CLEANLY',
144
+
145
+ /** @deprecated Use {@link NONE} instead. */
146
+ QUERY_REJECT_CONDITION_NONE: 'NONE', // eslint-disable-line deprecation/deprecation
147
+
148
+ /** @deprecated Use {@link NOT_OPEN} instead. */
149
+ QUERY_REJECT_CONDITION_NOT_OPEN: 'NOT_OPEN', // eslint-disable-line deprecation/deprecation
150
+
151
+ /** @deprecated Use {@link NOT_COMPLETED_CLEANLY} instead. */
152
+ QUERY_REJECT_CONDITION_NOT_COMPLETED_CLEANLY: 'NOT_COMPLETED_CLEANLY', // eslint-disable-line deprecation/deprecation
153
+
154
+ /** @deprecated Use `undefined` instead. */
155
+ QUERY_REJECT_CONDITION_UNSPECIFIED: undefined, // eslint-disable-line deprecation/deprecation
156
+ } as const;
157
+ export type QueryRejectCondition = (typeof QueryRejectCondition)[keyof typeof QueryRejectCondition];
158
+
159
+ export const [encodeQueryRejectCondition, decodeQueryRejectCondition] = makeProtoEnumConverters<
160
+ proto.temporal.api.enums.v1.QueryRejectCondition,
161
+ typeof proto.temporal.api.enums.v1.QueryRejectCondition,
162
+ keyof typeof proto.temporal.api.enums.v1.QueryRejectCondition,
163
+ typeof QueryRejectCondition,
164
+ 'QUERY_REJECT_CONDITION_'
165
+ >(
166
+ {
167
+ [QueryRejectCondition.NONE]: 1,
168
+ [QueryRejectCondition.NOT_OPEN]: 2,
169
+ [QueryRejectCondition.NOT_COMPLETED_CLEANLY]: 3,
170
+ UNSPECIFIED: 0,
171
+ } as const,
172
+ 'QUERY_REJECT_CONDITION_'
173
+ );
@@ -20,6 +20,9 @@ import {
20
20
  WorkflowNotFoundError,
21
21
  WorkflowResultType,
22
22
  extractWorkflowType,
23
+ encodeWorkflowIdReusePolicy,
24
+ decodeRetryState,
25
+ encodeWorkflowIdConflictPolicy,
23
26
  } from '@temporalio/common';
24
27
  import { composeInterceptors } from '@temporalio/common/lib/interceptors';
25
28
  import { History } from '@temporalio/common/lib/proto-utils';
@@ -56,7 +59,9 @@ import {
56
59
  } from './interceptors';
57
60
  import {
58
61
  DescribeWorkflowExecutionResponse,
62
+ encodeQueryRejectCondition,
59
63
  GetWorkflowExecutionHistoryRequest,
64
+ QueryRejectCondition,
60
65
  RequestCancelWorkflowExecutionResponse,
61
66
  StartWorkflowExecutionRequest,
62
67
  TerminateWorkflowExecutionResponse,
@@ -81,8 +86,9 @@ import {
81
86
  WithDefaults,
82
87
  } from './base-client';
83
88
  import { mapAsyncIterable } from './iterators-utils';
84
- import { WorkflowUpdateStage } from './workflow-update-stage';
85
- import * as workflowUpdateStage from './workflow-update-stage';
89
+ import { WorkflowUpdateStage, encodeWorkflowUpdateStage } from './workflow-update-stage';
90
+
91
+ const UpdateWorkflowExecutionLifecycleStage = temporal.api.enums.v1.UpdateWorkflowExecutionLifecycleStage;
86
92
 
87
93
  /**
88
94
  * A client side handle to a single Workflow instance.
@@ -168,7 +174,7 @@ export interface WorkflowHandle<T extends Workflow = Workflow> extends BaseWorkf
168
174
  * ```ts
169
175
  * const updateHandle = await handle.startUpdate(incrementAndGetValueUpdate, {
170
176
  * args: [2],
171
- * waitForStage: WorkflowUpdateStage.ACCEPTED,
177
+ * waitForStage: 'ACCEPTED',
172
178
  * });
173
179
  * const updateResult = await updateHandle.result();
174
180
  * ```
@@ -177,7 +183,7 @@ export interface WorkflowHandle<T extends Workflow = Workflow> extends BaseWorkf
177
183
  def: UpdateDefinition<Ret, Args, Name> | string,
178
184
  options: WorkflowUpdateOptions & {
179
185
  args: Args;
180
- waitForStage: WorkflowUpdateStage.ACCEPTED;
186
+ waitForStage: 'ACCEPTED';
181
187
  }
182
188
  ): Promise<WorkflowUpdateHandle<Ret>>;
183
189
 
@@ -185,7 +191,7 @@ export interface WorkflowHandle<T extends Workflow = Workflow> extends BaseWorkf
185
191
  def: UpdateDefinition<Ret, Args, Name> | string,
186
192
  options: WorkflowUpdateOptions & {
187
193
  args?: Args;
188
- waitForStage: WorkflowUpdateStage.ACCEPTED;
194
+ waitForStage: typeof WorkflowUpdateStage.ACCEPTED;
189
195
  }
190
196
  ): Promise<WorkflowUpdateHandle<Ret>>;
191
197
 
@@ -280,9 +286,9 @@ export interface WorkflowClientOptions extends BaseClientOptions {
280
286
  /**
281
287
  * Should a query be rejected by closed and failed workflows
282
288
  *
283
- * @default QUERY_REJECT_CONDITION_UNSPECIFIED which means that closed and failed workflows are still queryable
289
+ * @default `undefined` which means that closed and failed workflows are still queryable
284
290
  */
285
- queryRejectCondition?: temporal.api.enums.v1.QueryRejectCondition;
291
+ queryRejectCondition?: QueryRejectCondition;
286
292
  }
287
293
 
288
294
  export type LoadedWorkflowClientOptions = LoadedWithDefaults<WorkflowClientOptions>;
@@ -291,7 +297,7 @@ function defaultWorkflowClientOptions(): WithDefaults<WorkflowClientOptions> {
291
297
  return {
292
298
  ...defaultBaseClientOptions(),
293
299
  interceptors: [],
294
- queryRejectCondition: temporal.api.enums.v1.QueryRejectCondition.QUERY_REJECT_CONDITION_UNSPECIFIED,
300
+ queryRejectCondition: 'NONE',
295
301
  };
296
302
  }
297
303
 
@@ -659,7 +665,7 @@ export class WorkflowClient extends BaseClient {
659
665
  throw new WorkflowFailedError(
660
666
  'Workflow execution failed',
661
667
  await decodeOptionalFailureToOptionalError(this.dataConverter, failure),
662
- retryState ?? RetryState.RETRY_STATE_UNSPECIFIED
668
+ decodeRetryState(retryState)
663
669
  );
664
670
  } else if (ev.workflowExecutionCanceledEventAttributes) {
665
671
  const failure = new CancelledFailure(
@@ -670,11 +676,7 @@ export class WorkflowClient extends BaseClient {
670
676
  )
671
677
  );
672
678
  failure.stack = '';
673
- throw new WorkflowFailedError(
674
- 'Workflow execution cancelled',
675
- failure,
676
- RetryState.RETRY_STATE_NON_RETRYABLE_FAILURE
677
- );
679
+ throw new WorkflowFailedError('Workflow execution cancelled', failure, RetryState.NON_RETRYABLE_FAILURE);
678
680
  } else if (ev.workflowExecutionTerminatedEventAttributes) {
679
681
  const failure = new TerminatedFailure(
680
682
  ev.workflowExecutionTerminatedEventAttributes.reason || 'Workflow execution terminated'
@@ -683,7 +685,7 @@ export class WorkflowClient extends BaseClient {
683
685
  throw new WorkflowFailedError(
684
686
  ev.workflowExecutionTerminatedEventAttributes.reason || 'Workflow execution terminated',
685
687
  failure,
686
- RetryState.RETRY_STATE_NON_RETRYABLE_FAILURE
688
+ RetryState.NON_RETRYABLE_FAILURE
687
689
  );
688
690
  } else if (ev.workflowExecutionTimedOutEventAttributes) {
689
691
  if (followRuns && ev.workflowExecutionTimedOutEventAttributes.newExecutionRunId) {
@@ -691,16 +693,12 @@ export class WorkflowClient extends BaseClient {
691
693
  req.nextPageToken = undefined;
692
694
  continue;
693
695
  }
694
- const failure = new TimeoutFailure(
695
- 'Workflow execution timed out',
696
- undefined,
697
- TimeoutType.TIMEOUT_TYPE_START_TO_CLOSE
698
- );
696
+ const failure = new TimeoutFailure('Workflow execution timed out', undefined, TimeoutType.START_TO_CLOSE);
699
697
  failure.stack = '';
700
698
  throw new WorkflowFailedError(
701
699
  'Workflow execution timed out',
702
700
  failure,
703
- ev.workflowExecutionTimedOutEventAttributes.retryState || 0
701
+ decodeRetryState(ev.workflowExecutionTimedOutEventAttributes.retryState)
704
702
  );
705
703
  } else if (ev.workflowExecutionContinuedAsNewEventAttributes) {
706
704
  const { newExecutionRunId } = ev.workflowExecutionContinuedAsNewEventAttributes;
@@ -806,8 +804,15 @@ export class WorkflowClient extends BaseClient {
806
804
  waitForStage: WorkflowUpdateStage,
807
805
  input: WorkflowStartUpdateInput
808
806
  ): Promise<WorkflowStartUpdateOutput> {
809
- waitForStage = waitForStage >= WorkflowUpdateStage.ACCEPTED ? waitForStage : WorkflowUpdateStage.ACCEPTED;
810
- const waitForStageProto = workflowUpdateStage.toProtoEnum(waitForStage);
807
+ let waitForStageProto: temporal.api.enums.v1.UpdateWorkflowExecutionLifecycleStage =
808
+ encodeWorkflowUpdateStage(waitForStage) ??
809
+ UpdateWorkflowExecutionLifecycleStage.UPDATE_WORKFLOW_EXECUTION_LIFECYCLE_STAGE_ACCEPTED;
810
+
811
+ waitForStageProto =
812
+ waitForStageProto >= UpdateWorkflowExecutionLifecycleStage.UPDATE_WORKFLOW_EXECUTION_LIFECYCLE_STAGE_ACCEPTED
813
+ ? waitForStageProto
814
+ : UpdateWorkflowExecutionLifecycleStage.UPDATE_WORKFLOW_EXECUTION_LIFECYCLE_STAGE_ACCEPTED;
815
+
811
816
  const updateId = input.options?.updateId ?? uuid4();
812
817
  const req: temporal.api.workflowservice.v1.IUpdateWorkflowExecutionRequest = {
813
818
  namespace: this.options.namespace,
@@ -886,7 +891,7 @@ export class WorkflowClient extends BaseClient {
886
891
  updateRef: { workflowExecution, updateId },
887
892
  identity: this.options.identity,
888
893
  waitPolicy: {
889
- lifecycleStage: workflowUpdateStage.toProtoEnum(WorkflowUpdateStage.COMPLETED),
894
+ lifecycleStage: encodeWorkflowUpdateStage(WorkflowUpdateStage.COMPLETED),
890
895
  },
891
896
  };
892
897
  for (;;) {
@@ -938,7 +943,8 @@ export class WorkflowClient extends BaseClient {
938
943
  identity,
939
944
  requestId: uuid4(),
940
945
  workflowId: options.workflowId,
941
- workflowIdReusePolicy: options.workflowIdReusePolicy,
946
+ workflowIdReusePolicy: encodeWorkflowIdReusePolicy(options.workflowIdReusePolicy),
947
+ workflowIdConflictPolicy: encodeWorkflowIdConflictPolicy(options.workflowIdConflictPolicy),
942
948
  workflowType: { name: workflowType },
943
949
  input: { payloads: await encodeToPayloads(this.dataConverter, ...options.args) },
944
950
  signalName,
@@ -988,7 +994,8 @@ export class WorkflowClient extends BaseClient {
988
994
  identity,
989
995
  requestId: uuid4(),
990
996
  workflowId: opts.workflowId,
991
- workflowIdReusePolicy: opts.workflowIdReusePolicy,
997
+ workflowIdReusePolicy: encodeWorkflowIdReusePolicy(opts.workflowIdReusePolicy),
998
+ workflowIdConflictPolicy: encodeWorkflowIdConflictPolicy(opts.workflowIdConflictPolicy),
992
999
  workflowType: { name: workflowType },
993
1000
  input: { payloads: await encodeToPayloads(this.dataConverter, ...opts.args) },
994
1001
  taskQueue: {
@@ -1178,7 +1185,7 @@ export class WorkflowClient extends BaseClient {
1178
1185
  def: UpdateDefinition<Ret, Args> | string,
1179
1186
  options: WorkflowUpdateOptions & {
1180
1187
  args?: Args;
1181
- waitForStage: WorkflowUpdateStage.ACCEPTED;
1188
+ waitForStage: typeof WorkflowUpdateStage.ACCEPTED;
1182
1189
  }
1183
1190
  ): Promise<WorkflowUpdateHandle<Ret>> {
1184
1191
  return await _startUpdate(def, options.waitForStage, options);
@@ -1208,7 +1215,7 @@ export class WorkflowClient extends BaseClient {
1208
1215
  const fn = composeInterceptors(interceptors, 'query', next);
1209
1216
  return fn({
1210
1217
  workflowExecution: { workflowId, runId },
1211
- queryRejectCondition: this.client.options.queryRejectCondition,
1218
+ queryRejectCondition: encodeQueryRejectCondition(this.client.options.queryRejectCondition),
1212
1219
  queryType: typeof def === 'string' ? def : def.name,
1213
1220
  args,
1214
1221
  headers: {},
@@ -15,7 +15,8 @@ export interface WorkflowOptions extends CommonWorkflowOptions {
15
15
  *
16
16
  * Assign a meaningful business id.
17
17
  * This ID can be used to ensure starting Workflows is idempotent.
18
- * Workflow IDs are unique, see also {@link WorkflowOptions.workflowIdReusePolicy}
18
+ * Workflow IDs are unique: see {@link WorkflowOptions.workflowIdReusePolicy}
19
+ * and {@link WorkflowOptions.workflowIdConflictPolicy}.
19
20
  */
20
21
  workflowId: string;
21
22