@outputai/core 0.7.1-next.ae5bab4.0 → 0.7.1-next.ba2fb0b.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/bin/worker.sh +6 -0
- package/package.json +1 -1
- package/src/consts.js +0 -4
- package/src/errors.js +6 -2
- package/src/hooks/index.d.ts +10 -0
- package/src/interface/evaluator.js +7 -20
- package/src/interface/evaluator.spec.js +117 -1
- package/src/interface/step.js +8 -9
- package/src/interface/step.spec.js +124 -0
- package/src/interface/validations/index.js +108 -0
- package/src/interface/validations/index.spec.js +182 -0
- package/src/interface/validations/schemas.js +113 -0
- package/src/interface/validations/schemas.spec.js +209 -0
- package/src/interface/webhook.js +1 -1
- package/src/interface/webhook.spec.js +1 -1
- package/src/interface/workflow.d.ts +10 -9
- package/src/interface/workflow.js +76 -164
- package/src/interface/workflow.spec.js +637 -521
- package/src/interface/workflow_activity_options.js +16 -0
- package/src/interface/workflow_utils.js +1 -1
- package/src/interface/zod_integration.spec.js +2 -2
- package/src/internal_utils/aggregations.js +0 -10
- package/src/internal_utils/aggregations.spec.js +1 -48
- package/src/internal_utils/errors.js +14 -8
- package/src/internal_utils/errors.spec.js +73 -27
- package/src/utils/index.d.ts +19 -0
- package/src/utils/utils.js +53 -0
- package/src/utils/utils.spec.js +105 -1
- package/src/worker/bundle.js +26 -0
- package/src/worker/bundle.spec.js +53 -0
- package/src/worker/bundler_options.js +1 -1
- package/src/worker/bundler_options.spec.js +1 -1
- package/src/worker/catalog_workflow/catalog_job.js +148 -0
- package/src/worker/catalog_workflow/catalog_job.spec.js +232 -0
- package/src/worker/check.js +24 -0
- package/src/worker/connection_monitor.js +112 -0
- package/src/worker/connection_monitor.spec.js +199 -0
- package/src/worker/index.js +146 -41
- package/src/worker/index.spec.js +281 -109
- package/src/worker/interceptors/activity.js +7 -24
- package/src/worker/interceptors/activity.spec.js +97 -66
- package/src/worker/interceptors/index.js +4 -7
- package/src/worker/interceptors/modules.js +15 -0
- package/src/worker/interceptors/workflow.js +6 -8
- package/src/worker/interceptors/workflow.spec.js +49 -42
- package/src/worker/interruption.js +33 -0
- package/src/worker/interruption.spec.js +98 -0
- package/src/worker/loader/activities.js +75 -0
- package/src/worker/loader/activities.spec.js +213 -0
- package/src/worker/loader/hooks.js +28 -0
- package/src/worker/loader/hooks.spec.js +64 -0
- package/src/worker/loader/matchers.js +46 -0
- package/src/worker/loader/matchers.spec.js +140 -0
- package/src/worker/{loader_tools.js → loader/tools.js} +19 -67
- package/src/worker/{loader_tools.spec.js → loader/tools.spec.js} +53 -85
- package/src/worker/loader/workflows.js +82 -0
- package/src/worker/loader/workflows.spec.js +256 -0
- package/src/worker/{setup_telemetry.js → telemetry.js} +9 -4
- package/src/worker/{setup_telemetry.spec.js → telemetry.spec.js} +3 -3
- package/src/worker/webpack_loaders/workflow_rewriter/collect_target_imports.js +5 -109
- package/src/worker/webpack_loaders/workflow_rewriter/collect_target_imports.spec.js +31 -103
- package/src/worker/webpack_loaders/workflow_rewriter/index.mjs +5 -6
- package/src/worker/webpack_loaders/workflow_rewriter/index.spec.js +11 -83
- package/src/worker/webpack_loaders/workflow_rewriter/rewrite_fn_bodies.js +8 -11
- package/src/worker/webpack_loaders/workflow_rewriter/rewrite_fn_bodies.spec.js +9 -9
- package/src/interface/validations/runtime.js +0 -20
- package/src/interface/validations/runtime.spec.js +0 -29
- package/src/interface/validations/schema_utils.js +0 -8
- package/src/interface/validations/schema_utils.spec.js +0 -67
- package/src/interface/validations/static.js +0 -137
- package/src/interface/validations/static.spec.js +0 -397
- package/src/interface/workflow.replay_compatibility.spec.js +0 -254
- package/src/worker/loader.js +0 -202
- package/src/worker/loader.spec.js +0 -498
- package/src/worker/shutdown.js +0 -26
- package/src/worker/shutdown.spec.js +0 -82
- package/src/worker/start_catalog.js +0 -96
- package/src/worker/start_catalog.spec.js +0 -179
|
@@ -1,202 +1,114 @@
|
|
|
1
1
|
// THIS RUNS IN THE TEMPORAL'S SANDBOX ENVIRONMENT
|
|
2
2
|
import { proxyActivities, inWorkflowContext, executeChild, workflowInfo, uuid4, ParentClosePolicy } from '@temporalio/workflow';
|
|
3
|
-
import {
|
|
4
|
-
import { validateWorkflow } from './validations/static.js';
|
|
5
|
-
import { validateWithSchema } from './validations/runtime.js';
|
|
3
|
+
import { WorkflowValidator } from './validations/index.js';
|
|
6
4
|
import { deepMerge, setMetadata, toUrlSafeBase64 } from '#utils';
|
|
7
|
-
import { FatalError, ValidationError } from '#errors';
|
|
8
5
|
import { WorkflowContext } from '#internal_utils/workflow_context';
|
|
9
|
-
import { aggregateAttributes, mergeAggregations } from '#internal_utils/aggregations';
|
|
10
|
-
import { extractErrorDetail } from '#internal_utils/errors';
|
|
11
6
|
import { TraceInfo } from '#internal_utils/trace_info';
|
|
7
|
+
import { defaultOptions } from './workflow_activity_options.js';
|
|
12
8
|
import {
|
|
13
|
-
ACTIVITY_GET_TRACE_DESTINATIONS,
|
|
14
9
|
ACTIVITY_WRAPPER_VERSION_FIELD,
|
|
10
|
+
ACTIVITY_GET_TRACE_DESTINATIONS,
|
|
15
11
|
METADATA_ACCESS_SYMBOL,
|
|
16
12
|
SHARED_STEP_PREFIX,
|
|
17
|
-
Signal,
|
|
18
13
|
WORKFLOW_WRAPPER_VERSION_FIELD
|
|
19
14
|
} from '#consts';
|
|
20
15
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
initialInterval: '10s',
|
|
27
|
-
backoffCoefficient: 2.0,
|
|
28
|
-
maximumInterval: '2m',
|
|
29
|
-
maximumAttempts: 3,
|
|
30
|
-
nonRetryableErrorTypes: [ ValidationError.name, FatalError.name ]
|
|
31
|
-
}
|
|
32
|
-
},
|
|
33
|
-
disableTrace: false
|
|
34
|
-
};
|
|
16
|
+
/**
|
|
17
|
+
* @temp
|
|
18
|
+
* This is to keep backwards compatibility [OUT-468]
|
|
19
|
+
*/
|
|
20
|
+
const parseActivityOutput = p => Object.hasOwn( p ?? {}, ACTIVITY_WRAPPER_VERSION_FIELD ) ? p.output : p;
|
|
35
21
|
|
|
36
22
|
/**
|
|
37
|
-
*
|
|
23
|
+
* @temp This is a TEMP fallback method to allow workflow child checks on replays without memo. [OUT-468]
|
|
24
|
+
* This workflows for most scenarios, only does not supports recursion with the same name.
|
|
38
25
|
*/
|
|
39
|
-
const
|
|
26
|
+
const checkChildFallback = ( { workflowType, name, aliases } ) => workflowType !== name && !aliases.includes( workflowType );
|
|
40
27
|
|
|
28
|
+
/**
|
|
29
|
+
* Create a new workflow and return a wrapper function around its fn handler
|
|
30
|
+
*/
|
|
41
31
|
export function workflow( { name, description, inputSchema, outputSchema, fn, options = {}, aliases = [] } ) {
|
|
42
|
-
|
|
32
|
+
WorkflowValidator.validateDefinition( { name, description, inputSchema, outputSchema, fn, options, aliases } );
|
|
43
33
|
|
|
44
34
|
const { disableTrace, activityOptions } = deepMerge( defaultOptions, options );
|
|
45
|
-
const
|
|
46
|
-
|
|
47
|
-
/**
|
|
48
|
-
* Wraps the `fn` function of the workflow
|
|
49
|
-
*
|
|
50
|
-
* @param {unknown} input - The input, must match the inputSchema
|
|
51
|
-
* @param {object} extra - Workflow configurations (received directly only in unit tests)
|
|
52
|
-
* @returns {unknown} The result, will match the outputSchema
|
|
53
|
-
*/
|
|
35
|
+
const validator = new WorkflowValidator( { name, inputSchema, outputSchema } );
|
|
36
|
+
|
|
54
37
|
const wrapper = async ( input, extra = {} ) => {
|
|
38
|
+
validator.validateInvocationOptions( extra );
|
|
39
|
+
|
|
55
40
|
// this returns a plain function, for example, in unit tests
|
|
56
41
|
if ( !inWorkflowContext() ) {
|
|
57
|
-
|
|
58
|
-
const output = await fn( input, deepMerge( WorkflowContext.build(), extra
|
|
59
|
-
|
|
42
|
+
validator.validateInput( input );
|
|
43
|
+
const output = await fn( input, deepMerge( WorkflowContext.build(), extra?.context ) );
|
|
44
|
+
validator.validateOutput( output );
|
|
60
45
|
return output;
|
|
61
46
|
}
|
|
62
47
|
|
|
63
|
-
const { workflowId, memo, root } = workflowInfo();
|
|
64
|
-
|
|
48
|
+
const { workflowId, workflowType, memo, root } = workflowInfo();
|
|
49
|
+
|
|
50
|
+
// if the stack already includes this workflowId, means the workflow() function was called
|
|
51
|
+
// from within a running workflow, meaning it is suppose to start a child workflow
|
|
52
|
+
const isChild = Array.isArray( memo.stack ) ? memo.stack.includes( workflowId ) :
|
|
53
|
+
checkChildFallback( { workflowType, aliases, name } );
|
|
54
|
+
|
|
55
|
+
if ( isChild ) {
|
|
56
|
+
const result = await executeChild( name, {
|
|
57
|
+
args: undefined === input ? [] : [ input ],
|
|
58
|
+
workflowId: `${workflowId}-${toUrlSafeBase64( uuid4() )}`,
|
|
59
|
+
parentClosePolicy: ParentClosePolicy[extra?.detached ? 'ABANDON' : 'TERMINATE'],
|
|
60
|
+
memo: {
|
|
61
|
+
...memo, // Preserve memo and mix activityOptions, if provided
|
|
62
|
+
...( extra?.activityOptions && {
|
|
63
|
+
activityOptions: deepMerge( memo?.activityOptions ?? {}, extra?.activityOptions )
|
|
64
|
+
} )
|
|
65
|
+
}
|
|
66
|
+
} );
|
|
67
|
+
return result.output;
|
|
68
|
+
}
|
|
65
69
|
|
|
66
70
|
const isRoot = !root;
|
|
67
71
|
|
|
68
|
-
|
|
69
|
-
//
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
* @IMPORTANT Keep support for deprecated non-wrapped activity result to allow for Temporal replays.
|
|
79
|
-
* @TODO [OUT-468]
|
|
80
|
-
*/
|
|
81
|
-
const getTraceDestinations = async () => {
|
|
82
|
-
const result = await steps[ACTIVITY_GET_TRACE_DESTINATIONS]( memo.traceInfo );
|
|
83
|
-
return isActivityResultWrapped( result ) ? result.output : result;
|
|
84
|
-
};
|
|
85
|
-
|
|
86
|
-
// Creates the result wrapper with information about the workflow
|
|
87
|
-
const workflowResult = {
|
|
88
|
-
[WORKFLOW_WRAPPER_VERSION_FIELD]: 1,
|
|
89
|
-
aggregations: null,
|
|
90
|
-
...( isRoot && {
|
|
91
|
-
trace: {
|
|
92
|
-
destinations: await getTraceDestinations()
|
|
93
|
-
}
|
|
94
|
-
} )
|
|
95
|
-
};
|
|
96
|
-
|
|
97
|
-
// Combine aggregations in the workflow result aggregations, mutating it
|
|
98
|
-
const mergeAggregationsInWorkflowResult = aggregations => {
|
|
99
|
-
workflowResult.aggregations = mergeAggregations( workflowResult.aggregations, aggregations );
|
|
100
|
-
};
|
|
101
|
-
|
|
102
|
-
setHandler( defineSignal( Signal.SEND_AGGREGATIONS ), aggregations => {
|
|
103
|
-
mergeAggregationsInWorkflowResult( aggregations );
|
|
104
|
-
} );
|
|
105
|
-
|
|
106
|
-
/**
|
|
107
|
-
* @IMPORTANT Keep support for deprecated add_attribute Signal to allow for Temporal replays.
|
|
108
|
-
* @TODO This can be removed 30days after this release
|
|
109
|
-
*/
|
|
110
|
-
setHandler( defineSignal( 'add_attribute' ), attribute => {
|
|
111
|
-
mergeAggregationsInWorkflowResult( aggregateAttributes( [ attribute ] ) );
|
|
112
|
-
} );
|
|
113
|
-
|
|
114
|
-
/**
|
|
115
|
-
* Invoke a step and unwraps the result to extract and merge "aggregations" and return only the output.
|
|
116
|
-
*
|
|
117
|
-
* @IMPORTANT Keep support for deprecated non-wrapped activity result to allow for Temporal replays.
|
|
118
|
-
* @TODO [OUT-468]
|
|
119
|
-
* @param {Function} step
|
|
120
|
-
* @param {...any} args
|
|
121
|
-
* @returns {any} The step "output"
|
|
122
|
-
*/
|
|
123
|
-
const callStepAndUnwrapResult = async ( step, ...args ) => {
|
|
124
|
-
const result = await step( ...args );
|
|
125
|
-
if ( !isActivityResultWrapped( result ) ) {
|
|
126
|
-
return result;
|
|
127
|
-
}
|
|
128
|
-
const { output, aggregations } = result;
|
|
129
|
-
if ( aggregations ) {
|
|
130
|
-
mergeAggregationsInWorkflowResult( aggregations );
|
|
131
|
-
}
|
|
132
|
-
return output;
|
|
133
|
-
};
|
|
72
|
+
memo.stack = [ ...memo.stack ?? [], workflowId ];
|
|
73
|
+
// Parent options have prevalence on nested calls, child will be overwritten
|
|
74
|
+
memo.activityOptions = deepMerge( activityOptions, memo.activityOptions );
|
|
75
|
+
// Trace info is only added in the root workflow
|
|
76
|
+
if ( isRoot ) {
|
|
77
|
+
memo.traceInfo = TraceInfo.build( { disableTrace } );
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
const steps = proxyActivities( memo.activityOptions );
|
|
81
|
+
const traceDest = isRoot && parseActivityOutput( await steps[ACTIVITY_GET_TRACE_DESTINATIONS]( memo.traceInfo ) );
|
|
134
82
|
|
|
135
83
|
try {
|
|
136
|
-
|
|
137
|
-
validateWithSchema( inputSchema, input, `Workflow ${name} input` );
|
|
84
|
+
validator.validateInput( input );
|
|
138
85
|
|
|
86
|
+
// Creates an activity caller based on a prefix
|
|
87
|
+
const createCaller = prefix => async ( t, ...args ) => parseActivityOutput( await steps[`${prefix}#${t}`]( ...args ) );
|
|
88
|
+
|
|
89
|
+
// This are functions used by the AST to replace direct activity (step/evaluator) calls
|
|
139
90
|
const dispatchers = {
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
callStepAndUnwrapResult( steps[`${SHARED_STEP_PREFIX}#${stepName}`], input, options ),
|
|
145
|
-
invokeEvaluator: async ( evaluatorName, input, options ) =>
|
|
146
|
-
callStepAndUnwrapResult( steps[`${name}#${evaluatorName}`], input, options ),
|
|
147
|
-
invokeSharedEvaluator: async ( evaluatorName, input, options ) =>
|
|
148
|
-
callStepAndUnwrapResult( steps[`${SHARED_STEP_PREFIX}#${evaluatorName}`], input, options ),
|
|
149
|
-
|
|
150
|
-
// Start a new child workflow
|
|
151
|
-
startWorkflow: async ( childName, input, extra = {} ) => {
|
|
152
|
-
try {
|
|
153
|
-
const result = await executeChild( childName, {
|
|
154
|
-
args: undefined === input ? [] : [ input ],
|
|
155
|
-
workflowId: `${workflowId}-${toUrlSafeBase64( uuid4() )}`,
|
|
156
|
-
parentClosePolicy: ParentClosePolicy[extra?.detached ? 'ABANDON' : 'TERMINATE'],
|
|
157
|
-
memo: {
|
|
158
|
-
...memo,
|
|
159
|
-
...( extra?.options?.activityOptions && { activityOptions: deepMerge( activityOptions, extra.options.activityOptions ) } )
|
|
160
|
-
}
|
|
161
|
-
} );
|
|
162
|
-
/**
|
|
163
|
-
* @IMPORTANT Keep support for deprecated ".attributes" from workflow results to allow for Temporal replays.
|
|
164
|
-
* @TODO [OUT-468]
|
|
165
|
-
*/
|
|
166
|
-
if ( result?.attributes ) {
|
|
167
|
-
mergeAggregationsInWorkflowResult( aggregateAttributes( result.attributes ) );
|
|
168
|
-
}
|
|
169
|
-
if ( result?.aggregations ) {
|
|
170
|
-
mergeAggregationsInWorkflowResult( result.aggregations );
|
|
171
|
-
}
|
|
172
|
-
return result.output;
|
|
173
|
-
} catch ( error ) {
|
|
174
|
-
/**
|
|
175
|
-
* @IMPORTANT Keep support for deprecated ".attributes" from workflow errors to allow for Temporal replays.
|
|
176
|
-
* @TODO [OUT-468]
|
|
177
|
-
*/
|
|
178
|
-
const attributesFromError = extractErrorDetail( error, 'attributes' );
|
|
179
|
-
if ( attributesFromError ) {
|
|
180
|
-
mergeAggregationsInWorkflowResult( aggregateAttributes( attributesFromError ) );
|
|
181
|
-
}
|
|
182
|
-
const aggregationsFromError = extractErrorDetail( error, 'aggregations' );
|
|
183
|
-
if ( aggregationsFromError ) {
|
|
184
|
-
mergeAggregationsInWorkflowResult( aggregationsFromError );
|
|
185
|
-
}
|
|
186
|
-
throw error;
|
|
187
|
-
}
|
|
188
|
-
}
|
|
91
|
+
invokeStep: createCaller( name ),
|
|
92
|
+
invokeSharedStep: createCaller( SHARED_STEP_PREFIX ),
|
|
93
|
+
invokeEvaluator: createCaller( name ),
|
|
94
|
+
invokeSharedEvaluator: createCaller( SHARED_STEP_PREFIX )
|
|
189
95
|
};
|
|
190
96
|
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
97
|
+
// The workflow function execution with "this" set with the dispatchers
|
|
98
|
+
const output = await fn.call( dispatchers, input, WorkflowContext.build() );
|
|
99
|
+
validator.validateOutput( output );
|
|
194
100
|
|
|
195
|
-
return
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
101
|
+
return {
|
|
102
|
+
[WORKFLOW_WRAPPER_VERSION_FIELD]: 1,
|
|
103
|
+
output,
|
|
104
|
+
...( traceDest && { trace: { destinations: traceDest } } )
|
|
105
|
+
};
|
|
106
|
+
} catch ( error ) {
|
|
107
|
+
if ( isRoot && traceDest ) {
|
|
108
|
+
// Append the trace destinations so it is carried to interceptor
|
|
109
|
+
error[METADATA_ACCESS_SYMBOL] = { trace: { destinations: traceDest } };
|
|
110
|
+
}
|
|
111
|
+
throw error;
|
|
200
112
|
}
|
|
201
113
|
};
|
|
202
114
|
|