Skip to content

Commit cf923bc

Browse files
authored
feat(stepfunctions): CustomState addCatch (#28422)
Adds a public `addCatch` method to the stepfunctions `CustomState` state. Closes #25798. ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
1 parent c687778 commit cf923bc

File tree

5 files changed

+74
-3
lines changed

5 files changed

+74
-3
lines changed

packages/@aws-cdk-testing/framework-integ/test/aws-stepfunctions/test/integ.custom-state.js.snapshot/aws-stepfunctions-custom-state-integ.template.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
"Arn"
2727
]
2828
},
29-
"DefinitionString": "{\"StartAt\":\"my custom task\",\"States\":{\"my custom task\":{\"Next\":\"final step\",\"Type\":\"Task\",\"Resource\":\"arn:aws:states:::dynamodb:putItem\",\"Parameters\":{\"TableName\":\"my-cool-table\",\"Item\":{\"id\":{\"S\":\"my-entry\"}}},\"ResultPath\":null},\"final step\":{\"Type\":\"Pass\",\"End\":true}},\"TimeoutSeconds\":30}"
29+
"DefinitionString": "{\"StartAt\":\"my custom task\",\"States\":{\"my custom task\":{\"Next\":\"final step\",\"Type\":\"Task\",\"Resource\":\"arn:aws:states:::dynamodb:putItem\",\"Parameters\":{\"TableName\":\"my-cool-table\",\"Item\":{\"id\":{\"S\":\"my-entry\"}}},\"ResultPath\":null,\"Catch\":[{\"ErrorEquals\":[\"States.ALL\"],\"Next\":\"failed\"}]},\"final step\":{\"Type\":\"Pass\",\"End\":true},\"failed\":{\"Type\":\"Fail\",\"Error\":\"DidNotWork\",\"Cause\":\"We got stuck\"}},\"TimeoutSeconds\":30}"
3030
},
3131
"DependsOn": [
3232
"StateMachineRoleB840431D"

packages/@aws-cdk-testing/framework-integ/test/aws-stepfunctions/test/integ.custom-state.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,17 @@ const stateJson = {
2525
ResultPath: null,
2626
};
2727

28+
const failure = new sfn.Fail(stack, 'failed', {
29+
error: 'DidNotWork',
30+
cause: 'We got stuck',
31+
});
32+
2833
const custom = new sfn.CustomState(stack, 'my custom task', {
2934
stateJson,
3035
});
3136

37+
custom.addCatch(failure);
38+
3239
const chain = sfn.Chain.start(custom).next(finalStatus);
3340

3441
const sm = new sfn.StateMachine(stack, 'StateMachine', {

packages/aws-cdk-lib/aws-stepfunctions/README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -598,6 +598,10 @@ const custom = new sfn.CustomState(this, 'my custom task', {
598598
stateJson,
599599
});
600600

601+
// catch errors with addCatch
602+
const errorHandler = new sfn.Pass(this, 'handle failure');
603+
custom.addCatch(errorHandler);
604+
601605
const chain = sfn.Chain.start(custom)
602606
.next(finalStatus);
603607

packages/aws-cdk-lib/aws-stepfunctions/lib/states/custom-state.ts

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { Construct } from 'constructs';
22
import { State } from './state';
33
import { Chain } from '..';
4-
import { IChainable, INextable } from '../types';
4+
import { CatchProps, IChainable, INextable } from '../types';
55

66
/**
77
* Properties for defining a custom state definition
@@ -25,7 +25,7 @@ export class CustomState extends State implements IChainable, INextable {
2525
/**
2626
* Amazon States Language (JSON-based) definition of the state
2727
*/
28-
private readonly stateJson: { [key: string]: any};
28+
private readonly stateJson: { [key: string]: any };
2929

3030
constructor(scope: Construct, id: string, props: CustomStateProps) {
3131
super(scope, id, {});
@@ -34,6 +34,17 @@ export class CustomState extends State implements IChainable, INextable {
3434
this.stateJson = props.stateJson;
3535
}
3636

37+
/**
38+
* Add a recovery handler for this state
39+
*
40+
* When a particular error occurs, execution will continue at the error
41+
* handler instead of failing the state machine execution.
42+
*/
43+
public addCatch(handler: IChainable, props: CatchProps = {}): CustomState {
44+
super._addCatch(handler.startState, props);
45+
return this;
46+
}
47+
3748
/**
3849
* Continue normal execution with the given state
3950
*/
@@ -49,6 +60,7 @@ export class CustomState extends State implements IChainable, INextable {
4960
return {
5061
...this.renderNextEnd(),
5162
...this.stateJson,
63+
...this.renderRetryCatch(),
5264
};
5365
}
5466
}

packages/aws-cdk-lib/aws-stepfunctions/test/custom-state.test.ts

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ describe('Custom State', () => {
3333
// THEN
3434
expect(customState.toStateJson()).toStrictEqual({
3535
...stateJson,
36+
...{ Catch: undefined, Retry: undefined },
3637
End: true,
3738
});
3839
});
@@ -72,4 +73,51 @@ describe('Custom State', () => {
7273
},
7374
);
7475
});
76+
77+
test('can add a catch state', () => {
78+
// GIVEN
79+
const failure = new sfn.Fail(stack, 'failed', {
80+
error: 'DidNotWork',
81+
cause: 'We got stuck',
82+
});
83+
const custom = new sfn.CustomState(stack, 'Custom', {
84+
stateJson,
85+
});
86+
const chain = sfn.Chain.start(custom);
87+
88+
// WHEN
89+
custom.addCatch(failure);
90+
91+
// THEN
92+
expect(render(stack, chain)).toStrictEqual(
93+
{
94+
StartAt: 'Custom',
95+
States: {
96+
Custom: {
97+
Type: 'Task',
98+
Resource: 'arn:aws:states:::dynamodb:putItem',
99+
Parameters: {
100+
TableName: 'MyTable',
101+
Item: {
102+
id: {
103+
S: 'MyEntry',
104+
},
105+
},
106+
},
107+
ResultPath: null,
108+
Catch: [{
109+
ErrorEquals: ['States.ALL'],
110+
Next: 'failed',
111+
}],
112+
End: true,
113+
},
114+
failed: {
115+
Type: 'Fail',
116+
Error: 'DidNotWork',
117+
Cause: 'We got stuck',
118+
},
119+
},
120+
},
121+
);
122+
});
75123
});

0 commit comments

Comments
 (0)