@temporalio/workflow 1.12.3 → 1.13.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/errors.js +2 -1
- package/lib/errors.js.map +1 -1
- package/lib/index.d.ts +1 -0
- package/lib/index.js +3 -1
- package/lib/index.js.map +1 -1
- package/lib/interceptors.d.ts +234 -133
- package/lib/interceptors.js +1 -3
- package/lib/interceptors.js.map +1 -1
- package/lib/internals.d.ts +15 -12
- package/lib/internals.js +65 -13
- package/lib/internals.js.map +1 -1
- package/lib/nexus.d.ts +82 -0
- package/lib/nexus.js +92 -0
- package/lib/nexus.js.map +1 -0
- package/lib/workflow.d.ts +2 -4
- package/lib/workflow.js.map +1 -1
- package/package.json +5 -4
- package/src/errors.ts +3 -2
- package/src/index.ts +5 -1
- package/src/interceptors.ts +279 -144
- package/src/internals.ts +95 -27
- package/src/nexus.ts +228 -0
- package/src/workflow.ts +2 -4
package/src/internals.ts
CHANGED
|
@@ -41,7 +41,14 @@ import { alea, RNG } from './alea';
|
|
|
41
41
|
import { RootCancellationScope } from './cancellation-scope';
|
|
42
42
|
import { UpdateScope } from './update-scope';
|
|
43
43
|
import { DeterminismViolationError, LocalActivityDoBackoff, isCancellation } from './errors';
|
|
44
|
-
import {
|
|
44
|
+
import {
|
|
45
|
+
QueryInput,
|
|
46
|
+
SignalInput,
|
|
47
|
+
StartNexusOperationOutput,
|
|
48
|
+
UpdateInput,
|
|
49
|
+
WorkflowExecuteInput,
|
|
50
|
+
WorkflowInterceptors,
|
|
51
|
+
} from './interceptors';
|
|
45
52
|
import {
|
|
46
53
|
ContinueAsNew,
|
|
47
54
|
DefaultSignalHandler,
|
|
@@ -95,10 +102,9 @@ export interface PromiseStackStore {
|
|
|
95
102
|
promiseToStack: Map<Promise<unknown>, Stack>;
|
|
96
103
|
}
|
|
97
104
|
|
|
98
|
-
export interface Completion {
|
|
99
|
-
resolve(val:
|
|
100
|
-
|
|
101
|
-
reject(reason: unknown): unknown;
|
|
105
|
+
export interface Completion<Success> {
|
|
106
|
+
resolve(val: Success): void;
|
|
107
|
+
reject(reason: Error): void;
|
|
102
108
|
}
|
|
103
109
|
|
|
104
110
|
export interface Condition {
|
|
@@ -127,6 +133,8 @@ interface MessageHandlerExecution {
|
|
|
127
133
|
id?: string;
|
|
128
134
|
}
|
|
129
135
|
|
|
136
|
+
type InferMapValue<T> = T extends Map<number, infer V> ? V : never;
|
|
137
|
+
|
|
130
138
|
/**
|
|
131
139
|
* Keeps all of the Workflow runtime state like pending completions for activities and timers.
|
|
132
140
|
*
|
|
@@ -150,16 +158,19 @@ export class Activator implements ActivationHandler {
|
|
|
150
158
|
* Cache for modules - referenced in reusable-vm.ts
|
|
151
159
|
*/
|
|
152
160
|
readonly moduleCache = new Map<string, unknown>();
|
|
161
|
+
|
|
153
162
|
/**
|
|
154
163
|
* Map of task sequence to a Completion
|
|
155
164
|
*/
|
|
156
165
|
readonly completions = {
|
|
157
|
-
timer: new Map<number, Completion
|
|
158
|
-
activity: new Map<number, Completion
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
166
|
+
timer: new Map<number, Completion<void>>(),
|
|
167
|
+
activity: new Map<number, Completion<unknown>>(),
|
|
168
|
+
nexusOperationStart: new Map<number, Completion<StartNexusOperationOutput>>(),
|
|
169
|
+
nexusOperationComplete: new Map<number, Completion<unknown>>(),
|
|
170
|
+
childWorkflowStart: new Map<number, Completion<string>>(),
|
|
171
|
+
childWorkflowComplete: new Map<number, Completion<unknown>>(),
|
|
172
|
+
signalWorkflow: new Map<number, Completion<void>>(),
|
|
173
|
+
cancelWorkflow: new Map<number, Completion<void>>(),
|
|
163
174
|
};
|
|
164
175
|
|
|
165
176
|
/**
|
|
@@ -381,6 +392,7 @@ export class Activator implements ActivationHandler {
|
|
|
381
392
|
signalWorkflow: 1,
|
|
382
393
|
cancelWorkflow: 1,
|
|
383
394
|
condition: 1,
|
|
395
|
+
nexusOperation: 1,
|
|
384
396
|
// Used internally to keep track of active stack traces
|
|
385
397
|
stack: 1,
|
|
386
398
|
};
|
|
@@ -519,7 +531,7 @@ export class Activator implements ActivationHandler {
|
|
|
519
531
|
|
|
520
532
|
public async startWorkflowNextHandler({ args }: WorkflowExecuteInput): Promise<any> {
|
|
521
533
|
const { workflow } = this;
|
|
522
|
-
if (workflow
|
|
534
|
+
if (workflow == null) {
|
|
523
535
|
throw new IllegalStateError('Workflow uninitialized');
|
|
524
536
|
}
|
|
525
537
|
return await workflow(...args);
|
|
@@ -583,12 +595,16 @@ export class Activator implements ActivationHandler {
|
|
|
583
595
|
resolve(result);
|
|
584
596
|
} else if (activation.result.failed) {
|
|
585
597
|
const { failure } = activation.result.failed;
|
|
586
|
-
|
|
587
|
-
|
|
598
|
+
if (failure == null) {
|
|
599
|
+
throw new TypeError('Got failed result with no failure attribute');
|
|
600
|
+
}
|
|
601
|
+
reject(this.failureToError(failure));
|
|
588
602
|
} else if (activation.result.cancelled) {
|
|
589
603
|
const { failure } = activation.result.cancelled;
|
|
590
|
-
|
|
591
|
-
|
|
604
|
+
if (failure == null) {
|
|
605
|
+
throw new TypeError('Got cancelled result with no failure attribute');
|
|
606
|
+
}
|
|
607
|
+
reject(this.failureToError(failure));
|
|
592
608
|
} else if (activation.result.backoff) {
|
|
593
609
|
reject(new LocalActivityDoBackoff(activation.result.backoff));
|
|
594
610
|
}
|
|
@@ -599,6 +615,9 @@ export class Activator implements ActivationHandler {
|
|
|
599
615
|
): void {
|
|
600
616
|
const { resolve, reject } = this.consumeCompletion('childWorkflowStart', getSeq(activation));
|
|
601
617
|
if (activation.succeeded) {
|
|
618
|
+
if (!activation.succeeded.runId) {
|
|
619
|
+
throw new TypeError('Got ResolveChildWorkflowExecutionStart with no runId');
|
|
620
|
+
}
|
|
602
621
|
resolve(activation.succeeded.runId);
|
|
603
622
|
} else if (activation.failed) {
|
|
604
623
|
if (decodeStartChildWorkflowExecutionFailedCause(activation.failed.cause) !== 'WORKFLOW_ALREADY_EXISTS') {
|
|
@@ -635,25 +654,68 @@ export class Activator implements ActivationHandler {
|
|
|
635
654
|
resolve(result);
|
|
636
655
|
} else if (activation.result.failed) {
|
|
637
656
|
const { failure } = activation.result.failed;
|
|
638
|
-
if (failure
|
|
657
|
+
if (failure == null) {
|
|
639
658
|
throw new TypeError('Got failed result with no failure attribute');
|
|
640
659
|
}
|
|
641
660
|
reject(this.failureToError(failure));
|
|
642
661
|
} else if (activation.result.cancelled) {
|
|
643
662
|
const { failure } = activation.result.cancelled;
|
|
644
|
-
if (failure
|
|
663
|
+
if (failure == null) {
|
|
645
664
|
throw new TypeError('Got cancelled result with no failure attribute');
|
|
646
665
|
}
|
|
647
666
|
reject(this.failureToError(failure));
|
|
648
667
|
}
|
|
649
668
|
}
|
|
650
669
|
|
|
651
|
-
public resolveNexusOperationStart(
|
|
652
|
-
|
|
670
|
+
public resolveNexusOperationStart(activation: coresdk.workflow_activation.IResolveNexusOperationStart): void {
|
|
671
|
+
const seq = getSeq(activation);
|
|
672
|
+
const { resolve, reject } = this.consumeCompletion('nexusOperationStart', seq);
|
|
673
|
+
|
|
674
|
+
if (!activation.failed) {
|
|
675
|
+
const completePromise = new Promise((resolve, reject) => {
|
|
676
|
+
this.completions.nexusOperationComplete.set(seq, {
|
|
677
|
+
resolve,
|
|
678
|
+
reject,
|
|
679
|
+
});
|
|
680
|
+
});
|
|
681
|
+
untrackPromise(completePromise);
|
|
682
|
+
untrackPromise(completePromise.catch(() => undefined));
|
|
683
|
+
|
|
684
|
+
resolve({ token: activation.operationToken!, result: completePromise });
|
|
685
|
+
} else {
|
|
686
|
+
reject(this.failureToError(activation.failed));
|
|
687
|
+
}
|
|
653
688
|
}
|
|
654
689
|
|
|
655
|
-
public resolveNexusOperation(
|
|
656
|
-
|
|
690
|
+
public resolveNexusOperation(activation: coresdk.workflow_activation.IResolveNexusOperation): void {
|
|
691
|
+
const seq = getSeq(activation);
|
|
692
|
+
|
|
693
|
+
if (activation.result?.completed) {
|
|
694
|
+
const result = this.payloadConverter.fromPayload(activation.result.completed);
|
|
695
|
+
|
|
696
|
+
// It is possible for ResolveNexusOperation to be received without a prior ResolveNexusOperationStart,
|
|
697
|
+
// e.g. because the handler completed the Operation synchronously.
|
|
698
|
+
const startCompletion = this.maybeConsumeCompletion('nexusOperationStart', seq);
|
|
699
|
+
if (startCompletion) {
|
|
700
|
+
startCompletion.resolve({ result: Promise.resolve(result) });
|
|
701
|
+
} else {
|
|
702
|
+
this.consumeCompletion('nexusOperationComplete', seq).resolve(result);
|
|
703
|
+
}
|
|
704
|
+
} else {
|
|
705
|
+
let err: Error;
|
|
706
|
+
if (activation.result?.failed) {
|
|
707
|
+
err = this.failureToError(activation.result.failed);
|
|
708
|
+
} else if (activation.result?.cancelled) {
|
|
709
|
+
err = this.failureToError(activation.result.cancelled);
|
|
710
|
+
} else if (activation.result?.timedOut) {
|
|
711
|
+
err = this.failureToError(activation.result.timedOut);
|
|
712
|
+
}
|
|
713
|
+
|
|
714
|
+
const completion =
|
|
715
|
+
this.maybeConsumeCompletion('nexusOperationStart', seq) ??
|
|
716
|
+
this.consumeCompletion('nexusOperationComplete', seq);
|
|
717
|
+
completion.reject(err!);
|
|
718
|
+
}
|
|
657
719
|
}
|
|
658
720
|
|
|
659
721
|
// Intentionally non-async function so this handler doesn't show up in the stack trace
|
|
@@ -749,7 +811,7 @@ export class Activator implements ActivationHandler {
|
|
|
749
811
|
: null);
|
|
750
812
|
|
|
751
813
|
// If we don't have an entry from either source, buffer and return
|
|
752
|
-
if (entry
|
|
814
|
+
if (entry == null) {
|
|
753
815
|
this.bufferedUpdates.push(activation);
|
|
754
816
|
return;
|
|
755
817
|
}
|
|
@@ -1152,16 +1214,22 @@ export class Activator implements ActivationHandler {
|
|
|
1152
1214
|
}
|
|
1153
1215
|
|
|
1154
1216
|
/** Consume a completion if it exists in Workflow state */
|
|
1155
|
-
private maybeConsumeCompletion
|
|
1217
|
+
private maybeConsumeCompletion<K extends keyof Activator['completions']>(
|
|
1218
|
+
type: K,
|
|
1219
|
+
taskSeq: number
|
|
1220
|
+
): InferMapValue<Activator['completions'][K]> | undefined {
|
|
1156
1221
|
const completion = this.completions[type].get(taskSeq);
|
|
1157
1222
|
if (completion !== undefined) {
|
|
1158
1223
|
this.completions[type].delete(taskSeq);
|
|
1159
1224
|
}
|
|
1160
|
-
return completion;
|
|
1225
|
+
return completion as InferMapValue<Activator['completions'][K]> | undefined;
|
|
1161
1226
|
}
|
|
1162
1227
|
|
|
1163
1228
|
/** Consume a completion if it exists in Workflow state, throws if it doesn't */
|
|
1164
|
-
private consumeCompletion
|
|
1229
|
+
private consumeCompletion<K extends keyof Activator['completions']>(
|
|
1230
|
+
type: K,
|
|
1231
|
+
taskSeq: number
|
|
1232
|
+
): InferMapValue<Activator['completions'][K]> {
|
|
1165
1233
|
const completion = this.maybeConsumeCompletion(type, taskSeq);
|
|
1166
1234
|
if (completion === undefined) {
|
|
1167
1235
|
throw new IllegalStateError(`No completion for taskSeq ${taskSeq}`);
|
|
@@ -1191,7 +1259,7 @@ export class Activator implements ActivationHandler {
|
|
|
1191
1259
|
|
|
1192
1260
|
function getSeq<T extends { seq?: number | null }>(activation: T): number {
|
|
1193
1261
|
const seq = activation.seq;
|
|
1194
|
-
if (seq
|
|
1262
|
+
if (seq == null) {
|
|
1195
1263
|
throw new TypeError(`Got activation with no seq attribute`);
|
|
1196
1264
|
}
|
|
1197
1265
|
return seq;
|
package/src/nexus.ts
ADDED
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
import * as nexus from 'nexus-rpc';
|
|
2
|
+
import { msOptionalToTs } from '@temporalio/common/lib/time';
|
|
3
|
+
import { userMetadataToPayload } from '@temporalio/common/lib/user-metadata';
|
|
4
|
+
import { composeInterceptors } from '@temporalio/common/lib/interceptors';
|
|
5
|
+
import { CancellationScope } from './cancellation-scope';
|
|
6
|
+
import { getActivator } from './global-attributes';
|
|
7
|
+
import { untrackPromise } from './stack-helpers';
|
|
8
|
+
import { StartNexusOperationInput, StartNexusOperationOutput, StartNexusOperationOptions } from './interceptors';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* A Nexus client for invoking Nexus Operations for a specific service from a Workflow.
|
|
12
|
+
*
|
|
13
|
+
* @experimental Nexus support in Temporal SDK is experimental.
|
|
14
|
+
*/
|
|
15
|
+
export interface NexusClient<T extends nexus.ServiceDefinition> {
|
|
16
|
+
/**
|
|
17
|
+
* Start a Nexus Operation and wait for its completion taking a {@link nexus.operation}.
|
|
18
|
+
* Returns the operation's result.
|
|
19
|
+
*
|
|
20
|
+
* @experimental Nexus support in Temporal SDK is experimental.
|
|
21
|
+
*/
|
|
22
|
+
executeOperation<O extends T['operations'][keyof T['operations']]>(
|
|
23
|
+
op: O,
|
|
24
|
+
input: nexus.OperationInput<O>,
|
|
25
|
+
options?: Partial<StartNexusOperationOptions>
|
|
26
|
+
): Promise<nexus.OperationOutput<O>>;
|
|
27
|
+
|
|
28
|
+
// TODO(nexus/post-initial-release): Revisit the "Operation Property Name" terminology,
|
|
29
|
+
// and reflect in the Nexus RPC SDK.
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Start a Nexus Operation and wait for its completion, taking an Operation's _property name_.
|
|
33
|
+
* Returns the operation's result.
|
|
34
|
+
*
|
|
35
|
+
* An Operation's _property name_ is the name of the property used to define that Operation in
|
|
36
|
+
* the {@link nexus.ServiceDefinition} object; it may differ from the value of the `name` property
|
|
37
|
+
* if one was explicitly specified on the {@link nexus.OperationDefinition} object.
|
|
38
|
+
*
|
|
39
|
+
* @experimental Nexus support in Temporal SDK is experimental.
|
|
40
|
+
*/
|
|
41
|
+
executeOperation<K extends nexus.OperationKey<T['operations']>>(
|
|
42
|
+
op: K,
|
|
43
|
+
input: nexus.OperationInput<T['operations'][K]>,
|
|
44
|
+
options?: Partial<StartNexusOperationOptions>
|
|
45
|
+
): Promise<nexus.OperationOutput<T['operations'][K]>>;
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Start a Nexus Operation taking a {@link nexus.operation}.
|
|
49
|
+
*
|
|
50
|
+
* Returns a handle that can be used to wait for the Operation's result.
|
|
51
|
+
*
|
|
52
|
+
* @experimental Nexus support in Temporal SDK is experimental.
|
|
53
|
+
*/
|
|
54
|
+
startOperation<O extends T['operations'][keyof T['operations']]>(
|
|
55
|
+
op: O,
|
|
56
|
+
input: nexus.OperationInput<O>,
|
|
57
|
+
options?: Partial<StartNexusOperationOptions>
|
|
58
|
+
): Promise<NexusOperationHandle<nexus.OperationOutput<O>>>;
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Start a Nexus Operation, taking an Operation's _property name_.
|
|
62
|
+
* Returns a handle that can be used to wait for the Operation's result.
|
|
63
|
+
*
|
|
64
|
+
* An Operation's _property name_ is the name of the property used to define that Operation in
|
|
65
|
+
* the {@link nexus.ServiceDefinition} object; it may differ from the value of the `name` property
|
|
66
|
+
* if one was explicitly specified on the {@link nexus.OperationDefinition} object.
|
|
67
|
+
*
|
|
68
|
+
* @experimental Nexus support in Temporal SDK is experimental.
|
|
69
|
+
*/
|
|
70
|
+
startOperation<K extends nexus.OperationKey<T['operations']>>(
|
|
71
|
+
op: K,
|
|
72
|
+
input: nexus.OperationInput<T['operations'][K]>,
|
|
73
|
+
options?: Partial<StartNexusOperationOptions>
|
|
74
|
+
): Promise<NexusOperationHandle<nexus.OperationOutput<T['operations'][K]>>>;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* A handle to a Nexus Operation.
|
|
79
|
+
*
|
|
80
|
+
* @experimental Nexus support in Temporal SDK is experimental.
|
|
81
|
+
*/
|
|
82
|
+
export interface NexusOperationHandle<T> {
|
|
83
|
+
/**
|
|
84
|
+
* The Operation's service name.
|
|
85
|
+
*/
|
|
86
|
+
readonly service: string;
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* The name of the Operation.
|
|
90
|
+
*/
|
|
91
|
+
readonly operation: string;
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Operation token as set by the Operation's handler. May be empty if the Operation completed synchronously.
|
|
95
|
+
*/
|
|
96
|
+
readonly token?: string;
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Wait for Operation completion and get its result.
|
|
100
|
+
*/
|
|
101
|
+
result(): Promise<T>;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Options for {@link createNexusClient}.
|
|
106
|
+
*/
|
|
107
|
+
export interface NexusClientOptions<T> {
|
|
108
|
+
endpoint: string;
|
|
109
|
+
service: T;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Create a Nexus client for invoking Nexus Operations from a Workflow.
|
|
114
|
+
*
|
|
115
|
+
* @experimental Nexus support in Temporal SDK is experimental.
|
|
116
|
+
*/
|
|
117
|
+
export function createNexusClient<T extends nexus.ServiceDefinition>(options: NexusClientOptions<T>): NexusClient<T> {
|
|
118
|
+
class NexusClientImpl<T extends nexus.ServiceDefinition> implements NexusClient<T> {
|
|
119
|
+
async executeOperation<O extends T['operations'][keyof T['operations']]>(
|
|
120
|
+
operation: string | T['operations'][nexus.OperationKey<T['operations']>],
|
|
121
|
+
input: nexus.OperationInput<T['operations'][nexus.OperationKey<T['operations']>]>,
|
|
122
|
+
operationOptions?: Partial<StartNexusOperationOptions>
|
|
123
|
+
): Promise<nexus.OperationOutput<O>> {
|
|
124
|
+
const handle = await this.startOperation(operation, input, operationOptions);
|
|
125
|
+
return await handle.result();
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
async startOperation<O extends T['operations'][keyof T['operations']]>(
|
|
129
|
+
operation: string | T['operations'][nexus.OperationKey<T['operations']>],
|
|
130
|
+
input: nexus.OperationInput<T['operations'][nexus.OperationKey<T['operations']>]>,
|
|
131
|
+
operationOptions?: StartNexusOperationOptions
|
|
132
|
+
) {
|
|
133
|
+
const opName = typeof operation === 'string' ? options.service.operations[operation]?.name : operation.name;
|
|
134
|
+
|
|
135
|
+
const activator = getActivator();
|
|
136
|
+
const seq = activator.nextSeqs.nexusOperation++;
|
|
137
|
+
|
|
138
|
+
const execute = composeInterceptors(
|
|
139
|
+
activator.interceptors.outbound,
|
|
140
|
+
'startNexusOperation',
|
|
141
|
+
startNexusOperationNextHandler
|
|
142
|
+
);
|
|
143
|
+
|
|
144
|
+
// TODO: Do we want to make the interceptor async like we do for child workflow? That seems redundant.
|
|
145
|
+
// REVIEW: I ended up changing this so that the interceptor returns a Promise<StartNexusOperationOutput>,
|
|
146
|
+
// and the result promise is contained in that Output object. As a consequence of this,
|
|
147
|
+
// the result promise/completion does not exist until the StartNexusOperation event is received.
|
|
148
|
+
// That's totally different from what we did in ChildWorkflow, but I think that's cleaner from
|
|
149
|
+
// interceptors point of view, and will make it easier to extend the API in the future.
|
|
150
|
+
const { token, result: resultPromise } = await execute({
|
|
151
|
+
endpoint: options.endpoint,
|
|
152
|
+
service: options.service.name,
|
|
153
|
+
operation: opName,
|
|
154
|
+
options: operationOptions ?? {},
|
|
155
|
+
headers: {},
|
|
156
|
+
seq,
|
|
157
|
+
input,
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
return {
|
|
161
|
+
service: options.service.name,
|
|
162
|
+
operation: opName,
|
|
163
|
+
token,
|
|
164
|
+
async result(): Promise<nexus.OperationOutput<O>> {
|
|
165
|
+
return resultPromise as nexus.OperationOutput<O>;
|
|
166
|
+
},
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
return new NexusClientImpl<T>();
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
function startNexusOperationNextHandler({
|
|
175
|
+
input,
|
|
176
|
+
endpoint,
|
|
177
|
+
service,
|
|
178
|
+
options,
|
|
179
|
+
operation,
|
|
180
|
+
seq,
|
|
181
|
+
headers,
|
|
182
|
+
}: StartNexusOperationInput): Promise<StartNexusOperationOutput> {
|
|
183
|
+
const activator = getActivator();
|
|
184
|
+
|
|
185
|
+
return new Promise<StartNexusOperationOutput>((resolve, reject) => {
|
|
186
|
+
const scope = CancellationScope.current();
|
|
187
|
+
if (scope.consideredCancelled) {
|
|
188
|
+
untrackPromise(scope.cancelRequested.catch(reject));
|
|
189
|
+
return;
|
|
190
|
+
}
|
|
191
|
+
if (scope.cancellable) {
|
|
192
|
+
untrackPromise(
|
|
193
|
+
scope.cancelRequested.catch(() => {
|
|
194
|
+
const completed =
|
|
195
|
+
!activator.completions.nexusOperationStart.has(seq) &&
|
|
196
|
+
!activator.completions.nexusOperationComplete.has(seq);
|
|
197
|
+
|
|
198
|
+
if (!completed) {
|
|
199
|
+
activator.pushCommand({
|
|
200
|
+
requestCancelNexusOperation: { seq },
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
// Nothing to cancel otherwise
|
|
205
|
+
})
|
|
206
|
+
);
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
activator.pushCommand({
|
|
210
|
+
scheduleNexusOperation: {
|
|
211
|
+
seq,
|
|
212
|
+
endpoint,
|
|
213
|
+
service,
|
|
214
|
+
operation,
|
|
215
|
+
nexusHeader: headers,
|
|
216
|
+
input: activator.payloadConverter.toPayload(input),
|
|
217
|
+
scheduleToCloseTimeout: msOptionalToTs(options?.scheduleToCloseTimeout),
|
|
218
|
+
// FIXME(nexus-post-initial-release): cancellationType is not supported yet
|
|
219
|
+
},
|
|
220
|
+
userMetadata: userMetadataToPayload(activator.payloadConverter, options?.summary, undefined),
|
|
221
|
+
});
|
|
222
|
+
|
|
223
|
+
activator.completions.nexusOperationStart.set(seq, {
|
|
224
|
+
resolve,
|
|
225
|
+
reject,
|
|
226
|
+
});
|
|
227
|
+
});
|
|
228
|
+
}
|
package/src/workflow.ts
CHANGED
|
@@ -523,8 +523,7 @@ export type ActivityFunctionWithOptions<T extends ActivityFunction> = T & {
|
|
|
523
523
|
* @param args: list of arguments
|
|
524
524
|
* @returns return value of the activity
|
|
525
525
|
*
|
|
526
|
-
* @experimental executeWithOptions is a new method to provide call-site options
|
|
527
|
-
* and is subject to change
|
|
526
|
+
* @experimental executeWithOptions is a new method to provide call-site options and is subject to change
|
|
528
527
|
*/
|
|
529
528
|
executeWithOptions(options: ActivityOptions, args: Parameters<T>): Promise<Awaited<ReturnType<T>>>;
|
|
530
529
|
};
|
|
@@ -545,8 +544,7 @@ export type LocalActivityFunctionWithOptions<T extends ActivityFunction> = T & {
|
|
|
545
544
|
* @param args: list of arguments
|
|
546
545
|
* @returns return value of the activity
|
|
547
546
|
*
|
|
548
|
-
* @experimental executeWithOptions is a new method to provide call-site options
|
|
549
|
-
* and is subject to change
|
|
547
|
+
* @experimental executeWithOptions is a new method to provide call-site options and is subject to change
|
|
550
548
|
*/
|
|
551
549
|
executeWithOptions(options: LocalActivityOptions, args: Parameters<T>): Promise<Awaited<ReturnType<T>>>;
|
|
552
550
|
};
|