@temporalio/client 1.2.0 → 1.4.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/async-completion-client.d.ts +17 -5
- package/lib/async-completion-client.js +28 -11
- package/lib/async-completion-client.js.map +1 -1
- package/lib/client.d.ts +92 -0
- package/lib/client.js +77 -0
- package/lib/client.js.map +1 -0
- package/lib/connection.d.ts +12 -4
- package/lib/connection.js +13 -4
- package/lib/connection.js.map +1 -1
- package/lib/grpc-retry.d.ts +51 -8
- package/lib/grpc-retry.js +73 -46
- package/lib/grpc-retry.js.map +1 -1
- package/lib/index.d.ts +6 -6
- package/lib/index.js +4 -3
- package/lib/index.js.map +1 -1
- package/lib/interceptors.d.ts +10 -2
- package/lib/types.d.ts +16 -15
- package/lib/types.js +28 -4
- package/lib/types.js.map +1 -1
- package/lib/workflow-client.d.ts +26 -10
- package/lib/workflow-client.js +51 -45
- package/lib/workflow-client.js.map +1 -1
- package/lib/workflow-options.d.ts +16 -5
- package/lib/workflow-options.js +1 -27
- package/lib/workflow-options.js.map +1 -1
- package/package.json +7 -9
- package/src/async-completion-client.ts +30 -8
- package/src/client.ts +151 -0
- package/src/connection.ts +21 -3
- package/src/grpc-retry.ts +129 -56
- package/src/index.ts +6 -5
- package/src/interceptors.ts +11 -2
- package/src/types.ts +19 -15
- package/src/workflow-client.ts +65 -49
- package/src/workflow-options.ts +21 -35
package/src/workflow-client.ts
CHANGED
|
@@ -18,23 +18,24 @@ import {
|
|
|
18
18
|
decodeOptionalFailureToOptionalError,
|
|
19
19
|
encodeMapToPayloads,
|
|
20
20
|
encodeToPayloads,
|
|
21
|
+
filterNullAndUndefined,
|
|
22
|
+
isLoadedDataConverter,
|
|
21
23
|
loadDataConverter,
|
|
22
|
-
} from '@temporalio/internal-non-workflow
|
|
24
|
+
} from '@temporalio/common/lib/internal-non-workflow';
|
|
23
25
|
import {
|
|
24
26
|
BaseWorkflowHandle,
|
|
25
27
|
compileRetryPolicy,
|
|
26
|
-
composeInterceptors,
|
|
27
|
-
optionalTsToDate,
|
|
28
28
|
QueryDefinition,
|
|
29
|
-
Replace,
|
|
30
29
|
SearchAttributes,
|
|
31
30
|
SignalDefinition,
|
|
32
|
-
tsToDate,
|
|
33
31
|
WithWorkflowArgs,
|
|
34
32
|
Workflow,
|
|
35
33
|
WorkflowNotFoundError,
|
|
36
34
|
WorkflowResultType,
|
|
37
|
-
} from '@temporalio/
|
|
35
|
+
} from '@temporalio/common';
|
|
36
|
+
import { optionalTsToDate, tsToDate } from '@temporalio/common/lib/time';
|
|
37
|
+
import { composeInterceptors } from '@temporalio/common/lib/interceptors';
|
|
38
|
+
import { Replace } from '@temporalio/common/lib/type-helpers';
|
|
38
39
|
import { temporal } from '@temporalio/proto';
|
|
39
40
|
import os from 'os';
|
|
40
41
|
import { v4 as uuid4 } from 'uuid';
|
|
@@ -118,7 +119,17 @@ export interface WorkflowHandle<T extends Workflow = Workflow> extends BaseWorkf
|
|
|
118
119
|
terminate(reason?: string): Promise<TerminateWorkflowExecutionResponse>;
|
|
119
120
|
|
|
120
121
|
/**
|
|
121
|
-
* Cancel a running Workflow
|
|
122
|
+
* Cancel a running Workflow.
|
|
123
|
+
*
|
|
124
|
+
* When a Workflow is cancelled, the root scope throws {@link CancelledFailure} with `message: 'Workflow canceled'`.
|
|
125
|
+
* That means that all cancellable scopes will throw `CancelledFailure`.
|
|
126
|
+
*
|
|
127
|
+
* Cancellation may be propagated to Activities depending on {@link ActivityOptions#cancellationType}, after which
|
|
128
|
+
* Activity calls may throw an {@link ActivityFailure}, and `isCancellation(error)` will be true (see {@link isCancellation}).
|
|
129
|
+
*
|
|
130
|
+
* Cancellation may be propagated to Child Workflows depending on {@link ChildWorkflowOptions#cancellationType}, after
|
|
131
|
+
* which calls to {@link executeChild} and {@link ChildWorkflowHandle#result} will throw, and `isCancellation(error)`
|
|
132
|
+
* will be true (see {@link isCancellation}).
|
|
122
133
|
*/
|
|
123
134
|
cancel(): Promise<RequestCancelWorkflowExecutionResponse>;
|
|
124
135
|
|
|
@@ -160,9 +171,9 @@ export interface WorkflowHandleWithSignaledRunId<T extends Workflow = Workflow>
|
|
|
160
171
|
|
|
161
172
|
export interface WorkflowClientOptions {
|
|
162
173
|
/**
|
|
163
|
-
* {@link DataConverter} to use for serializing and deserializing payloads
|
|
174
|
+
* {@link DataConverter} or {@link LoadedDataConverter} to use for serializing and deserializing payloads
|
|
164
175
|
*/
|
|
165
|
-
dataConverter?: DataConverter;
|
|
176
|
+
dataConverter?: DataConverter | LoadedDataConverter;
|
|
166
177
|
|
|
167
178
|
/**
|
|
168
179
|
* Used to override and extend default Connection functionality
|
|
@@ -285,7 +296,10 @@ interface WorkflowHandleOptions extends GetWorkflowHandleOptions {
|
|
|
285
296
|
export type WorkflowStartOptions<T extends Workflow = Workflow> = WithWorkflowArgs<T, WorkflowOptions>;
|
|
286
297
|
|
|
287
298
|
/**
|
|
288
|
-
* Client for starting Workflow executions and creating Workflow handles
|
|
299
|
+
* Client for starting Workflow executions and creating Workflow handles.
|
|
300
|
+
*
|
|
301
|
+
* Typically this client should not be instantiated directly, instead create the high level {@link Client} and use
|
|
302
|
+
* {@link Client.workflow} to interact with Workflows.
|
|
289
303
|
*/
|
|
290
304
|
export class WorkflowClient {
|
|
291
305
|
public readonly options: LoadedWorkflowClientOptions;
|
|
@@ -293,22 +307,29 @@ export class WorkflowClient {
|
|
|
293
307
|
|
|
294
308
|
constructor(options?: WorkflowClientOptions) {
|
|
295
309
|
this.connection = options?.connection ?? Connection.lazy();
|
|
310
|
+
const dataConverter = options?.dataConverter;
|
|
311
|
+
const loadedDataConverter = isLoadedDataConverter(dataConverter) ? dataConverter : loadDataConverter(dataConverter);
|
|
296
312
|
this.options = {
|
|
297
313
|
...defaultWorkflowClientOptions(),
|
|
298
|
-
...options,
|
|
299
|
-
loadedDataConverter
|
|
314
|
+
...filterNullAndUndefined(options ?? {}),
|
|
315
|
+
loadedDataConverter,
|
|
300
316
|
};
|
|
301
317
|
}
|
|
302
318
|
|
|
303
319
|
/**
|
|
304
320
|
* Raw gRPC access to the Temporal service.
|
|
305
321
|
*
|
|
306
|
-
* **NOTE**: The namespace provided in {@link options} is **not** automatically set on requests made
|
|
322
|
+
* **NOTE**: The namespace provided in {@link options} is **not** automatically set on requests made via this service
|
|
323
|
+
* object.
|
|
307
324
|
*/
|
|
308
325
|
get workflowService(): WorkflowService {
|
|
309
326
|
return this.connection.workflowService;
|
|
310
327
|
}
|
|
311
328
|
|
|
329
|
+
protected get dataConverter(): LoadedDataConverter {
|
|
330
|
+
return this.options.loadedDataConverter;
|
|
331
|
+
}
|
|
332
|
+
|
|
312
333
|
/**
|
|
313
334
|
* Set the deadline for any service requests executed in `fn`'s scope.
|
|
314
335
|
*/
|
|
@@ -377,7 +398,7 @@ export class WorkflowClient {
|
|
|
377
398
|
headers: {},
|
|
378
399
|
workflowType,
|
|
379
400
|
signalName: typeof signal === 'string' ? signal : signal.name,
|
|
380
|
-
signalArgs,
|
|
401
|
+
signalArgs: signalArgs ?? [],
|
|
381
402
|
});
|
|
382
403
|
}
|
|
383
404
|
|
|
@@ -409,15 +430,15 @@ export class WorkflowClient {
|
|
|
409
430
|
}
|
|
410
431
|
|
|
411
432
|
/**
|
|
412
|
-
* Sends a
|
|
413
|
-
* Useful when you're unsure
|
|
433
|
+
* Sends a Signal to a running Workflow or starts a new one if not already running and immediately Signals it.
|
|
434
|
+
* Useful when you're unsure whether the Workflow has been started.
|
|
414
435
|
*
|
|
415
|
-
* @returns a WorkflowHandle to the started Workflow
|
|
436
|
+
* @returns a {@link WorkflowHandle} to the started Workflow
|
|
416
437
|
*/
|
|
417
|
-
public async signalWithStart<
|
|
418
|
-
workflowTypeOrFunc: string |
|
|
419
|
-
options: WithWorkflowArgs<
|
|
420
|
-
): Promise<WorkflowHandleWithSignaledRunId<
|
|
438
|
+
public async signalWithStart<WorkflowFn extends Workflow, SignalArgs extends any[] = []>(
|
|
439
|
+
workflowTypeOrFunc: string | WorkflowFn,
|
|
440
|
+
options: WithWorkflowArgs<WorkflowFn, WorkflowSignalWithStartOptions<SignalArgs>>
|
|
441
|
+
): Promise<WorkflowHandleWithSignaledRunId<WorkflowFn>> {
|
|
421
442
|
const { workflowId } = options;
|
|
422
443
|
const interceptors = (this.options.interceptors.calls ?? []).map((ctor) => ctor({ workflowId }));
|
|
423
444
|
const runId = await this._signalWithStart(workflowTypeOrFunc, options, interceptors);
|
|
@@ -430,7 +451,7 @@ export class WorkflowClient {
|
|
|
430
451
|
runIdForResult: runId,
|
|
431
452
|
interceptors,
|
|
432
453
|
followRuns: options.followRuns ?? true,
|
|
433
|
-
}) as WorkflowHandleWithSignaledRunId<
|
|
454
|
+
}) as WorkflowHandleWithSignaledRunId<WorkflowFn>; // Cast is safe because we know we add the signaledRunId below
|
|
434
455
|
(handle as any) /* readonly */.signaledRunId = runId;
|
|
435
456
|
return handle;
|
|
436
457
|
}
|
|
@@ -506,7 +527,7 @@ export class WorkflowClient {
|
|
|
506
527
|
// Note that we can only return one value from our workflow function in JS.
|
|
507
528
|
// Ignore any other payloads in result
|
|
508
529
|
const [result] = await decodeArrayFromPayloads(
|
|
509
|
-
this.
|
|
530
|
+
this.dataConverter,
|
|
510
531
|
ev.workflowExecutionCompletedEventAttributes.result?.payloads
|
|
511
532
|
);
|
|
512
533
|
return result as any;
|
|
@@ -519,14 +540,14 @@ export class WorkflowClient {
|
|
|
519
540
|
const { failure, retryState } = ev.workflowExecutionFailedEventAttributes;
|
|
520
541
|
throw new WorkflowFailedError(
|
|
521
542
|
'Workflow execution failed',
|
|
522
|
-
await decodeOptionalFailureToOptionalError(this.
|
|
543
|
+
await decodeOptionalFailureToOptionalError(this.dataConverter, failure),
|
|
523
544
|
retryState ?? RetryState.RETRY_STATE_UNSPECIFIED
|
|
524
545
|
);
|
|
525
546
|
} else if (ev.workflowExecutionCanceledEventAttributes) {
|
|
526
547
|
const failure = new CancelledFailure(
|
|
527
548
|
'Workflow canceled',
|
|
528
549
|
await decodeArrayFromPayloads(
|
|
529
|
-
this.
|
|
550
|
+
this.dataConverter,
|
|
530
551
|
ev.workflowExecutionCanceledEventAttributes.details?.payloads
|
|
531
552
|
)
|
|
532
553
|
);
|
|
@@ -606,7 +627,7 @@ export class WorkflowClient {
|
|
|
606
627
|
execution: input.workflowExecution,
|
|
607
628
|
query: {
|
|
608
629
|
queryType: input.queryType,
|
|
609
|
-
queryArgs: { payloads: await encodeToPayloads(this.
|
|
630
|
+
queryArgs: { payloads: await encodeToPayloads(this.dataConverter, ...input.args) },
|
|
610
631
|
header: { fields: input.headers },
|
|
611
632
|
},
|
|
612
633
|
});
|
|
@@ -626,7 +647,7 @@ export class WorkflowClient {
|
|
|
626
647
|
throw new TypeError('Invalid response from server');
|
|
627
648
|
}
|
|
628
649
|
// We ignore anything but the first result
|
|
629
|
-
return await decodeFromPayloadsAtIndex(this.
|
|
650
|
+
return await decodeFromPayloadsAtIndex(this.dataConverter, 0, response.queryResult?.payloads);
|
|
630
651
|
}
|
|
631
652
|
|
|
632
653
|
/**
|
|
@@ -644,7 +665,7 @@ export class WorkflowClient {
|
|
|
644
665
|
// control is unused,
|
|
645
666
|
signalName: input.signalName,
|
|
646
667
|
header: { fields: input.headers },
|
|
647
|
-
input: { payloads: await encodeToPayloads(this.
|
|
668
|
+
input: { payloads: await encodeToPayloads(this.dataConverter, ...input.args) },
|
|
648
669
|
});
|
|
649
670
|
} catch (err) {
|
|
650
671
|
this.rethrowGrpcError(err, input.workflowExecution, 'Failed to signal Workflow');
|
|
@@ -667,9 +688,9 @@ export class WorkflowClient {
|
|
|
667
688
|
workflowId: options.workflowId,
|
|
668
689
|
workflowIdReusePolicy: options.workflowIdReusePolicy,
|
|
669
690
|
workflowType: { name: workflowType },
|
|
670
|
-
input: { payloads: await encodeToPayloads(this.
|
|
691
|
+
input: { payloads: await encodeToPayloads(this.dataConverter, ...options.args) },
|
|
671
692
|
signalName,
|
|
672
|
-
signalInput: { payloads: await encodeToPayloads(this.
|
|
693
|
+
signalInput: { payloads: await encodeToPayloads(this.dataConverter, ...signalArgs) },
|
|
673
694
|
taskQueue: {
|
|
674
695
|
kind: temporal.api.enums.v1.TaskQueueKind.TASK_QUEUE_KIND_UNSPECIFIED,
|
|
675
696
|
name: options.taskQueue,
|
|
@@ -678,9 +699,7 @@ export class WorkflowClient {
|
|
|
678
699
|
workflowRunTimeout: options.workflowRunTimeout,
|
|
679
700
|
workflowTaskTimeout: options.workflowTaskTimeout,
|
|
680
701
|
retryPolicy: options.retry ? compileRetryPolicy(options.retry) : undefined,
|
|
681
|
-
memo: options.memo
|
|
682
|
-
? { fields: await encodeMapToPayloads(this.options.loadedDataConverter, options.memo) }
|
|
683
|
-
: undefined,
|
|
702
|
+
memo: options.memo ? { fields: await encodeMapToPayloads(this.dataConverter, options.memo) } : undefined,
|
|
684
703
|
searchAttributes: options.searchAttributes
|
|
685
704
|
? {
|
|
686
705
|
indexedFields: mapToPayloads(searchAttributePayloadConverter, options.searchAttributes),
|
|
@@ -710,7 +729,7 @@ export class WorkflowClient {
|
|
|
710
729
|
workflowId: opts.workflowId,
|
|
711
730
|
workflowIdReusePolicy: opts.workflowIdReusePolicy,
|
|
712
731
|
workflowType: { name: workflowType },
|
|
713
|
-
input: { payloads: await encodeToPayloads(this.
|
|
732
|
+
input: { payloads: await encodeToPayloads(this.dataConverter, ...opts.args) },
|
|
714
733
|
taskQueue: {
|
|
715
734
|
kind: temporal.api.enums.v1.TaskQueueKind.TASK_QUEUE_KIND_UNSPECIFIED,
|
|
716
735
|
name: opts.taskQueue,
|
|
@@ -719,7 +738,7 @@ export class WorkflowClient {
|
|
|
719
738
|
workflowRunTimeout: opts.workflowRunTimeout,
|
|
720
739
|
workflowTaskTimeout: opts.workflowTaskTimeout,
|
|
721
740
|
retryPolicy: opts.retry ? compileRetryPolicy(opts.retry) : undefined,
|
|
722
|
-
memo: opts.memo ? { fields: await encodeMapToPayloads(this.
|
|
741
|
+
memo: opts.memo ? { fields: await encodeMapToPayloads(this.dataConverter, opts.memo) } : undefined,
|
|
723
742
|
searchAttributes: opts.searchAttributes
|
|
724
743
|
? {
|
|
725
744
|
indexedFields: mapToPayloads(searchAttributePayloadConverter, opts.searchAttributes),
|
|
@@ -757,9 +776,7 @@ export class WorkflowClient {
|
|
|
757
776
|
identity: this.options.identity,
|
|
758
777
|
...input,
|
|
759
778
|
details: {
|
|
760
|
-
payloads: input.details
|
|
761
|
-
? await encodeToPayloads(this.options.loadedDataConverter, ...input.details)
|
|
762
|
-
: undefined,
|
|
779
|
+
payloads: input.details ? await encodeToPayloads(this.dataConverter, ...input.details) : undefined,
|
|
763
780
|
},
|
|
764
781
|
firstExecutionRunId: input.firstExecutionRunId,
|
|
765
782
|
});
|
|
@@ -853,21 +870,20 @@ export class WorkflowClient {
|
|
|
853
870
|
code: raw.workflowExecutionInfo!.status!,
|
|
854
871
|
name: workflowStatusCodeToName(raw.workflowExecutionInfo!.status!),
|
|
855
872
|
},
|
|
856
|
-
//
|
|
857
|
-
|
|
858
|
-
// Max history length is 50k, which is much less than Number.MAX_SAFE_INTEGER
|
|
859
|
-
historyLength: raw.workflowExecutionInfo!.historyLength!,
|
|
873
|
+
// Safe to convert to number, max history length is 50k, which is much less than Number.MAX_SAFE_INTEGER
|
|
874
|
+
historyLength: raw.workflowExecutionInfo!.historyLength!.toNumber(),
|
|
860
875
|
startTime: tsToDate(raw.workflowExecutionInfo!.startTime!),
|
|
861
876
|
executionTime: optionalTsToDate(raw.workflowExecutionInfo!.executionTime),
|
|
862
877
|
closeTime: optionalTsToDate(raw.workflowExecutionInfo!.closeTime),
|
|
863
|
-
memo: await decodeMapFromPayloads(
|
|
864
|
-
|
|
865
|
-
|
|
878
|
+
memo: await decodeMapFromPayloads(this.client.dataConverter, raw.workflowExecutionInfo!.memo?.fields),
|
|
879
|
+
searchAttributes: Object.fromEntries(
|
|
880
|
+
Object.entries(
|
|
881
|
+
mapFromPayloads(
|
|
882
|
+
searchAttributePayloadConverter,
|
|
883
|
+
raw.workflowExecutionInfo!.searchAttributes?.indexedFields ?? {}
|
|
884
|
+
) as SearchAttributes
|
|
885
|
+
).filter(([_, v]) => v && v.length > 0) // Filter out empty arrays returned by pre 1.18 servers
|
|
866
886
|
),
|
|
867
|
-
searchAttributes: mapFromPayloads(
|
|
868
|
-
searchAttributePayloadConverter,
|
|
869
|
-
raw.workflowExecutionInfo!.searchAttributes?.indexedFields ?? {}
|
|
870
|
-
) as SearchAttributes,
|
|
871
887
|
parentExecution: raw.workflowExecutionInfo?.parentExecution
|
|
872
888
|
? {
|
|
873
889
|
workflowId: raw.workflowExecutionInfo.parentExecution.workflowId!,
|
package/src/workflow-options.ts
CHANGED
|
@@ -1,10 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
CommonWorkflowOptions,
|
|
3
|
-
SignalDefinition,
|
|
4
|
-
WithCompiledWorkflowOptions,
|
|
5
|
-
} from '@temporalio/internal-workflow-common';
|
|
1
|
+
import { CommonWorkflowOptions, SignalDefinition, WithCompiledWorkflowOptions } from '@temporalio/common';
|
|
6
2
|
|
|
7
|
-
export * from '@temporalio/
|
|
3
|
+
export * from '@temporalio/common/lib/workflow-options';
|
|
8
4
|
|
|
9
5
|
export interface CompiledWorkflowOptions extends WithCompiledWorkflowOptions<WorkflowOptions> {
|
|
10
6
|
args: unknown[];
|
|
@@ -37,40 +33,30 @@ export interface WorkflowOptions extends CommonWorkflowOptions {
|
|
|
37
33
|
followRuns?: boolean;
|
|
38
34
|
}
|
|
39
35
|
|
|
40
|
-
export
|
|
36
|
+
export type WorkflowSignalWithStartOptions<SignalArgs extends any[] = []> = SignalArgs extends [any, ...any[]]
|
|
37
|
+
? WorkflowSignalWithStartOptionsWithArgs<SignalArgs>
|
|
38
|
+
: WorkflowSignalWithStartOptionsWithoutArgs<SignalArgs>;
|
|
39
|
+
|
|
40
|
+
export interface WorkflowSignalWithStartOptionsWithoutArgs<SignalArgs extends any[]> extends WorkflowOptions {
|
|
41
41
|
/**
|
|
42
42
|
* SignalDefinition or name of signal
|
|
43
43
|
*/
|
|
44
|
-
signal: SignalDefinition
|
|
44
|
+
signal: SignalDefinition | string;
|
|
45
|
+
|
|
45
46
|
/**
|
|
46
47
|
* Arguments to invoke the signal handler with
|
|
47
48
|
*/
|
|
48
|
-
signalArgs
|
|
49
|
+
signalArgs?: SignalArgs;
|
|
49
50
|
}
|
|
50
51
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
//
|
|
63
|
-
// /**
|
|
64
|
-
// * Adds default values to `workflowId` and `workflowIdReusePolicy` to given workflow options.
|
|
65
|
-
// */
|
|
66
|
-
// export function addDefaults<T extends Workflow>(
|
|
67
|
-
// opts: WithWorkflowArgs<T, WorkflowOptions>
|
|
68
|
-
// ): WorkflowOptionsWithDefaults<T> {
|
|
69
|
-
// const { workflowId, args, ...rest } = opts;
|
|
70
|
-
// return {
|
|
71
|
-
// followRuns: true,
|
|
72
|
-
// args: args ?? [],
|
|
73
|
-
// workflowId: workflowId ?? uuid4(),
|
|
74
|
-
// ...rest,
|
|
75
|
-
// };
|
|
76
|
-
// }
|
|
52
|
+
export interface WorkflowSignalWithStartOptionsWithArgs<SignalArgs extends any[]> extends WorkflowOptions {
|
|
53
|
+
/**
|
|
54
|
+
* SignalDefinition or name of signal
|
|
55
|
+
*/
|
|
56
|
+
signal: SignalDefinition<SignalArgs> | string;
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Arguments to invoke the signal handler with
|
|
60
|
+
*/
|
|
61
|
+
signalArgs: SignalArgs;
|
|
62
|
+
}
|