@temporalio/client 1.13.0 → 1.13.2

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/types.ts CHANGED
@@ -3,6 +3,7 @@ import type { TypedSearchAttributes, SearchAttributes, SearchAttributeValue, Pri
3
3
  import { makeProtoEnumConverters } from '@temporalio/common/lib/internal-workflow';
4
4
  import * as proto from '@temporalio/proto';
5
5
  import { Replace } from '@temporalio/common/lib/type-helpers';
6
+ import type { ConnectionPlugin } from './connection';
6
7
 
7
8
  export interface WorkflowExecution {
8
9
  workflowId: string;
@@ -122,6 +123,7 @@ export interface CallContext {
122
123
  */
123
124
  export interface ConnectionLike {
124
125
  workflowService: WorkflowService;
126
+ plugins: ConnectionPlugin[];
125
127
  close(): Promise<void>;
126
128
  ensureConnected(): Promise<void>;
127
129
 
@@ -164,6 +166,17 @@ export interface ConnectionLike {
164
166
  withAbortSignal<R>(abortSignal: AbortSignal, fn: () => Promise<R>): Promise<R>;
165
167
  }
166
168
 
169
+ export const InternalConnectionLikeSymbol = Symbol('__temporal_internal_connection_like');
170
+ export type InternalConnectionLike = ConnectionLike & {
171
+ [InternalConnectionLikeSymbol]?: {
172
+ /**
173
+ * Capability flag that determines whether the connection supports eager workflow start.
174
+ * This will only be true if the underlying connection is a {@link NativeConnection}.
175
+ */
176
+ readonly supportsEagerStart?: boolean;
177
+ };
178
+ };
179
+
167
180
  export const QueryRejectCondition = {
168
181
  NONE: 'NONE',
169
182
  NOT_OPEN: 'NOT_OPEN',
@@ -61,12 +61,15 @@ import {
61
61
  WorkflowStartUpdateOutput,
62
62
  WorkflowStartUpdateWithStartInput,
63
63
  WorkflowStartUpdateWithStartOutput,
64
+ WorkflowStartOutput,
64
65
  } from './interceptors';
65
66
  import {
66
67
  CountWorkflowExecution,
67
68
  DescribeWorkflowExecutionResponse,
68
69
  encodeQueryRejectCondition,
69
70
  GetWorkflowExecutionHistoryRequest,
71
+ InternalConnectionLike,
72
+ InternalConnectionLikeSymbol,
70
73
  QueryRejectCondition,
71
74
  RequestCancelWorkflowExecutionResponse,
72
75
  StartWorkflowExecutionRequest,
@@ -94,6 +97,7 @@ import {
94
97
  import { mapAsyncIterable } from './iterators-utils';
95
98
  import { WorkflowUpdateStage, encodeWorkflowUpdateStage } from './workflow-update-stage';
96
99
  import { InternalWorkflowStartOptionsSymbol, InternalWorkflowStartOptions } from './internal';
100
+ import { adaptWorkflowClientInterceptor } from './interceptor-adapters';
97
101
 
98
102
  const UpdateWorkflowExecutionLifecycleStage = temporal.api.enums.v1.UpdateWorkflowExecutionLifecycleStage;
99
103
 
@@ -263,6 +267,15 @@ export interface WorkflowHandleWithFirstExecutionRunId<T extends Workflow = Work
263
267
  readonly firstExecutionRunId: string;
264
268
  }
265
269
 
270
+ /**
271
+ * This interface is exactly the same as {@link WorkflowHandleWithFirstExecutionRunId} except it
272
+ * includes the `eagerlyStarted` returned from {@link WorkflowClient.start}.
273
+ */
274
+ export interface WorkflowHandleWithStartDetails<T extends Workflow = Workflow>
275
+ extends WorkflowHandleWithFirstExecutionRunId<T> {
276
+ readonly eagerlyStarted: boolean;
277
+ }
278
+
266
279
  /**
267
280
  * This interface is exactly the same as {@link WorkflowHandle} except it
268
281
  * includes the `signaledRunId` returned from `signalWithStart`.
@@ -514,14 +527,19 @@ export class WorkflowClient extends BaseClient {
514
527
  workflowTypeOrFunc: string | T,
515
528
  options: WorkflowStartOptions<T>,
516
529
  interceptors: WorkflowClientInterceptor[]
517
- ): Promise<string> {
530
+ ): Promise<WorkflowStartOutput> {
518
531
  const workflowType = extractWorkflowType(workflowTypeOrFunc);
519
532
  assertRequiredWorkflowOptions(options);
520
533
  const compiledOptions = compileWorkflowOptions(ensureArgs(options));
534
+ const adaptedInterceptors = interceptors.map((i) => adaptWorkflowClientInterceptor(i));
521
535
 
522
- const start = composeInterceptors(interceptors, 'start', this._startWorkflowHandler.bind(this));
536
+ const startWithDetails = composeInterceptors(
537
+ adaptedInterceptors,
538
+ 'startWithDetails',
539
+ this._startWorkflowHandler.bind(this)
540
+ );
523
541
 
524
- return start({
542
+ return startWithDetails({
525
543
  options: compiledOptions,
526
544
  headers: {},
527
545
  workflowType,
@@ -537,7 +555,6 @@ export class WorkflowClient extends BaseClient {
537
555
  const { signal, signalArgs, ...rest } = options;
538
556
  assertRequiredWorkflowOptions(rest);
539
557
  const compiledOptions = compileWorkflowOptions(ensureArgs(rest));
540
-
541
558
  const signalWithStart = composeInterceptors(
542
559
  interceptors,
543
560
  'signalWithStart',
@@ -561,22 +578,25 @@ export class WorkflowClient extends BaseClient {
561
578
  public async start<T extends Workflow>(
562
579
  workflowTypeOrFunc: string | T,
563
580
  options: WorkflowStartOptions<T>
564
- ): Promise<WorkflowHandleWithFirstExecutionRunId<T>> {
581
+ ): Promise<WorkflowHandleWithStartDetails<T>> {
565
582
  const { workflowId } = options;
566
583
  const interceptors = this.getOrMakeInterceptors(workflowId);
567
- const runId = await this._start(workflowTypeOrFunc, { ...options, workflowId }, interceptors);
584
+ const wfStartOutput = await this._start(workflowTypeOrFunc, { ...options, workflowId }, interceptors);
568
585
  // runId is not used in handles created with `start*` calls because these
569
586
  // handles should allow interacting with the workflow if it continues as new.
570
- const handle = this._createWorkflowHandle({
587
+ const baseHandle = this._createWorkflowHandle({
571
588
  workflowId,
572
589
  runId: undefined,
573
- firstExecutionRunId: runId,
574
- runIdForResult: runId,
590
+ firstExecutionRunId: wfStartOutput.runId,
591
+ runIdForResult: wfStartOutput.runId,
575
592
  interceptors,
576
593
  followRuns: options.followRuns ?? true,
577
- }) as WorkflowHandleWithFirstExecutionRunId<T>; // Cast is safe because we know we add the firstExecutionRunId below
578
- (handle as any) /* readonly */.firstExecutionRunId = runId;
579
- return handle;
594
+ });
595
+ return {
596
+ ...baseHandle,
597
+ firstExecutionRunId: wfStartOutput.runId,
598
+ eagerlyStarted: wfStartOutput.eagerlyStarted,
599
+ };
580
600
  }
581
601
 
582
602
  /**
@@ -1246,7 +1266,7 @@ export class WorkflowClient extends BaseClient {
1246
1266
  *
1247
1267
  * Used as the final function of the start interceptor chain
1248
1268
  */
1249
- protected async _startWorkflowHandler(input: WorkflowStartInput): Promise<string> {
1269
+ protected async _startWorkflowHandler(input: WorkflowStartInput): Promise<WorkflowStartOutput> {
1250
1270
  const req = await this.createStartWorkflowRequest(input);
1251
1271
  const { options: opts, workflowType } = input;
1252
1272
  const internalOptions = (opts as InternalWorkflowStartOptions)[InternalWorkflowStartOptionsSymbol];
@@ -1255,7 +1275,10 @@ export class WorkflowClient extends BaseClient {
1255
1275
  if (internalOptions != null) {
1256
1276
  internalOptions.backLink = response.link ?? undefined;
1257
1277
  }
1258
- return response.runId;
1278
+ return {
1279
+ runId: response.runId,
1280
+ eagerlyStarted: response.eagerWorkflowTask != null,
1281
+ };
1259
1282
  } catch (err: any) {
1260
1283
  if (err.code === grpcStatus.ALREADY_EXISTS) {
1261
1284
  throw new WorkflowExecutionAlreadyStartedError(
@@ -1272,6 +1295,15 @@ export class WorkflowClient extends BaseClient {
1272
1295
  const { options: opts, workflowType, headers } = input;
1273
1296
  const { identity, namespace } = this.options;
1274
1297
  const internalOptions = (opts as InternalWorkflowStartOptions)[InternalWorkflowStartOptionsSymbol];
1298
+ const supportsEagerStart = (this.connection as InternalConnectionLike)?.[InternalConnectionLikeSymbol]
1299
+ ?.supportsEagerStart;
1300
+
1301
+ if (opts.requestEagerStart && !supportsEagerStart) {
1302
+ throw new Error(
1303
+ 'Eager workflow start requires a NativeConnection shared between client and worker. ' +
1304
+ 'Pass a NativeConnection via ClientOptions.connection, or disable requestEagerStart.'
1305
+ );
1306
+ }
1275
1307
 
1276
1308
  return {
1277
1309
  namespace,
@@ -1303,6 +1335,7 @@ export class WorkflowClient extends BaseClient {
1303
1335
  userMetadata: await encodeUserMetadata(this.dataConverter, opts.staticSummary, opts.staticDetails),
1304
1336
  priority: opts.priority ? compilePriority(opts.priority) : undefined,
1305
1337
  versioningOverride: opts.versioningOverride ?? undefined,
1338
+ requestEagerExecution: opts.requestEagerStart,
1306
1339
  ...filterNullAndUndefined(internalOptions ?? {}),
1307
1340
  };
1308
1341
  }
@@ -54,6 +54,12 @@ export interface WorkflowOptions extends CommonWorkflowOptions {
54
54
  * @experimental Deployment based versioning is experimental and may change in the future.
55
55
  */
56
56
  versioningOverride?: VersioningOverride;
57
+
58
+ /**
59
+ * Potentially reduce the latency to start this workflow by requesting that the server
60
+ * start it on a local worker running with this same client.
61
+ */
62
+ requestEagerStart?: boolean;
57
63
  }
58
64
 
59
65
  export type WithCompiledWorkflowOptions<T extends WorkflowOptions> = Replace<
@@ -97,7 +103,8 @@ export type WorkflowSignalWithStartOptions<SignalArgs extends any[] = []> = Sign
97
103
  ? WorkflowSignalWithStartOptionsWithArgs<SignalArgs>
98
104
  : WorkflowSignalWithStartOptionsWithoutArgs<SignalArgs>;
99
105
 
100
- export interface WorkflowSignalWithStartOptionsWithoutArgs<SignalArgs extends any[]> extends WorkflowOptions {
106
+ export interface WorkflowSignalWithStartOptionsWithoutArgs<SignalArgs extends any[]>
107
+ extends Omit<WorkflowOptions, 'requestEagerStart'> {
101
108
  /**
102
109
  * SignalDefinition or name of signal
103
110
  */
@@ -109,7 +116,8 @@ export interface WorkflowSignalWithStartOptionsWithoutArgs<SignalArgs extends an
109
116
  signalArgs?: SignalArgs;
110
117
  }
111
118
 
112
- export interface WorkflowSignalWithStartOptionsWithArgs<SignalArgs extends any[]> extends WorkflowOptions {
119
+ export interface WorkflowSignalWithStartOptionsWithArgs<SignalArgs extends any[]>
120
+ extends Omit<WorkflowOptions, 'requestEagerStart'> {
113
121
  /**
114
122
  * SignalDefinition or name of signal
115
123
  */