Skip to content
This repository has been archived by the owner on Mar 20, 2023. It is now read-only.

Commit

Permalink
docs(stepfunctions): make examples compile (aws#17141)
Browse files Browse the repository at this point in the history
----

*By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
  • Loading branch information
kaizencc authored Oct 26, 2021
1 parent aea7a60 commit e1bf1b9
Show file tree
Hide file tree
Showing 3 changed files with 107 additions and 46 deletions.
135 changes: 91 additions & 44 deletions packages/@aws-cdk/aws-stepfunctions/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,10 @@ example](https://docs.aws.amazon.com/step-functions/latest/dg/job-status-poller-
## Example

```ts
import * as cdk from '@aws-cdk/core';
import * as sfn from '@aws-cdk/aws-stepfunctions';
import * as tasks from '@aws-cdk/aws-stepfunctions-tasks';
import * as lambda from '@aws-cdk/aws-lambda';

const submitLambda = new lambda.Function(this, 'SubmitLambda', { ... });
const getStatusLambda = new lambda.Function(this, 'CheckLambda', { ... });
declare const submitLambda: lambda.Function;
declare const getStatusLambda: lambda.Function;

const submitJob = new tasks.LambdaInvoke(this, 'Submit Job', {
lambdaFunction: submitLambda,
Expand Down Expand Up @@ -71,7 +68,7 @@ const definition = submitJob

new sfn.StateMachine(this, 'StateMachine', {
definition,
timeout: cdk.Duration.minutes(5),
timeout: Duration.minutes(5),
});
```

Expand Down Expand Up @@ -145,6 +142,7 @@ const pass = new sfn.Pass(this, 'Add Hello World', {
});

// Set the next state
const nextState = new sfn.Pass(this, 'NextState');
pass.next(nextState);
```

Expand Down Expand Up @@ -183,6 +181,7 @@ const wait = new sfn.Wait(this, 'Wait For Trigger Time', {
});

// Set the next state
const startTheWork = new sfn.Pass(this, 'StartTheWork');
wait.next(startTheWork);
```

Expand All @@ -195,10 +194,13 @@ values in the execution's JSON state:
const choice = new sfn.Choice(this, 'Did it work?');

// Add conditions with .when()
const successState = new sfn.Pass(this, 'SuccessState');
const failureState = new sfn.Pass(this, 'FailureState');
choice.when(sfn.Condition.stringEquals('$.status', 'SUCCESS'), successState);
choice.when(sfn.Condition.numberGreaterThan('$.attempts', 5), failureState);

// Use .otherwise() to indicate what should be done if none of the conditions match
const tryAgainState = new sfn.Pass(this, 'TryAgainState');
choice.otherwise(tryAgainState);
```

Expand All @@ -208,11 +210,15 @@ then ... else` works in a programming language), use the `.afterwards()` method:

```ts
const choice = new sfn.Choice(this, 'What color is it?');
const handleBlueItem = new sfn.Pass(this, 'HandleBlueItem');
const handleRedItem = new sfn.Pass(this, 'HandleRedItem');
const handleOtherItemColor = new sfn.Pass(this, 'HanldeOtherItemColor');
choice.when(sfn.Condition.stringEquals('$.color', 'BLUE'), handleBlueItem);
choice.when(sfn.Condition.stringEquals('$.color', 'RED'), handleRedItem);
choice.otherwise(handleOtherItemColor);

// Use .afterwards() to join all possible paths back together and continue
const shipTheItem = new sfn.Pass(this, 'ShipTheItem');
choice.afterwards().next(shipTheItem);
```

Expand Down Expand Up @@ -279,6 +285,9 @@ be used to catch and recover from errors in subworkflows.
const parallel = new sfn.Parallel(this, 'Do the work in parallel');

// Add branches to be executed in parallel
const shipItem = new sfn.Pass(this, 'ShipItem');
const sendInvoice = new sfn.Pass(this, 'SendInvoice');
const restock = new sfn.Pass(this, 'Restock');
parallel.branch(shipItem);
parallel.branch(sendInvoice);
parallel.branch(restock);
Expand All @@ -287,9 +296,11 @@ parallel.branch(restock);
parallel.addRetry({ maxAttempts: 1 });

// How to recover from errors
const sendFailureNotification = new sfn.Pass(this, 'SendFailureNotification');
parallel.addCatch(sendFailureNotification);

// What to do in case everything succeeded
const closeOrder = new sfn.Pass(this, 'CloseOrder');
parallel.next(closeOrder);
```

Expand Down Expand Up @@ -354,19 +365,17 @@ the State Machine uses.
The following example uses the `DynamoDB` service integration to insert data into a DynamoDB table.

```ts
import * as cdk from '@aws-cdk/core';
import * as ddb from '@aws-cdk/aws-dynamodb';
import * as sfn from '@aws-cdk/aws-stepfunctions';
import * as dynamodb from '@aws-cdk/aws-dynamodb';

// create a table
const table = new ddb.Table(this, 'montable', {
const table = new dynamodb.Table(this, 'montable', {
partitionKey: {
name: 'id',
type: ddb.AttributeType.STRING,
type: dynamodb.AttributeType.STRING,
},
});

const finalStatus = new sfn.Pass(stack, 'final step');
const finalStatus = new sfn.Pass(this, 'final step');

// States language JSON to put an item into DynamoDB
// snippet generated from https://docs.aws.amazon.com/step-functions/latest/dg/tutorial-code-snippet.html#tutorial-code-snippet-1
Expand Down Expand Up @@ -394,7 +403,7 @@ const chain = sfn.Chain.start(custom)

const sm = new sfn.StateMachine(this, 'StateMachine', {
definition: chain,
timeout: cdk.Duration.seconds(30),
timeout: Duration.seconds(30),
});

// don't forget permissions. You need to assign them
Expand All @@ -410,6 +419,21 @@ In particular, the `.next()` method can be repeated. The result of a series of
targets of `Choice.on` or `Parallel.branch`:

```ts
const step1 = new sfn.Pass(this, 'Step1');
const step2 = new sfn.Pass(this, 'Step2');
const step3 = new sfn.Pass(this, 'Step3');
const step4 = new sfn.Pass(this, 'Step4');
const step5 = new sfn.Pass(this, 'Step5');
const step6 = new sfn.Pass(this, 'Step6');
const step7 = new sfn.Pass(this, 'Step7');
const step8 = new sfn.Pass(this, 'Step8');
const step9 = new sfn.Pass(this, 'Step9');
const step10 = new sfn.Pass(this, 'Step10');
const choice = new sfn.Choice(this, 'Choice');
const condition1 = sfn.Condition.stringEquals('$.status', 'SUCCESS');
const parallel = new sfn.Parallel(this, 'Parallel');
const finish = new sfn.Pass(this, 'Finish');

const definition = step1
.next(step2)
.next(choice
Expand All @@ -430,6 +454,10 @@ If you don't like the visual look of starting a chain directly off the first
step, you can use `Chain.start`:

```ts
const step1 = new sfn.Pass(this, 'Step1');
const step2 = new sfn.Pass(this, 'Step2');
const step3 = new sfn.Pass(this, 'Step3');

const definition = sfn.Chain
.start(step1)
.next(step2)
Expand All @@ -456,7 +484,11 @@ The class `StateMachineFragment` contains some helper functions (like
`prefixStates()`) to make it easier for you to do this. If you define your state
machine as a subclass of this, it will be convenient to use:

```ts
```ts nofixture
import { Construct, Stack } from '@aws-cdk/core';
import * as sfn from '@aws-cdk/aws-stepfunctions';
import * as tasks from '@aws-cdk/aws-stepfunctions-tasks';

interface MyJobProps {
jobFlavor: string;
}
Expand All @@ -465,23 +497,30 @@ class MyJob extends sfn.StateMachineFragment {
public readonly startState: sfn.State;
public readonly endStates: sfn.INextable[];

constructor(parent: cdk.Construct, id: string, props: MyJobProps) {
constructor(parent: Construct, id: string, props: MyJobProps) {
super(parent, id);

const first = new sfn.Task(this, 'First', { ... });
const choice = new sfn.Choice(this, 'Choice')
.when(sfn.Condition.stringEquals('$.branch', 'left'), new sfn.Pass(this, 'Left Branch'))
.when(sfn.Condition.stringEquals('$.branch', 'right'), new sfn.Pass(this, 'Right Branch'));

// ...
const last = new sfn.Task(this, 'Last', { ... });

this.startState = first;
this.endStates = [last];
this.startState = choice;
this.endStates = choice.afterwards().endStates;
}
}

// Do 3 different variants of MyJob in parallel
new sfn.Parallel(this, 'All jobs')
.branch(new MyJob(this, 'Quick', { jobFlavor: 'quick' }).prefixStates())
.branch(new MyJob(this, 'Medium', { jobFlavor: 'medium' }).prefixStates())
.branch(new MyJob(this, 'Slow', { jobFlavor: 'slow' }).prefixStates());
class MyStack extends Stack {
constructor(scope: Construct, id: string) {
super(scope, id);
// Do 3 different variants of MyJob in parallel
new sfn.Parallel(this, 'All jobs')
.branch(new MyJob(this, 'Quick', { jobFlavor: 'quick' }).prefixStates())
.branch(new MyJob(this, 'Medium', { jobFlavor: 'medium' }).prefixStates())
.branch(new MyJob(this, 'Slow', { jobFlavor: 'slow' }).prefixStates());
}
}
```

A few utility functions are available to parse state machine fragments.
Expand All @@ -504,7 +543,7 @@ const activity = new sfn.Activity(this, 'Activity');

// Read this CloudFormation Output from your application and use it to poll for work on
// the activity.
new cdk.CfnOutput(this, 'ActivityArn', { value: activity.activityArn });
new CfnOutput(this, 'ActivityArn', { value: activity.activityArn });
```

### Activity-Level Permissions
Expand All @@ -514,7 +553,7 @@ Granting IAM permissions to an activity can be achieved by calling the `grant(pr
```ts
const activity = new sfn.Activity(this, 'Activity');

const role = new iam.Role(stack, 'Role', {
const role = new iam.Role(this, 'Role', {
assumedBy: new iam.ServicePrincipal('lambda.amazonaws.com'),
});

Expand All @@ -529,6 +568,7 @@ This will grant the IAM principal the specified actions onto the activity.
to create an alarm on a particular task failing:

```ts
declare const task: sfn.Task;
new cloudwatch.Alarm(this, 'TaskAlarm', {
metric: task.metricFailed(),
threshold: 1,
Expand All @@ -539,6 +579,7 @@ new cloudwatch.Alarm(this, 'TaskAlarm', {
There are also metrics on the complete state machine:

```ts
declare const stateMachine: sfn.StateMachine;
new cloudwatch.Alarm(this, 'StateMachineAlarm', {
metric: stateMachine.metricFailed(),
threshold: 1,
Expand All @@ -550,7 +591,7 @@ And there are metrics on the capacity of all state machines in your account:

```ts
new cloudwatch.Alarm(this, 'ThrottledAlarm', {
metric: StateTransitionMetrics.metricThrottledEvents(),
metric: sfn.StateTransitionMetric.metricThrottledEvents(),
threshold: 10,
evaluationPeriods: 2,
});
Expand Down Expand Up @@ -578,10 +619,12 @@ Enable logging to CloudWatch by passing a logging configuration with a
destination LogGroup:

```ts
const logGroup = new logs.LogGroup(stack, 'MyLogGroup');
import * as logs from '@aws-cdk/aws-logs';

const logGroup = new logs.LogGroup(this, 'MyLogGroup');

new sfn.StateMachine(stack, 'MyStateMachine', {
definition: sfn.Chain.start(new sfn.Pass(stack, 'Pass')),
new sfn.StateMachine(this, 'MyStateMachine', {
definition: sfn.Chain.start(new sfn.Pass(this, 'Pass')),
logs: {
destination: logGroup,
level: sfn.LogLevel.ALL,
Expand All @@ -594,8 +637,8 @@ new sfn.StateMachine(stack, 'MyStateMachine', {
Enable X-Ray tracing for StateMachine:

```ts
new sfn.StateMachine(stack, 'MyStateMachine', {
definition: sfn.Chain.start(new sfn.Pass(stack, 'Pass')),
new sfn.StateMachine(this, 'MyStateMachine', {
definition: sfn.Chain.start(new sfn.Pass(this, 'Pass')),
tracingEnabled: true,
});
```
Expand All @@ -620,11 +663,12 @@ Any object that implements the `IGrantable` interface (has an associated princip
Grant permission to start an execution of a state machine by calling the `grantStartExecution()` API.

```ts
const role = new iam.Role(stack, 'Role', {
const role = new iam.Role(this, 'Role', {
assumedBy: new iam.ServicePrincipal('lambda.amazonaws.com'),
});

const stateMachine = new stepfunction.StateMachine(stack, 'StateMachine', {
declare const definition: sfn.IChainable;
const stateMachine = new sfn.StateMachine(this, 'StateMachine', {
definition,
});

Expand All @@ -641,11 +685,12 @@ The following permission is provided to a service principal by the `grantStartEx
Grant `read` access to a state machine by calling the `grantRead()` API.

```ts
const role = new iam.Role(stack, 'Role', {
const role = new iam.Role(this, 'Role', {
assumedBy: new iam.ServicePrincipal('lambda.amazonaws.com'),
});

const stateMachine = new stepfunction.StateMachine(stack, 'StateMachine', {
declare const definition: sfn.IChainable;
const stateMachine = new sfn.StateMachine(this, 'StateMachine', {
definition,
});

Expand All @@ -669,11 +714,12 @@ The following read permissions are provided to a service principal by the `grant
Grant permission to allow task responses to a state machine by calling the `grantTaskResponse()` API:

```ts
const role = new iam.Role(stack, 'Role', {
const role = new iam.Role(this, 'Role', {
assumedBy: new iam.ServicePrincipal('lambda.amazonaws.com'),
});

const stateMachine = new stepfunction.StateMachine(stack, 'StateMachine', {
declare const definition: sfn.IChainable;
const stateMachine = new sfn.StateMachine(this, 'StateMachine', {
definition,
});

Expand All @@ -692,11 +738,12 @@ The following read permissions are provided to a service principal by the `grant
Grant execution-level permissions to a state machine by calling the `grantExecution()` API:

```ts
const role = new iam.Role(stack, 'Role', {
const role = new iam.Role(this, 'Role', {
assumedBy: new iam.ServicePrincipal('lambda.amazonaws.com'),
});

const stateMachine = new stepfunction.StateMachine(stack, 'StateMachine', {
declare const definition: sfn.IChainable;
const stateMachine = new sfn.StateMachine(this, 'StateMachine', {
definition,
});

Expand All @@ -709,9 +756,10 @@ stateMachine.grantExecution(role, 'states:GetExecutionHistory');
You can add any set of permissions to a state machine by calling the `grant()` API.

```ts
const user = new iam.User(stack, 'MyUser');
const user = new iam.User(this, 'MyUser');

const stateMachine = new stepfunction.StateMachine(stack, 'StateMachine', {
declare const definition: sfn.IChainable;
const stateMachine = new sfn.StateMachine(this, 'StateMachine', {
definition,
});

Expand All @@ -727,8 +775,7 @@ into your CDK stack.
State machines can be imported by their ARN via the `StateMachine.fromStateMachineArn()` API

```ts
import * as sfn from 'aws-stepfunctions';

const app = new App();
const stack = new Stack(app, 'MyStack');
sfn.StateMachine.fromStateMachineArn(
stack,
Expand Down
14 changes: 14 additions & 0 deletions packages/@aws-cdk/aws-stepfunctions/rosetta/default.ts-fixture
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// Fixture with packages imported, but nothing else
import { Construct } from 'constructs';
import { App, CfnOutput, Duration, Stack } from '@aws-cdk/core';
import sfn = require('@aws-cdk/aws-stepfunctions');
import tasks = require('@aws-cdk/aws-stepfunctions-tasks');
import cloudwatch = require('@aws-cdk/aws-cloudwatch');
import iam = require('@aws-cdk/aws-iam');

class Fixture extends Stack {
constructor(scope: Construct, id: string) {
super(scope, id);
/// here
}
}
4 changes: 2 additions & 2 deletions packages/aws-cdk-lib/scripts/verify-readme-import-rewrites.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ const jsiiManifest = JSON.parse(fs.readFileSync(jsiiManifestPath, { encoding: 'u
// If this test fails because one of the below import statements is invalid,
// please update to have a new, comparable example.
// This is admittedly a bit fragile; if this test breaks a lot, we should reconsider validation methodology.
// Count of times this test has been broken by README updates so far (please increment as necessary! :D): 0
// Count of times this test has been broken by README updates so far (please increment as necessary! :D): 1
const EXPECTED_SUBMODULE_IMPORTS = {
// import * as origins from '@aws-cdk/aws-cloudfront-origins';
'aws-cdk-lib.aws_cloudfront_origins': "import { aws_cloudfront_origins as origins } from 'aws-cdk-lib';",
Expand All @@ -34,7 +34,7 @@ const EXPECTED_SUBMODULE_IMPORTS = {
// import { Rule, Schedule } from '@aws-cdk/aws-events';
'aws-cdk-lib.aws_events': "import { Rule, Schedule } from 'aws-cdk-lib/aws-events';",
// import * as cdk from '@aws-cdk/core';
'aws-cdk-lib.aws_stepfunctions': "import * as cdk from 'aws-cdk-lib';",
'aws-cdk-lib.aws_rds': "import * as cdk from 'aws-cdk-lib';",
};

Object.entries(EXPECTED_SUBMODULE_IMPORTS).forEach(([submodule, importStatement]) => {
Expand Down

0 comments on commit e1bf1b9

Please sign in to comment.