@temporalio/workflow 1.14.2-canary-release-testing.0 → 1.15.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/src/nexus.ts CHANGED
@@ -2,6 +2,8 @@ import * as nexus from 'nexus-rpc';
2
2
  import { msOptionalToTs } from '@temporalio/common/lib/time';
3
3
  import { userMetadataToPayload } from '@temporalio/common/lib/user-metadata';
4
4
  import { composeInterceptors } from '@temporalio/common/lib/interceptors';
5
+ import { makeProtoEnumConverters } from '@temporalio/common/lib/internal-workflow/enums-helpers';
6
+ import type { coresdk } from '@temporalio/proto';
5
7
  import { CancellationScope } from './cancellation-scope';
6
8
  import { getActivator } from './global-attributes';
7
9
  import { untrackPromise } from './stack-helpers';
@@ -146,17 +148,18 @@ export function createNexusClient<T extends nexus.ServiceDefinition>(options: Ne
146
148
  startNexusOperationNextHandler
147
149
  );
148
150
 
149
- // TODO: Do we want to make the interceptor async like we do for child workflow? That seems redundant.
150
- // REVIEW: I ended up changing this so that the interceptor returns a Promise<StartNexusOperationOutput>,
151
- // and the result promise is contained in that Output object. As a consequence of this,
152
- // the result promise/completion does not exist until the StartNexusOperation event is received.
153
- // That's totally different from what we did in ChildWorkflow, but I think that's cleaner from
154
- // interceptors point of view, and will make it easier to extend the API in the future.
151
+ // The interceptor returns a Promise<StartNexusOperationOutput>, with the result promise contained
152
+ // in that Output object. As a consequence of this, the result promise/completion does not exist
153
+ // until the StartNexusOperation event is received. This is totally different from what we did in
154
+ // ChildWorkflow, but is much cleaner from the interceptors point of view.
155
155
  const { token, result: resultPromise } = await execute({
156
156
  endpoint: options.endpoint,
157
157
  service: options.service.name,
158
158
  operation: opName,
159
- options: operationOptions ?? {},
159
+ options: {
160
+ ...operationOptions,
161
+ cancellationType: operationOptions?.cancellationType ?? 'WAIT_CANCELLATION_COMPLETED',
162
+ },
160
163
  headers: {},
161
164
  seq,
162
165
  input,
@@ -220,7 +223,7 @@ function startNexusOperationNextHandler({
220
223
  nexusHeader: headers,
221
224
  input: activator.payloadConverter.toPayload(input),
222
225
  scheduleToCloseTimeout: msOptionalToTs(options?.scheduleToCloseTimeout),
223
- // FIXME(nexus-post-initial-release): cancellationType is not supported yet
226
+ cancellationType: encodeNexusOperationCancellationType(options?.cancellationType),
224
227
  },
225
228
  userMetadata: userMetadataToPayload(activator.payloadConverter, options?.summary, undefined),
226
229
  });
@@ -231,3 +234,76 @@ function startNexusOperationNextHandler({
231
234
  });
232
235
  });
233
236
  }
237
+
238
+ /**
239
+ * Determines:
240
+ * - whether cancellation requests should be propagated from the Workflow to the Nexus Operation
241
+ * - whether and when should the Operation's cancellation be reported back to the Workflow
242
+ * (i.e. at which moment should the operation's result promise fail with a `NexusOperationFailure`,
243
+ * with `cause` set to a `CancelledFailure`).
244
+ *
245
+ * Note that this setting only applies to cancellation originating from an external request for the
246
+ * Workflow itself, or from internal cancellation of the `CancellationScope` in which the
247
+ * Operation call was made.
248
+ *
249
+ * @experimental Nexus support in Temporal SDK is experimental.
250
+ */
251
+ // MAINTENANCE: Keep this typedoc in sync with the `StartNexusOperationOptions.cancellationType` field
252
+ export const NexusOperationCancellationType = {
253
+ /**
254
+ * Do not propagate cancellation requests to the Nexus Operation, and immediately report
255
+ * cancellation to the caller.
256
+ */
257
+ ABANDON: 'ABANDON',
258
+
259
+ /**
260
+ * Initiate a cancellation request for the Nexus operation and immediately report cancellation to
261
+ * the caller. Note that it doesn't guarantee that cancellation is delivered to the operation if
262
+ * calling workflow exits before the delivery is done. If you want to ensure that cancellation is
263
+ * delivered to the operation, use {@link WAIT_CANCELLATION_REQUESTED}.
264
+ *
265
+ * Propagate cancellation request from the Workflow to the Operation, yet _immediately_ report
266
+ * cancellation to the caller, i.e. without waiting for the server to confirm the cancellation
267
+ * request.
268
+ *
269
+ * Note that this cancellation type provides no guarantee, from the Workflow-side, that the
270
+ * cancellation request will be delivered to the Operation Handler. In particular, either the
271
+ * Operation or the Workflow may complete (either successfully or uncessfully) before the
272
+ * cancellation request is delivered, resulting in a situation where the Operation completed
273
+ * successfully, but the Workflow thinks it was cancelled.
274
+ *
275
+ * To guarantee that the Operation will eventually be notified of the cancellation request,
276
+ * use {@link WAIT_CANCELLATION_REQUESTED}.
277
+ */
278
+ TRY_CANCEL: 'TRY_CANCEL',
279
+
280
+ /**
281
+ * Propagate cancellation request from the Workflow to the Operation, then wait for the server
282
+ * to confirm that the Operation cancellation request was delivered to the Operation Handler.
283
+ */
284
+ WAIT_CANCELLATION_REQUESTED: 'WAIT_CANCELLATION_REQUESTED',
285
+
286
+ /**
287
+ * Propagate cancellation request from the Workflow to the Operation, then wait for completion
288
+ * of the Operation.
289
+ */
290
+ WAIT_CANCELLATION_COMPLETED: 'WAIT_CANCELLATION_COMPLETED',
291
+ } as const;
292
+ export type NexusOperationCancellationType =
293
+ (typeof NexusOperationCancellationType)[keyof typeof NexusOperationCancellationType];
294
+
295
+ const [encodeNexusOperationCancellationType, _] = makeProtoEnumConverters<
296
+ coresdk.nexus.NexusOperationCancellationType,
297
+ typeof coresdk.nexus.NexusOperationCancellationType,
298
+ keyof typeof coresdk.nexus.NexusOperationCancellationType,
299
+ typeof NexusOperationCancellationType,
300
+ ''
301
+ >(
302
+ {
303
+ [NexusOperationCancellationType.WAIT_CANCELLATION_COMPLETED]: 0,
304
+ [NexusOperationCancellationType.ABANDON]: 1,
305
+ [NexusOperationCancellationType.TRY_CANCEL]: 2,
306
+ [NexusOperationCancellationType.WAIT_CANCELLATION_REQUESTED]: 3,
307
+ } as const,
308
+ ''
309
+ );
package/src/workflow.ts CHANGED
@@ -202,7 +202,7 @@ function scheduleActivityNextHandler({ options, args, headers, seq, activityType
202
202
  headers,
203
203
  cancellationType: encodeActivityCancellationType(options.cancellationType),
204
204
  doNotEagerlyExecute: !(options.allowEagerDispatch ?? true),
205
- versioningIntent: versioningIntentToProto(options.versioningIntent), // eslint-disable-line deprecation/deprecation
205
+ versioningIntent: versioningIntentToProto(options.versioningIntent), // eslint-disable-line @typescript-eslint/no-deprecated
206
206
  priority: options.priority ? compilePriority(options.priority) : undefined,
207
207
  },
208
208
  userMetadata: userMetadataToPayload(activator.payloadConverter, options.summary, undefined),
@@ -401,11 +401,11 @@ function startChildWorkflowExecutionNextHandler({
401
401
  parentClosePolicy: encodeParentClosePolicy(options.parentClosePolicy),
402
402
  cronSchedule: options.cronSchedule,
403
403
  searchAttributes:
404
- options.searchAttributes || options.typedSearchAttributes // eslint-disable-line deprecation/deprecation
405
- ? encodeUnifiedSearchAttributes(options.searchAttributes, options.typedSearchAttributes) // eslint-disable-line deprecation/deprecation
404
+ options.searchAttributes || options.typedSearchAttributes // eslint-disable-line @typescript-eslint/no-deprecated
405
+ ? encodeUnifiedSearchAttributes(options.searchAttributes, options.typedSearchAttributes) // eslint-disable-line @typescript-eslint/no-deprecated
406
406
  : undefined,
407
407
  memo: options.memo && mapToPayloads(activator.payloadConverter, options.memo),
408
- versioningIntent: versioningIntentToProto(options.versioningIntent), // eslint-disable-line deprecation/deprecation
408
+ versioningIntent: versioningIntentToProto(options.versioningIntent), // eslint-disable-line @typescript-eslint/no-deprecated
409
409
  priority: options.priority ? compilePriority(options.priority) : undefined,
410
410
  },
411
411
  userMetadata: userMetadataToPayload(activator.payloadConverter, options?.staticSummary, options?.staticDetails),
@@ -1018,12 +1018,12 @@ export function makeContinueAsNewFunc<F extends Workflow>(
1018
1018
  taskQueue: options.taskQueue,
1019
1019
  memo: options.memo && mapToPayloads(activator.payloadConverter, options.memo),
1020
1020
  searchAttributes:
1021
- options.searchAttributes || options.typedSearchAttributes // eslint-disable-line deprecation/deprecation
1022
- ? encodeUnifiedSearchAttributes(options.searchAttributes, options.typedSearchAttributes) // eslint-disable-line deprecation/deprecation
1021
+ options.searchAttributes || options.typedSearchAttributes // eslint-disable-line @typescript-eslint/no-deprecated
1022
+ ? encodeUnifiedSearchAttributes(options.searchAttributes, options.typedSearchAttributes) // eslint-disable-line @typescript-eslint/no-deprecated
1023
1023
  : undefined,
1024
1024
  workflowRunTimeout: msOptionalToTs(options.workflowRunTimeout),
1025
1025
  workflowTaskTimeout: msOptionalToTs(options.workflowTaskTimeout),
1026
- versioningIntent: versioningIntentToProto(options.versioningIntent), // eslint-disable-line deprecation/deprecation
1026
+ versioningIntent: versioningIntentToProto(options.versioningIntent), // eslint-disable-line @typescript-eslint/no-deprecated
1027
1027
  });
1028
1028
  });
1029
1029
  return fn({
@@ -1509,7 +1509,7 @@ export function setDefaultQueryHandler(handler: DefaultQueryHandler | undefined)
1509
1509
  * If using SearchAttributeUpdatePair[] (preferred), set a value to null to remove the search attribute.
1510
1510
  * If using SearchAttributes (deprecated), set a value to undefined or an empty list to remove the search attribute.
1511
1511
  */
1512
- // eslint-disable-next-line deprecation/deprecation
1512
+ // eslint-disable-next-line @typescript-eslint/no-deprecated
1513
1513
  export function upsertSearchAttributes(searchAttributes: SearchAttributes | SearchAttributeUpdatePair[]): void {
1514
1514
  const activator = assertInWorkflowContext(
1515
1515
  'Workflow.upsertSearchAttributes(...) may only be used from a Workflow Execution.'
@@ -1529,7 +1529,7 @@ export function upsertSearchAttributes(searchAttributes: SearchAttributes | Sear
1529
1529
 
1530
1530
  activator.mutateWorkflowInfo((info: WorkflowInfo): WorkflowInfo => {
1531
1531
  // Create a copy of the current state.
1532
- const newSearchAttributes: SearchAttributes = { ...info.searchAttributes }; // eslint-disable-line deprecation/deprecation
1532
+ const newSearchAttributes: SearchAttributes = { ...info.searchAttributes }; // eslint-disable-line @typescript-eslint/no-deprecated
1533
1533
  for (const pair of searchAttributes) {
1534
1534
  if (pair.value == null) {
1535
1535
  // If the value is null, remove the search attribute.
@@ -1538,7 +1538,7 @@ export function upsertSearchAttributes(searchAttributes: SearchAttributes | Sear
1538
1538
  } else {
1539
1539
  newSearchAttributes[pair.key.name] = Array.isArray(pair.value)
1540
1540
  ? pair.value
1541
- : ([pair.value] as SearchAttributeValue); // eslint-disable-line deprecation/deprecation
1541
+ : ([pair.value] as SearchAttributeValue); // eslint-disable-line @typescript-eslint/no-deprecated
1542
1542
  }
1543
1543
  }
1544
1544
  return {
@@ -1559,7 +1559,7 @@ export function upsertSearchAttributes(searchAttributes: SearchAttributes | Sear
1559
1559
  activator.mutateWorkflowInfo((info: WorkflowInfo): WorkflowInfo => {
1560
1560
  // Create a new copy of the current state.
1561
1561
  let typedSearchAttributes = info.typedSearchAttributes.updateCopy([]);
1562
- const newSearchAttributes: SearchAttributes = { ...info.searchAttributes }; // eslint-disable-line deprecation/deprecation
1562
+ const newSearchAttributes: SearchAttributes = { ...info.searchAttributes }; // eslint-disable-line @typescript-eslint/no-deprecated
1563
1563
 
1564
1564
  // Upsert legacy search attributes into typedSearchAttributes.
1565
1565
  for (const [k, v] of Object.entries(searchAttributes)) {