@temporalio/workflow 0.21.0 → 1.0.0-rc.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/README.md +2 -2
- package/lib/cancellation-scope.js +6 -2
- package/lib/cancellation-scope.js.map +1 -1
- package/lib/index.d.ts +5 -5
- package/lib/index.js +4 -4
- package/lib/index.js.map +1 -1
- package/lib/interceptors.d.ts +18 -18
- package/lib/interfaces.d.ts +77 -10
- package/lib/interfaces.js.map +1 -1
- package/lib/internals.d.ts +18 -3
- package/lib/internals.js +49 -14
- package/lib/internals.js.map +1 -1
- package/lib/stack-helpers.d.ts +4 -0
- package/lib/stack-helpers.js +15 -0
- package/lib/stack-helpers.js.map +1 -0
- package/lib/trigger.d.ts +5 -4
- package/lib/trigger.js +10 -7
- package/lib/trigger.js.map +1 -1
- package/lib/worker-interface.d.ts +6 -3
- package/lib/worker-interface.js +21 -24
- package/lib/worker-interface.js.map +1 -1
- package/lib/workflow-handle.d.ts +5 -2
- package/lib/workflow.d.ts +70 -11
- package/lib/workflow.js +184 -76
- package/lib/workflow.js.map +1 -1
- package/package.json +5 -4
package/lib/workflow.js
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.setHandler = exports.defineQuery = exports.defineSignal = exports.condition = exports.deprecatePatch = exports.patched = exports.uuid4 = exports.continueAsNew = exports.makeContinueAsNewFunc = exports.proxySinks = exports.workflowInfo = exports.executeChild = exports.startChild = exports.getExternalWorkflowHandle = exports.proxyLocalActivities = exports.proxyActivities = exports.scheduleLocalActivity = exports.scheduleActivity = exports.
|
|
3
|
+
exports.stackTraceQuery = exports.taskInfo = exports.upsertSearchAttributes = exports.setHandler = exports.defineQuery = exports.defineSignal = exports.condition = exports.deprecatePatch = exports.patched = exports.uuid4 = exports.continueAsNew = exports.makeContinueAsNewFunc = exports.proxySinks = exports.inWorkflowContext = exports.workflowInfo = exports.executeChild = exports.startChild = exports.getExternalWorkflowHandle = exports.proxyLocalActivities = exports.proxyActivities = exports.scheduleLocalActivity = exports.scheduleActivity = exports.sleep = exports.addDefaultWorkflowOptions = void 0;
|
|
4
4
|
const common_1 = require("@temporalio/common");
|
|
5
5
|
const internal_workflow_common_1 = require("@temporalio/internal-workflow-common");
|
|
6
6
|
const cancellation_scope_1 = require("./cancellation-scope");
|
|
7
7
|
const interfaces_1 = require("./interfaces");
|
|
8
8
|
const internals_1 = require("./internals");
|
|
9
|
+
const stack_helpers_1 = require("./stack-helpers");
|
|
9
10
|
// Avoid a circular dependency
|
|
10
11
|
(0, cancellation_scope_1.registerSleepImplementation)(sleep);
|
|
11
12
|
/**
|
|
@@ -28,13 +29,13 @@ function timerNextHandler(input) {
|
|
|
28
29
|
return new Promise((resolve, reject) => {
|
|
29
30
|
const scope = cancellation_scope_1.CancellationScope.current();
|
|
30
31
|
if (scope.consideredCancelled) {
|
|
31
|
-
scope.cancelRequested.catch(reject);
|
|
32
|
+
(0, stack_helpers_1.untrackPromise)(scope.cancelRequested.catch(reject));
|
|
32
33
|
return;
|
|
33
34
|
}
|
|
34
35
|
if (scope.cancellable) {
|
|
35
|
-
scope.cancelRequested.catch((err) => {
|
|
36
|
+
(0, stack_helpers_1.untrackPromise)(scope.cancelRequested.catch((err) => {
|
|
36
37
|
if (!internals_1.state.completions.timer.delete(input.seq)) {
|
|
37
|
-
return; // Already resolved
|
|
38
|
+
return; // Already resolved or never scheduled
|
|
38
39
|
}
|
|
39
40
|
internals_1.state.pushCommand({
|
|
40
41
|
cancelTimer: {
|
|
@@ -42,18 +43,18 @@ function timerNextHandler(input) {
|
|
|
42
43
|
},
|
|
43
44
|
});
|
|
44
45
|
reject(err);
|
|
45
|
-
});
|
|
46
|
+
}));
|
|
46
47
|
}
|
|
47
|
-
internals_1.state.completions.timer.set(input.seq, {
|
|
48
|
-
resolve,
|
|
49
|
-
reject,
|
|
50
|
-
});
|
|
51
48
|
internals_1.state.pushCommand({
|
|
52
49
|
startTimer: {
|
|
53
50
|
seq: input.seq,
|
|
54
51
|
startToFireTimeout: (0, internal_workflow_common_1.msToTs)(input.durationMs),
|
|
55
52
|
},
|
|
56
53
|
});
|
|
54
|
+
internals_1.state.completions.timer.set(input.seq, {
|
|
55
|
+
resolve,
|
|
56
|
+
reject,
|
|
57
|
+
});
|
|
57
58
|
});
|
|
58
59
|
}
|
|
59
60
|
/**
|
|
@@ -61,28 +62,24 @@ function timerNextHandler(input) {
|
|
|
61
62
|
*
|
|
62
63
|
* Schedules a timer on the Temporal service.
|
|
63
64
|
*
|
|
64
|
-
* @param ms sleep duration - {@link https://www.npmjs.com/package/ms | ms} formatted string or number of milliseconds.
|
|
65
|
-
*
|
|
65
|
+
* @param ms sleep duration - {@link https://www.npmjs.com/package/ms | ms} formatted string or number of milliseconds.
|
|
66
|
+
* If given a negative number or 0, value will be set to 1.
|
|
66
67
|
*/
|
|
67
68
|
function sleep(ms) {
|
|
68
69
|
const seq = internals_1.state.nextSeqs.timer++;
|
|
69
|
-
const execute = (0, internal_workflow_common_1.composeInterceptors)(internals_1.state.interceptors.outbound, 'startTimer', timerNextHandler);
|
|
70
70
|
const durationMs = Math.max(1, (0, internal_workflow_common_1.msToNumber)(ms));
|
|
71
|
+
const execute = (0, internal_workflow_common_1.composeInterceptors)(internals_1.state.interceptors.outbound, 'startTimer', timerNextHandler);
|
|
71
72
|
return execute({
|
|
72
73
|
durationMs,
|
|
73
74
|
seq,
|
|
74
75
|
});
|
|
75
76
|
}
|
|
76
77
|
exports.sleep = sleep;
|
|
77
|
-
/**
|
|
78
|
-
* @hidden
|
|
79
|
-
*/
|
|
80
78
|
function validateActivityOptions(options) {
|
|
81
79
|
if (options.scheduleToCloseTimeout === undefined && options.startToCloseTimeout === undefined) {
|
|
82
80
|
throw new TypeError('Required either scheduleToCloseTimeout or startToCloseTimeout');
|
|
83
81
|
}
|
|
84
82
|
}
|
|
85
|
-
exports.validateActivityOptions = validateActivityOptions;
|
|
86
83
|
// Use same validation we use for normal activities
|
|
87
84
|
const validateLocalActivityOptions = validateActivityOptions;
|
|
88
85
|
/**
|
|
@@ -93,30 +90,26 @@ const validateLocalActivityOptions = validateActivityOptions;
|
|
|
93
90
|
/**
|
|
94
91
|
* Push a scheduleActivity command into state accumulator and register completion
|
|
95
92
|
*/
|
|
96
|
-
|
|
93
|
+
function scheduleActivityNextHandler({ options, args, headers, seq, activityType }) {
|
|
97
94
|
validateActivityOptions(options);
|
|
98
95
|
return new Promise((resolve, reject) => {
|
|
99
96
|
const scope = cancellation_scope_1.CancellationScope.current();
|
|
100
97
|
if (scope.consideredCancelled) {
|
|
101
|
-
scope.cancelRequested.catch(reject);
|
|
98
|
+
(0, stack_helpers_1.untrackPromise)(scope.cancelRequested.catch(reject));
|
|
102
99
|
return;
|
|
103
100
|
}
|
|
104
101
|
if (scope.cancellable) {
|
|
105
|
-
scope.cancelRequested.catch(() => {
|
|
102
|
+
(0, stack_helpers_1.untrackPromise)(scope.cancelRequested.catch(() => {
|
|
106
103
|
if (!internals_1.state.completions.activity.has(seq)) {
|
|
107
|
-
return; // Already resolved
|
|
104
|
+
return; // Already resolved or never scheduled
|
|
108
105
|
}
|
|
109
106
|
internals_1.state.pushCommand({
|
|
110
107
|
requestCancelActivity: {
|
|
111
108
|
seq,
|
|
112
109
|
},
|
|
113
110
|
});
|
|
114
|
-
});
|
|
111
|
+
}));
|
|
115
112
|
}
|
|
116
|
-
internals_1.state.completions.activity.set(seq, {
|
|
117
|
-
resolve,
|
|
118
|
-
reject,
|
|
119
|
-
});
|
|
120
113
|
internals_1.state.pushCommand({
|
|
121
114
|
scheduleActivity: {
|
|
122
115
|
seq,
|
|
@@ -133,6 +126,10 @@ async function scheduleActivityNextHandler({ options, args, headers, seq, activi
|
|
|
133
126
|
cancellationType: options.cancellationType,
|
|
134
127
|
},
|
|
135
128
|
});
|
|
129
|
+
internals_1.state.completions.activity.set(seq, {
|
|
130
|
+
resolve,
|
|
131
|
+
reject,
|
|
132
|
+
});
|
|
136
133
|
});
|
|
137
134
|
}
|
|
138
135
|
/**
|
|
@@ -143,25 +140,21 @@ async function scheduleLocalActivityNextHandler({ options, args, headers, seq, a
|
|
|
143
140
|
return new Promise((resolve, reject) => {
|
|
144
141
|
const scope = cancellation_scope_1.CancellationScope.current();
|
|
145
142
|
if (scope.consideredCancelled) {
|
|
146
|
-
scope.cancelRequested.catch(reject);
|
|
143
|
+
(0, stack_helpers_1.untrackPromise)(scope.cancelRequested.catch(reject));
|
|
147
144
|
return;
|
|
148
145
|
}
|
|
149
146
|
if (scope.cancellable) {
|
|
150
|
-
scope.cancelRequested.catch(() => {
|
|
147
|
+
(0, stack_helpers_1.untrackPromise)(scope.cancelRequested.catch(() => {
|
|
151
148
|
if (!internals_1.state.completions.activity.has(seq)) {
|
|
152
|
-
return; // Already resolved
|
|
149
|
+
return; // Already resolved or never scheduled
|
|
153
150
|
}
|
|
154
151
|
internals_1.state.pushCommand({
|
|
155
152
|
requestCancelLocalActivity: {
|
|
156
153
|
seq,
|
|
157
154
|
},
|
|
158
155
|
});
|
|
159
|
-
});
|
|
156
|
+
}));
|
|
160
157
|
}
|
|
161
|
-
internals_1.state.completions.activity.set(seq, {
|
|
162
|
-
resolve,
|
|
163
|
-
reject,
|
|
164
|
-
});
|
|
165
158
|
internals_1.state.pushCommand({
|
|
166
159
|
scheduleLocalActivity: {
|
|
167
160
|
seq,
|
|
@@ -171,7 +164,7 @@ async function scheduleLocalActivityNextHandler({ options, args, headers, seq, a
|
|
|
171
164
|
activityId: `${seq}`,
|
|
172
165
|
activityType,
|
|
173
166
|
arguments: (0, common_1.toPayloads)(internals_1.state.payloadConverter, ...args),
|
|
174
|
-
retryPolicy: options.retry ? (0, internal_workflow_common_1.compileRetryPolicy)(options.retry) :
|
|
167
|
+
retryPolicy: options.retry ? (0, internal_workflow_common_1.compileRetryPolicy)(options.retry) : undefined,
|
|
175
168
|
scheduleToCloseTimeout: (0, internal_workflow_common_1.msOptionalToTs)(options.scheduleToCloseTimeout),
|
|
176
169
|
startToCloseTimeout: (0, internal_workflow_common_1.msOptionalToTs)(options.startToCloseTimeout),
|
|
177
170
|
scheduleToStartTimeout: (0, internal_workflow_common_1.msOptionalToTs)(options.scheduleToStartTimeout),
|
|
@@ -180,6 +173,10 @@ async function scheduleLocalActivityNextHandler({ options, args, headers, seq, a
|
|
|
180
173
|
cancellationType: options.cancellationType,
|
|
181
174
|
},
|
|
182
175
|
});
|
|
176
|
+
internals_1.state.completions.activity.set(seq, {
|
|
177
|
+
resolve,
|
|
178
|
+
reject,
|
|
179
|
+
});
|
|
183
180
|
});
|
|
184
181
|
}
|
|
185
182
|
/**
|
|
@@ -241,16 +238,16 @@ async function scheduleLocalActivity(activityType, args, options) {
|
|
|
241
238
|
}
|
|
242
239
|
}
|
|
243
240
|
exports.scheduleLocalActivity = scheduleLocalActivity;
|
|
244
|
-
|
|
241
|
+
function startChildWorkflowExecutionNextHandler({ options, headers, workflowType, seq, }) {
|
|
245
242
|
const workflowId = options.workflowId ?? uuid4();
|
|
246
243
|
const startPromise = new Promise((resolve, reject) => {
|
|
247
244
|
const scope = cancellation_scope_1.CancellationScope.current();
|
|
248
245
|
if (scope.consideredCancelled) {
|
|
249
|
-
scope.cancelRequested.catch(reject);
|
|
246
|
+
(0, stack_helpers_1.untrackPromise)(scope.cancelRequested.catch(reject));
|
|
250
247
|
return;
|
|
251
248
|
}
|
|
252
249
|
if (scope.cancellable) {
|
|
253
|
-
scope.cancelRequested.catch(() => {
|
|
250
|
+
(0, stack_helpers_1.untrackPromise)(scope.cancelRequested.catch(() => {
|
|
254
251
|
const complete = !internals_1.state.completions.childWorkflowComplete.has(seq);
|
|
255
252
|
const started = !internals_1.state.completions.childWorkflowStart.has(seq);
|
|
256
253
|
if (started && !complete) {
|
|
@@ -270,12 +267,8 @@ async function startChildWorkflowExecutionNextHandler({ options, headers, workfl
|
|
|
270
267
|
});
|
|
271
268
|
}
|
|
272
269
|
// Nothing to cancel otherwise
|
|
273
|
-
});
|
|
270
|
+
}));
|
|
274
271
|
}
|
|
275
|
-
internals_1.state.completions.childWorkflowStart.set(seq, {
|
|
276
|
-
resolve,
|
|
277
|
-
reject,
|
|
278
|
-
});
|
|
279
272
|
internals_1.state.pushCommand({
|
|
280
273
|
startChildWorkflowExecution: {
|
|
281
274
|
seq,
|
|
@@ -299,43 +292,52 @@ async function startChildWorkflowExecutionNextHandler({ options, headers, workfl
|
|
|
299
292
|
memo: options.memo && (0, common_1.mapToPayloads)(internals_1.state.payloadConverter, options.memo),
|
|
300
293
|
},
|
|
301
294
|
});
|
|
295
|
+
internals_1.state.completions.childWorkflowStart.set(seq, {
|
|
296
|
+
resolve,
|
|
297
|
+
reject,
|
|
298
|
+
});
|
|
302
299
|
});
|
|
303
300
|
// We construct a Promise for the completion of the child Workflow before we know
|
|
304
301
|
// if the Workflow code will await it to capture the result in case it does.
|
|
305
302
|
const completePromise = new Promise((resolve, reject) => {
|
|
306
303
|
// Chain start Promise rejection to the complete Promise.
|
|
307
|
-
startPromise.catch(reject);
|
|
304
|
+
(0, stack_helpers_1.untrackPromise)(startPromise.catch(reject));
|
|
308
305
|
internals_1.state.completions.childWorkflowComplete.set(seq, {
|
|
309
306
|
resolve,
|
|
310
307
|
reject,
|
|
311
308
|
});
|
|
312
309
|
});
|
|
310
|
+
(0, stack_helpers_1.untrackPromise)(startPromise);
|
|
311
|
+
(0, stack_helpers_1.untrackPromise)(completePromise);
|
|
313
312
|
// Prevent unhandled rejection because the completion might not be awaited
|
|
314
|
-
completePromise.catch(() => undefined);
|
|
315
|
-
|
|
313
|
+
(0, stack_helpers_1.untrackPromise)(completePromise.catch(() => undefined));
|
|
314
|
+
const ret = new Promise((resolve) => resolve([startPromise, completePromise]));
|
|
315
|
+
(0, stack_helpers_1.untrackPromise)(ret);
|
|
316
|
+
return ret;
|
|
316
317
|
}
|
|
317
|
-
function signalWorkflowNextHandler({ seq, signalName, args, target }) {
|
|
318
|
+
function signalWorkflowNextHandler({ seq, signalName, args, target, headers }) {
|
|
318
319
|
return new Promise((resolve, reject) => {
|
|
319
320
|
if (internals_1.state.info === undefined) {
|
|
320
321
|
throw new internal_workflow_common_1.IllegalStateError('Workflow uninitialized');
|
|
321
322
|
}
|
|
322
323
|
const scope = cancellation_scope_1.CancellationScope.current();
|
|
323
324
|
if (scope.consideredCancelled) {
|
|
324
|
-
scope.cancelRequested.catch(reject);
|
|
325
|
+
(0, stack_helpers_1.untrackPromise)(scope.cancelRequested.catch(reject));
|
|
325
326
|
return;
|
|
326
327
|
}
|
|
327
328
|
if (scope.cancellable) {
|
|
328
|
-
scope.cancelRequested.catch(() => {
|
|
329
|
+
(0, stack_helpers_1.untrackPromise)(scope.cancelRequested.catch(() => {
|
|
329
330
|
if (!internals_1.state.completions.signalWorkflow.has(seq)) {
|
|
330
331
|
return;
|
|
331
332
|
}
|
|
332
333
|
internals_1.state.pushCommand({ cancelSignalWorkflow: { seq } });
|
|
333
|
-
});
|
|
334
|
+
}));
|
|
334
335
|
}
|
|
335
336
|
internals_1.state.pushCommand({
|
|
336
337
|
signalExternalWorkflowExecution: {
|
|
337
338
|
seq,
|
|
338
339
|
args: (0, common_1.toPayloads)(internals_1.state.payloadConverter, ...args),
|
|
340
|
+
headers,
|
|
339
341
|
signalName,
|
|
340
342
|
...(target.type === 'external'
|
|
341
343
|
? {
|
|
@@ -403,7 +405,7 @@ function proxyActivities(options) {
|
|
|
403
405
|
if (typeof activityType !== 'string') {
|
|
404
406
|
throw new TypeError(`Only strings are supported for Activity types, got: ${String(activityType)}`);
|
|
405
407
|
}
|
|
406
|
-
return (...args)
|
|
408
|
+
return function activityProxyFunction(...args) {
|
|
407
409
|
return scheduleActivity(activityType, args, options);
|
|
408
410
|
};
|
|
409
411
|
},
|
|
@@ -435,13 +437,15 @@ function proxyLocalActivities(options) {
|
|
|
435
437
|
if (typeof activityType !== 'string') {
|
|
436
438
|
throw new TypeError(`Only strings are supported for Activity types, got: ${String(activityType)}`);
|
|
437
439
|
}
|
|
438
|
-
return (...args)
|
|
440
|
+
return function localActivityProxyFunction(...args) {
|
|
439
441
|
return scheduleLocalActivity(activityType, args, options);
|
|
440
442
|
};
|
|
441
443
|
},
|
|
442
444
|
});
|
|
443
445
|
}
|
|
444
446
|
exports.proxyLocalActivities = proxyLocalActivities;
|
|
447
|
+
// TODO: deprecate this patch after "enough" time has passed
|
|
448
|
+
const EXTERNAL_WF_CANCEL_PATCH = '__temporal_internal_connect_external_handle_cancel_to_scope';
|
|
445
449
|
/**
|
|
446
450
|
* Returns a client-side handle that can be used to signal and cancel an existing Workflow execution.
|
|
447
451
|
* It takes a Workflow ID and optional run ID.
|
|
@@ -455,6 +459,26 @@ function getExternalWorkflowHandle(workflowId, runId) {
|
|
|
455
459
|
if (internals_1.state.info === undefined) {
|
|
456
460
|
throw new internal_workflow_common_1.IllegalStateError('Uninitialized workflow');
|
|
457
461
|
}
|
|
462
|
+
// Connect this cancel operation to the current cancellation scope.
|
|
463
|
+
// This is behavior was introduced after v0.22.0 and is incompatible
|
|
464
|
+
// with histories generated with previous SDK versions and thus requires
|
|
465
|
+
// patching.
|
|
466
|
+
//
|
|
467
|
+
// We try to delay patching as much as possible to avoid polluting
|
|
468
|
+
// histories unless strictly required.
|
|
469
|
+
const scope = cancellation_scope_1.CancellationScope.current();
|
|
470
|
+
if (scope.cancellable) {
|
|
471
|
+
(0, stack_helpers_1.untrackPromise)(scope.cancelRequested.catch((err) => {
|
|
472
|
+
if (patched(EXTERNAL_WF_CANCEL_PATCH)) {
|
|
473
|
+
reject(err);
|
|
474
|
+
}
|
|
475
|
+
}));
|
|
476
|
+
}
|
|
477
|
+
if (scope.consideredCancelled) {
|
|
478
|
+
if (patched(EXTERNAL_WF_CANCEL_PATCH)) {
|
|
479
|
+
return;
|
|
480
|
+
}
|
|
481
|
+
}
|
|
458
482
|
const seq = internals_1.state.nextSeqs.cancelWorkflow++;
|
|
459
483
|
internals_1.state.pushCommand({
|
|
460
484
|
requestCancelExternalWorkflowExecution: {
|
|
@@ -469,7 +493,7 @@ function getExternalWorkflowHandle(workflowId, runId) {
|
|
|
469
493
|
internals_1.state.completions.cancelWorkflow.set(seq, { resolve, reject });
|
|
470
494
|
});
|
|
471
495
|
},
|
|
472
|
-
|
|
496
|
+
signal(def, ...args) {
|
|
473
497
|
return (0, internal_workflow_common_1.composeInterceptors)(internals_1.state.interceptors.outbound, 'signalWorkflow', signalWorkflowNextHandler)({
|
|
474
498
|
seq: internals_1.state.nextSeqs.signalWorkflow++,
|
|
475
499
|
signalName: typeof def === 'string' ? def : def.name,
|
|
@@ -478,6 +502,7 @@ function getExternalWorkflowHandle(workflowId, runId) {
|
|
|
478
502
|
type: 'external',
|
|
479
503
|
workflowExecution: { workflowId, runId },
|
|
480
504
|
},
|
|
505
|
+
headers: {},
|
|
481
506
|
});
|
|
482
507
|
},
|
|
483
508
|
};
|
|
@@ -493,20 +518,14 @@ async function startChild(workflowTypeOrFunc, options) {
|
|
|
493
518
|
headers: {},
|
|
494
519
|
workflowType,
|
|
495
520
|
});
|
|
496
|
-
const
|
|
521
|
+
const firstExecutionRunId = await started;
|
|
497
522
|
return {
|
|
498
523
|
workflowId: optionsWithDefaults.workflowId,
|
|
499
|
-
|
|
500
|
-
result() {
|
|
501
|
-
|
|
502
|
-
throw new internal_workflow_common_1.IllegalStateError('Child Workflow was not started');
|
|
503
|
-
}
|
|
504
|
-
return completed;
|
|
524
|
+
firstExecutionRunId,
|
|
525
|
+
async result() {
|
|
526
|
+
return (await completed);
|
|
505
527
|
},
|
|
506
528
|
async signal(def, ...args) {
|
|
507
|
-
if (started === undefined) {
|
|
508
|
-
throw new internal_workflow_common_1.IllegalStateError('Workflow execution not started');
|
|
509
|
-
}
|
|
510
529
|
return (0, internal_workflow_common_1.composeInterceptors)(internals_1.state.interceptors.outbound, 'signalWorkflow', signalWorkflowNextHandler)({
|
|
511
530
|
seq: internals_1.state.nextSeqs.signalWorkflow++,
|
|
512
531
|
signalName: typeof def === 'string' ? def : def.name,
|
|
@@ -515,6 +534,7 @@ async function startChild(workflowTypeOrFunc, options) {
|
|
|
515
534
|
type: 'child',
|
|
516
535
|
childWorkflowId: optionsWithDefaults.workflowId,
|
|
517
536
|
},
|
|
537
|
+
headers: {},
|
|
518
538
|
});
|
|
519
539
|
},
|
|
520
540
|
};
|
|
@@ -524,13 +544,16 @@ async function executeChild(workflowTypeOrFunc, options) {
|
|
|
524
544
|
const optionsWithDefaults = addDefaultWorkflowOptions(options ?? {});
|
|
525
545
|
const workflowType = typeof workflowTypeOrFunc === 'string' ? workflowTypeOrFunc : workflowTypeOrFunc.name;
|
|
526
546
|
const execute = (0, internal_workflow_common_1.composeInterceptors)(internals_1.state.interceptors.outbound, 'startChildWorkflowExecution', startChildWorkflowExecutionNextHandler);
|
|
527
|
-
const
|
|
547
|
+
const execPromise = execute({
|
|
528
548
|
seq: internals_1.state.nextSeqs.childWorkflow++,
|
|
529
549
|
options: optionsWithDefaults,
|
|
530
550
|
headers: {},
|
|
531
551
|
workflowType,
|
|
532
552
|
});
|
|
533
|
-
|
|
553
|
+
(0, stack_helpers_1.untrackPromise)(execPromise);
|
|
554
|
+
const completedPromise = execPromise.then(([_started, completed]) => completed);
|
|
555
|
+
(0, stack_helpers_1.untrackPromise)(completedPromise);
|
|
556
|
+
return completedPromise;
|
|
534
557
|
}
|
|
535
558
|
exports.executeChild = executeChild;
|
|
536
559
|
/**
|
|
@@ -543,6 +566,26 @@ function workflowInfo() {
|
|
|
543
566
|
return internals_1.state.info;
|
|
544
567
|
}
|
|
545
568
|
exports.workflowInfo = workflowInfo;
|
|
569
|
+
/**
|
|
570
|
+
* Returns whether or not code is executing in workflow context
|
|
571
|
+
*/
|
|
572
|
+
function inWorkflowContext() {
|
|
573
|
+
try {
|
|
574
|
+
workflowInfo();
|
|
575
|
+
return true;
|
|
576
|
+
}
|
|
577
|
+
catch (err) {
|
|
578
|
+
// Use string comparison in case multiple versions of @temporalio/common are
|
|
579
|
+
// installed in which case an instanceof check would fail.
|
|
580
|
+
if (err.name === 'IllegalStateError') {
|
|
581
|
+
return false;
|
|
582
|
+
}
|
|
583
|
+
else {
|
|
584
|
+
throw err;
|
|
585
|
+
}
|
|
586
|
+
}
|
|
587
|
+
}
|
|
588
|
+
exports.inWorkflowContext = inWorkflowContext;
|
|
546
589
|
/**
|
|
547
590
|
* Get a reference to Sinks for exporting data out of the Workflow.
|
|
548
591
|
*
|
|
@@ -615,7 +658,9 @@ function makeContinueAsNewFunc(options) {
|
|
|
615
658
|
headers,
|
|
616
659
|
taskQueue: options.taskQueue,
|
|
617
660
|
memo: options.memo,
|
|
618
|
-
searchAttributes: options.searchAttributes
|
|
661
|
+
searchAttributes: options.searchAttributes
|
|
662
|
+
? (0, common_1.mapToPayloads)(common_1.searchAttributePayloadConverter, options.searchAttributes)
|
|
663
|
+
: undefined,
|
|
619
664
|
workflowRunTimeout: (0, internal_workflow_common_1.msOptionalToTs)(options.workflowRunTimeout),
|
|
620
665
|
workflowTaskTimeout: (0, internal_workflow_common_1.msOptionalToTs)(options.workflowTaskTimeout),
|
|
621
666
|
});
|
|
@@ -679,7 +724,7 @@ exports.uuid4 = uuid4;
|
|
|
679
724
|
/**
|
|
680
725
|
* Patch or upgrade workflow code by checking or stating that this workflow has a certain patch.
|
|
681
726
|
*
|
|
682
|
-
* See [docs page](https://docs.temporal.io/
|
|
727
|
+
* See [docs page](https://docs.temporal.io/typescript/versioning) for info.
|
|
683
728
|
*
|
|
684
729
|
* If the workflow is replaying an existing history, then this function returns true if that
|
|
685
730
|
* history was produced by a worker which also had a `patched` call with the same `patchId`.
|
|
@@ -700,7 +745,7 @@ exports.patched = patched;
|
|
|
700
745
|
/**
|
|
701
746
|
* Indicate that a patch is being phased out.
|
|
702
747
|
*
|
|
703
|
-
* See [docs page](https://docs.temporal.io/
|
|
748
|
+
* See [docs page](https://docs.temporal.io/typescript/versioning) for info.
|
|
704
749
|
*
|
|
705
750
|
* Workflows with this call may be deployed alongside workflows with a {@link patched} call, but
|
|
706
751
|
* they must *not* be deployed while any workers still exist running old code without a
|
|
@@ -721,11 +766,10 @@ exports.deprecatePatch = deprecatePatch;
|
|
|
721
766
|
function patchInternal(patchId, deprecated) {
|
|
722
767
|
// Patch operation does not support interception at the moment, if it did,
|
|
723
768
|
// this would be the place to start the interception chain
|
|
724
|
-
const { isReplaying } = workflowInfo();
|
|
725
769
|
if (internals_1.state.workflow === undefined) {
|
|
726
770
|
throw new internal_workflow_common_1.IllegalStateError('Patches cannot be used before Workflow starts');
|
|
727
771
|
}
|
|
728
|
-
const usePatch = !isReplaying || internals_1.state.knownPresentPatches.has(patchId);
|
|
772
|
+
const usePatch = !internals_1.state.isReplaying || internals_1.state.knownPresentPatches.has(patchId);
|
|
729
773
|
// Avoid sending commands for patches core already knows about.
|
|
730
774
|
// This optimization enables development of automatic patching tools.
|
|
731
775
|
if (usePatch && !internals_1.state.sentPatches.has(patchId)) {
|
|
@@ -738,7 +782,7 @@ function patchInternal(patchId, deprecated) {
|
|
|
738
782
|
}
|
|
739
783
|
async function condition(fn, timeout) {
|
|
740
784
|
if (timeout) {
|
|
741
|
-
return
|
|
785
|
+
return cancellation_scope_1.CancellationScope.cancellable(async () => {
|
|
742
786
|
try {
|
|
743
787
|
return await Promise.race([sleep(timeout).then(() => false), conditionInner(fn).then(() => true)]);
|
|
744
788
|
}
|
|
@@ -754,15 +798,15 @@ function conditionInner(fn) {
|
|
|
754
798
|
return new Promise((resolve, reject) => {
|
|
755
799
|
const scope = cancellation_scope_1.CancellationScope.current();
|
|
756
800
|
if (scope.consideredCancelled) {
|
|
757
|
-
scope.cancelRequested.catch(reject);
|
|
801
|
+
(0, stack_helpers_1.untrackPromise)(scope.cancelRequested.catch(reject));
|
|
758
802
|
return;
|
|
759
803
|
}
|
|
760
804
|
const seq = internals_1.state.nextSeqs.condition++;
|
|
761
805
|
if (scope.cancellable) {
|
|
762
|
-
scope.cancelRequested.catch((err) => {
|
|
806
|
+
(0, stack_helpers_1.untrackPromise)(scope.cancelRequested.catch((err) => {
|
|
763
807
|
internals_1.state.blockedConditions.delete(seq);
|
|
764
808
|
reject(err);
|
|
765
|
-
});
|
|
809
|
+
}));
|
|
766
810
|
}
|
|
767
811
|
// Eager evaluation
|
|
768
812
|
if (fn()) {
|
|
@@ -804,17 +848,17 @@ exports.defineQuery = defineQuery;
|
|
|
804
848
|
* If this function is called multiple times for a given signal or query name the last handler will overwrite any previous calls.
|
|
805
849
|
*
|
|
806
850
|
* @param def a {@link SignalDefinition} or {@link QueryDefinition} as returned by {@link defineSignal} or {@link defineQuery} respectively.
|
|
807
|
-
* @param handler
|
|
851
|
+
* @param handler a compatible handler function for the given definition or `undefined` to unset the handler.
|
|
808
852
|
*/
|
|
809
853
|
function setHandler(def, handler) {
|
|
810
854
|
if (def.type === 'signal') {
|
|
811
855
|
internals_1.state.signalHandlers.set(def.name, handler);
|
|
812
856
|
const bufferedSignals = internals_1.state.bufferedSignals.get(def.name);
|
|
813
|
-
if (bufferedSignals !== undefined) {
|
|
857
|
+
if (bufferedSignals !== undefined && handler !== undefined) {
|
|
858
|
+
internals_1.state.bufferedSignals.delete(def.name);
|
|
814
859
|
for (const signal of bufferedSignals) {
|
|
815
860
|
internals_1.state.activator.signalWorkflow(signal);
|
|
816
861
|
}
|
|
817
|
-
internals_1.state.bufferedSignals.delete(def.name);
|
|
818
862
|
}
|
|
819
863
|
}
|
|
820
864
|
else if (def.type === 'query') {
|
|
@@ -825,4 +869,68 @@ function setHandler(def, handler) {
|
|
|
825
869
|
}
|
|
826
870
|
}
|
|
827
871
|
exports.setHandler = setHandler;
|
|
872
|
+
/**
|
|
873
|
+
* Updates this Workflow's Search Attributes by merging the provided `searchAttributes` with the existing Search
|
|
874
|
+
* Attributes, `workflowInfo().searchAttributes`.
|
|
875
|
+
*
|
|
876
|
+
* For example, this Workflow code:
|
|
877
|
+
*
|
|
878
|
+
* ```ts
|
|
879
|
+
* upsertSearchAttributes({
|
|
880
|
+
* CustomIntField: [1, 2, 3],
|
|
881
|
+
* CustomBoolField: [true]
|
|
882
|
+
* });
|
|
883
|
+
* upsertSearchAttributes({
|
|
884
|
+
* CustomIntField: [42],
|
|
885
|
+
* CustomKeywordField: ['durable code', 'is great']
|
|
886
|
+
* });
|
|
887
|
+
* ```
|
|
888
|
+
*
|
|
889
|
+
* would result in the Workflow having these Search Attributes:
|
|
890
|
+
*
|
|
891
|
+
* ```ts
|
|
892
|
+
* {
|
|
893
|
+
* CustomIntField: [42],
|
|
894
|
+
* CustomBoolField: [true],
|
|
895
|
+
* CustomKeywordField: ['durable code', 'is great']
|
|
896
|
+
* }
|
|
897
|
+
* ```
|
|
898
|
+
*
|
|
899
|
+
* @param searchAttributes The Record to merge. Use a value of `[]` to clear a Search Attribute.
|
|
900
|
+
*/
|
|
901
|
+
function upsertSearchAttributes(searchAttributes) {
|
|
902
|
+
if (!internals_1.state.info) {
|
|
903
|
+
throw new internal_workflow_common_1.IllegalStateError('`state.info` should be defined');
|
|
904
|
+
}
|
|
905
|
+
const mergedSearchAttributes = { ...internals_1.state.info.searchAttributes, ...searchAttributes };
|
|
906
|
+
if (!mergedSearchAttributes) {
|
|
907
|
+
throw new Error('searchAttributes must be a non-null SearchAttributes');
|
|
908
|
+
}
|
|
909
|
+
internals_1.state.pushCommand({
|
|
910
|
+
upsertWorkflowSearchAttributes: {
|
|
911
|
+
searchAttributes: (0, common_1.mapToPayloads)(common_1.searchAttributePayloadConverter, searchAttributes),
|
|
912
|
+
},
|
|
913
|
+
});
|
|
914
|
+
internals_1.state.info.searchAttributes = mergedSearchAttributes;
|
|
915
|
+
}
|
|
916
|
+
exports.upsertSearchAttributes = upsertSearchAttributes;
|
|
917
|
+
/**
|
|
918
|
+
* Get information about the currently executing Workflow Task.
|
|
919
|
+
*
|
|
920
|
+
* See {@link TaskInfo}
|
|
921
|
+
*/
|
|
922
|
+
function taskInfo() {
|
|
923
|
+
const { isReplaying, historyLength } = internals_1.state;
|
|
924
|
+
if (isReplaying == null || historyLength == null) {
|
|
925
|
+
throw new internal_workflow_common_1.IllegalStateError('Workflow uninitialized');
|
|
926
|
+
}
|
|
927
|
+
return {
|
|
928
|
+
historyLength,
|
|
929
|
+
unsafe: {
|
|
930
|
+
isReplaying,
|
|
931
|
+
},
|
|
932
|
+
};
|
|
933
|
+
}
|
|
934
|
+
exports.taskInfo = taskInfo;
|
|
935
|
+
exports.stackTraceQuery = defineQuery('__stack_trace');
|
|
828
936
|
//# sourceMappingURL=workflow.js.map
|