Skip to content

Commit

Permalink
fix(stepfunctions): the Retry field in the statesJson in CustomState …
Browse files Browse the repository at this point in the history
…is always overwrited (#28793)

After #28422 was merged, the regression that overwrites the Retry field defined in the stateJson was introduced.
The `this.renderRetryCatch()` method overwrites the Retry field in the stateJson.
https://github.com/aws/aws-cdk/blob/45b8398bec9ba9c03f195c14f3b92188c9058a7b/packages/aws-cdk-lib/aws-stepfunctions/lib/states/custom-state.ts#L74

This PR fixes this regression and clarifies the current behavior for configuring the Retry and Catch field.

Previously, I added the `addRetry` method to add the Retry field and did not render the Retry field in the stateJson in #28598, but this is initially a regression and should have been fixed.

Closes #28769
Relates #28586

----

*By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
  • Loading branch information
sakurai-ryo committed Feb 1, 2024
1 parent 4a7c432 commit 3c33e2c
Show file tree
Hide file tree
Showing 8 changed files with 102 additions and 7 deletions.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
"StateMachine2E01A3A5": {
"Type": "AWS::StepFunctions::StateMachine",
"Properties": {
"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,\"Retry\":[{\"ErrorEquals\":[\"States.ALL\"],\"IntervalSeconds\":10,\"MaxAttempts\":5}],\"Catch\":[{\"ErrorEquals\":[\"States.ALL\"],\"Next\":\"failed\"}]},\"final step\":{\"Type\":\"Pass\",\"End\":true},\"failed\":{\"Type\":\"Fail\",\"Error\":\"DidNotWork\",\"Cause\":\"We got stuck\"}},\"TimeoutSeconds\":30}",
"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,\"Retry\":[{\"ErrorEquals\":[\"States.Timeout\"],\"IntervalSeconds\":10,\"MaxAttempts\":5},{\"ErrorEquals\":[\"States.Permissions\"],\"IntervalSeconds\":20,\"MaxAttempts\":2}],\"Catch\":[{\"ErrorEquals\":[\"States.ALL\"],\"Next\":\"failed\"}]},\"final step\":{\"Type\":\"Pass\",\"End\":true},\"failed\":{\"Type\":\"Fail\",\"Error\":\"DidNotWork\",\"Cause\":\"We got stuck\"}},\"TimeoutSeconds\":30}",
"RoleArn": {
"Fn::GetAtt": [
"StateMachineRoleB840431D",
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,11 @@ const stateJson = {
},
},
ResultPath: null,
Retry: [{
ErrorEquals: [sfn.Errors.PERMISSIONS],
IntervalSeconds: 20,
MaxAttempts: 2,
}],
};

const failure = new sfn.Fail(stack, 'failed', {
Expand All @@ -36,7 +41,7 @@ const custom = new sfn.CustomState(stack, 'my custom task', {

custom.addCatch(failure);
custom.addRetry({
errors: [sfn.Errors.ALL],
errors: [sfn.Errors.TIMEOUT],
interval: cdk.Duration.seconds(10),
maxAttempts: 5,
});
Expand Down
4 changes: 4 additions & 0 deletions packages/aws-cdk-lib/aws-stepfunctions/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -562,6 +562,10 @@ Custom states can be chained together with any of the other states to create you
definition. You will also need to provide any permissions that are required to the `role` that
the State Machine uses.

The Retry and Catch fields are available for error handling.
You can configure the Retry field by defining it in the JSON object or by adding it using the `addRetry` method.
However, the Catch field cannot be configured by defining it in the JSON object, so it must be added using the `addCatch` method.

The following example uses the `DynamoDB` service integration to insert data into a DynamoDB table.

```ts
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,10 +68,17 @@ export class CustomState extends State implements IChainable, INextable {
* Returns the Amazon States Language object for this state
*/
public toStateJson(): object {
return {
const state = {
...this.renderNextEnd(),
...this.stateJson,
...this.renderRetryCatch(),
};

// merge the Retry filed defined in the stateJson into the state
if (Array.isArray(this.stateJson.Retry)) {
state.Retry = [...state.Retry, ...this.stateJson.Retry];
}

return state;
}
}
79 changes: 79 additions & 0 deletions packages/aws-cdk-lib/aws-stepfunctions/test/custom-state.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -163,4 +163,83 @@ describe('Custom State', () => {
},
);
});

test('respect the Retry field in the stateJson', () => {
// GIVEN
const custom = new sfn.CustomState(stack, 'Custom', {
stateJson: {
Type: 'Task',
Resource: 'arn:aws:states:::dynamodb:putItem',
Parameters: {
TableName: 'MyTable',
Item: {
id: {
S: 'MyEntry',
},
},
},
ResultPath: null,
Retry: [
{
ErrorEquals: [sfn.Errors.TIMEOUT],
IntervalSeconds: 20,
MaxAttempts: 2,
},
{
ErrorEquals: [sfn.Errors.RESULT_PATH_MATCH_FAILURE],
IntervalSeconds: 20,
MaxAttempts: 2,
},
],
},
});
const chain = sfn.Chain.start(custom);

// WHEN
custom.addRetry({
errors: [sfn.Errors.PERMISSIONS],
interval: cdk.Duration.seconds(10),
maxAttempts: 5,
});

// THEN
expect(render(stack, chain)).toStrictEqual(
{
StartAt: 'Custom',
States: {
Custom: {
Type: 'Task',
Resource: 'arn:aws:states:::dynamodb:putItem',
Parameters: {
TableName: 'MyTable',
Item: {
id: {
S: 'MyEntry',
},
},
},
ResultPath: null,
Retry: [
{
ErrorEquals: ['States.Permissions'],
IntervalSeconds: 10,
MaxAttempts: 5,
},
{
ErrorEquals: ['States.Timeout'],
IntervalSeconds: 20,
MaxAttempts: 2,
},
{
ErrorEquals: ['States.ResultPathMatchFailure'],
IntervalSeconds: 20,
MaxAttempts: 2,
},
],
End: true,
},
},
},
);
});
});

0 comments on commit 3c33e2c

Please sign in to comment.