-
Notifications
You must be signed in to change notification settings - Fork 4k
/
waiter-state-machine.ts
97 lines (85 loc) · 2.76 KB
/
waiter-state-machine.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
import { Construct } from 'constructs';
import { Grant, IGrantable, Role, ServicePrincipal } from '../../../aws-iam';
import { IFunction } from '../../../aws-lambda';
import { CfnResource, Duration, Stack } from '../../../core';
export interface WaiterStateMachineProps {
/**
* The main handler that notifies if the waiter to decide 'complete' or 'incomplete'.
*/
readonly isCompleteHandler: IFunction;
/**
* The handler to call if the waiter times out and is incomplete.
*/
readonly timeoutHandler: IFunction;
/**
* The interval to wait between attempts.
*/
readonly interval: Duration;
/**
* Number of attempts.
*/
readonly maxAttempts: number;
/**
* Backoff between attempts.
*/
readonly backoffRate: number;
}
/**
* A very simple StateMachine construct highly customized to the provider framework.
* This is so that this package does not need to depend on aws-stepfunctions module.
*
* The state machine continuously calls the isCompleteHandler, until it succeeds or times out.
* The handler is called `maxAttempts` times with an `interval` duration and a `backoffRate` rate.
*/
export class WaiterStateMachine extends Construct {
public readonly stateMachineArn: string;
constructor(scope: Construct, id: string, props: WaiterStateMachineProps) {
super(scope, id);
const role = new Role(this, 'Role', {
assumedBy: new ServicePrincipal('states.amazonaws.com'),
});
props.isCompleteHandler.grantInvoke(role);
props.timeoutHandler.grantInvoke(role);
const definition = Stack.of(this).toJsonString({
StartAt: 'framework-isComplete-task',
States: {
'framework-isComplete-task': {
End: true,
Retry: [{
ErrorEquals: ['States.ALL'],
IntervalSeconds: props.interval.toSeconds(),
MaxAttempts: props.maxAttempts,
BackoffRate: props.backoffRate,
}],
Catch: [{
ErrorEquals: ['States.ALL'],
Next: 'framework-onTimeout-task',
}],
Type: 'Task',
Resource: props.isCompleteHandler.functionArn,
},
'framework-onTimeout-task': {
End: true,
Type: 'Task',
Resource: props.timeoutHandler.functionArn,
},
},
});
const resource = new CfnResource(this, 'Resource', {
type: 'AWS::StepFunctions::StateMachine',
properties: {
DefinitionString: definition,
RoleArn: role.roleArn,
},
});
resource.node.addDependency(role);
this.stateMachineArn = resource.ref;
}
public grantStartExecution(identity: IGrantable) {
return Grant.addToPrincipal({
grantee: identity,
actions: ['states:StartExecution'],
resourceArns: [this.stateMachineArn],
});
}
}