Skip to content

Commit

Permalink
feat(stepfunctions-tasks): evaluate expression as a task construct (#…
Browse files Browse the repository at this point in the history
…8555)

Replacement for the current implementation of experimental Evaluate Expression.
Merges state and service integration properties and represents them as a
construct.

Note that the changes to test are only the reordering of elements.
Re-ran the integration test and verified that it functions as documented.

BREAKING CHANGE:
`EvaluateExpression` is now a construct representing a task state rather than an embedded property called `task`

----

*By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
  • Loading branch information
shivlaks committed Jun 29, 2020
1 parent d1c2ef2 commit 83fd2ae
Show file tree
Hide file tree
Showing 5 changed files with 64 additions and 69 deletions.
21 changes: 9 additions & 12 deletions packages/@aws-cdk/aws-stepfunctions-tasks/README.md
Expand Up @@ -164,25 +164,22 @@ Use the `EvaluateExpression` to perform simple operations referencing state path
Example: convert a wait time from milliseconds to seconds, concat this in a message and wait:

```ts
const convertToSeconds = new sfn.Task(this, 'Convert to seconds', {
task: new tasks.EvaluateExpression({ expression: '$.waitMilliseconds / 1000' }),
resultPath: '$.waitSeconds'
const convertToSeconds = new tasks.EvaluateExpression(this, 'Convert to seconds', {
expression: '$.waitMilliseconds / 1000',
resultPath: '$.waitSeconds',
});

const createMessage = new sfn.Task(this, 'Create message', {
const createMessage = new tasks.EvaluateExpression(this, 'Create message', {
// Note: this is a string inside a string.
task: new tasks.EvaluateExpression({
expression: '`Now waiting ${$.waitSeconds} seconds...`',
runtime: lambda.Runtime.NODEJS_10_X,
}),
resultPath: '$.message'
resultPath: '$.message',
});

const publishMessage = new sfn.Task(this, 'Publish message', {
task: new tasks.PublishToTopic(topic, {
message: sfn.TaskInput.fromDataAt('$.message'),
}),
resultPath: '$.sns'
const publishMessage = new tasks.SnsPublish(this, 'Publish message', {
topic,
message: sfn.TaskInput.fromDataAt('$.message'),
resultPath: '$.sns',
});

const wait = new sfn.Wait(this, 'Wait', {
Expand Down
Expand Up @@ -9,7 +9,7 @@ import * as path from 'path';
*
* @experimental
*/
export interface EvaluateExpressionProps {
export interface EvaluateExpressionProps extends sfn.TaskStateBaseProps {
/**
* The expression to evaluate. The expression may contain state paths.
*
Expand Down Expand Up @@ -49,11 +49,29 @@ export interface Event {
*
* @experimental
*/
export class EvaluateExpression implements sfn.IStepFunctionsTask {
constructor(private readonly props: EvaluateExpressionProps) {
export class EvaluateExpression extends sfn.TaskStateBase {
protected readonly taskMetrics?: sfn.TaskMetricsConfig;
protected readonly taskPolicies?: iam.PolicyStatement[];

private readonly evalFn: lambda.SingletonFunction;

constructor(scope: cdk.Construct, id: string, private readonly props: EvaluateExpressionProps) {
super(scope, id, props);

this.evalFn = createEvalFn(this.props.runtime || lambda.Runtime.NODEJS_10_X, this);

this.taskPolicies = [
new iam.PolicyStatement({
resources: [this.evalFn.functionArn],
actions: ['lambda:InvokeFunction'],
}),
];
}

public bind(task: sfn.Task): sfn.StepFunctionsTaskConfig {
/**
* @internal
*/
protected _renderTask(): any {
const matches = this.props.expression.match(/\$[.\[][.a-zA-Z[\]0-9]+/g);

let expressionAttributeValues = {};
Expand All @@ -67,19 +85,13 @@ export class EvaluateExpression implements sfn.IStepFunctionsTask {
);
}

const evalFn = createEvalFn(this.props.runtime || lambda.Runtime.NODEJS_10_X, task);

const parameters: Event = {
expression: this.props.expression,
expressionAttributeValues,
};
return {
resourceArn: evalFn.functionArn,
policyStatements: [new iam.PolicyStatement({
resources: [evalFn.functionArn],
actions: ['lambda:InvokeFunction'],
})],
parameters,
Resource: this.evalFn.functionArn,
Parameters: sfn.FieldUtils.renderObject(parameters),
};
}
}
Expand Down
Expand Up @@ -10,10 +10,8 @@ beforeEach(() => {

test('Eval with Node.js', () => {
// WHEN
const task = new sfn.Task(stack, 'Task', {
task: new tasks.EvaluateExpression({
expression: '$.a + $.b',
}),
const task = new tasks.EvaluateExpression(stack, 'Task', {
expression: '$.a + $.b',
});
new sfn.StateMachine(stack, 'SM', {
definition: task,
Expand All @@ -25,14 +23,11 @@ test('Eval with Node.js', () => {
'Fn::Join': [
'',
[
'{"StartAt":"Task","States":{"Task":{"End":true,"Parameters":{"expression":"$.a + $.b","expressionAttributeValues":{"$.a.$":"$.a","$.b.$":"$.b"}},"Type":"Task","Resource":"',
'{"StartAt":"Task","States":{"Task":{"End":true,"Type":"Task","Resource":"',
{
'Fn::GetAtt': [
'Evala0d2ce44871b4e7487a1f5e63d7c3bdc4DAC06E1',
'Arn',
],
'Fn::GetAtt': ['Evala0d2ce44871b4e7487a1f5e63d7c3bdc4DAC06E1', 'Arn'],
},
'"}}}',
'","Parameters":{"expression":"$.a + $.b","expressionAttributeValues":{"$.a.$":"$.a","$.b.$":"$.b"}}}}}',
],
],
},
Expand All @@ -45,10 +40,8 @@ test('Eval with Node.js', () => {

test('expression does not contain paths', () => {
// WHEN
const task = new sfn.Task(stack, 'Task', {
task: new tasks.EvaluateExpression({
expression: '2 + 2',
}),
const task = new tasks.EvaluateExpression(stack, 'Task', {
expression: '2 + 2',
});
new sfn.StateMachine(stack, 'SM', {
definition: task,
Expand All @@ -59,14 +52,11 @@ test('expression does not contain paths', () => {
'Fn::Join': [
'',
[
'{"StartAt":"Task","States":{"Task":{"End":true,"Parameters":{"expression":"2 + 2",\"expressionAttributeValues\":{}},"Type":"Task","Resource":"',
'{"StartAt":"Task","States":{"Task":{"End":true,"Type":"Task","Resource":"',
{
'Fn::GetAtt': [
'Evala0d2ce44871b4e7487a1f5e63d7c3bdc4DAC06E1',
'Arn',
],
'Fn::GetAtt': ['Evala0d2ce44871b4e7487a1f5e63d7c3bdc4DAC06E1', 'Arn'],
},
'"}}}',
'","Parameters":{"expression":"2 + 2","expressionAttributeValues":{}}}}}',
],
],
},
Expand Down
Expand Up @@ -142,40 +142,40 @@
"StateMachine2E01A3A5": {
"Type": "AWS::StepFunctions::StateMachine",
"Properties": {
"RoleArn": {
"Fn::GetAtt": [
"StateMachineRoleB840431D",
"Arn"
]
},
"DefinitionString": {
"Fn::Join": [
"",
[
"{\"StartAt\":\"Sum\",\"States\":{\"Sum\":{\"Next\":\"Multiply\",\"Parameters\":{\"expression\":\"$.a + $.b\",\"expressionAttributeValues\":{\"$.a.$\":\"$.a\",\"$.b.$\":\"$.b\"}},\"Type\":\"Task\",\"Resource\":\"",
"{\"StartAt\":\"Sum\",\"States\":{\"Sum\":{\"Next\":\"Multiply\",\"Type\":\"Task\",\"ResultPath\":\"$.c\",\"Resource\":\"",
{
"Fn::GetAtt": [
"Evala0d2ce44871b4e7487a1f5e63d7c3bdc4DAC06E1",
"Arn"
]
},
"\",\"ResultPath\":\"$.c\"},\"Multiply\":{\"Next\":\"Wait\",\"Parameters\":{\"expression\":\"$.c * 2\",\"expressionAttributeValues\":{\"$.c.$\":\"$.c\"}},\"Type\":\"Task\",\"Resource\":\"",
"\",\"Parameters\":{\"expression\":\"$.a + $.b\",\"expressionAttributeValues\":{\"$.a.$\":\"$.a\",\"$.b.$\":\"$.b\"}}},\"Multiply\":{\"Next\":\"Wait\",\"Type\":\"Task\",\"ResultPath\":\"$.d\",\"Resource\":\"",
{
"Fn::GetAtt": [
"Evala0d2ce44871b4e7487a1f5e63d7c3bdc4DAC06E1",
"Arn"
]
},
"\",\"ResultPath\":\"$.d\"},\"Wait\":{\"Type\":\"Wait\",\"SecondsPath\":\"$.d\",\"Next\":\"Now\"},\"Now\":{\"End\":true,\"Parameters\":{\"expression\":\"(new Date()).toUTCString()\",\"expressionAttributeValues\":{}},\"Type\":\"Task\",\"Resource\":\"",
"\",\"Parameters\":{\"expression\":\"$.c * 2\",\"expressionAttributeValues\":{\"$.c.$\":\"$.c\"}}},\"Wait\":{\"Type\":\"Wait\",\"SecondsPath\":\"$.d\",\"Next\":\"Now\"},\"Now\":{\"End\":true,\"Type\":\"Task\",\"ResultPath\":\"$.now\",\"Resource\":\"",
{
"Fn::GetAtt": [
"Evala0d2ce44871b4e7487a1f5e63d7c3bdc4DAC06E1",
"Arn"
]
},
"\",\"ResultPath\":\"$.now\"}}}"
"\",\"Parameters\":{\"expression\":\"(new Date()).toUTCString()\",\"expressionAttributeValues\":{}}}}}"
]
]
},
"RoleArn": {
"Fn::GetAtt": [
"StateMachineRoleB840431D",
"Arn"
]
}
},
"DependsOn": [
Expand Down
Expand Up @@ -12,33 +12,29 @@ import * as tasks from '../lib';
const app = new cdk.App();
const stack = new cdk.Stack(app, 'aws-stepfunctions-integ');

const sum = new sfn.Task(stack, 'Sum', {
task: new tasks.EvaluateExpression({
expression: '$.a + $.b',
}),
const sum = new tasks.EvaluateExpression(stack, 'Sum', {
expression: '$.a + $.b',
resultPath: '$.c',
});

const multiply = new sfn.Task(stack, 'Multiply', {
task: new tasks.EvaluateExpression({
expression: '$.c * 2',
}),
const multiply = new tasks.EvaluateExpression(stack, 'Multiply', {
expression: '$.c * 2',
resultPath: '$.d',
});

const now = new sfn.Task(stack, 'Now', {
task: new tasks.EvaluateExpression({
expression: '(new Date()).toUTCString()',
}),
const now = new tasks.EvaluateExpression(stack, 'Now', {
expression: '(new Date()).toUTCString()',
resultPath: '$.now',
});

const statemachine = new sfn.StateMachine(stack, 'StateMachine', {
definition: sum
.next(multiply)
.next(new sfn.Wait(stack, 'Wait', {
time: sfn.WaitTime.secondsPath('$.d'),
}))
.next(
new sfn.Wait(stack, 'Wait', {
time: sfn.WaitTime.secondsPath('$.d'),
}),
)
.next(now),
});

Expand Down

0 comments on commit 83fd2ae

Please sign in to comment.