@dontirun/state-machine-semaphore
An aws-cdk construct that enables you to use AWS Step Functions to control concurrency in your distributed system. You can use this construct to distributed state machine semaphores to control concurrent invocations of contentious work.
This construct is based off of Justin Callison's example code. Make sure to check out Justin's blogpost to learn about how the system works.
Examples
Example 1) A state machine with a controlled job
Click to see code
import { Function } from 'aws-cdk-lib/aws-lambda';
import { Duration, Stack, StackProps } from 'aws-cdk-lib';
import { StateMachine, Succeed, Wait, WaitTime } from 'aws-cdk-lib/aws-stepfunctions';
import { LambdaInvoke } from 'aws-cdk-lib/aws-stepfunctions-tasks';
import { Construct } from 'constructs';
import { Semaphore } from '@dontirun/state-machine-semaphore';
export class CdkTestStack extends Stack {
constructor(scope: Construct, id: string, props?: StackProps) {
super(scope, id, props);
const contestedJob = new LambdaInvoke(this, 'ContestedJobPart1', {
lambdaFunction: Function.fromFunctionName(this, 'JobFunctionPart1', 'cool-function'),
}).next(new Wait(this, 'Wait', { time: WaitTime.duration(Duration.seconds(7)) }))
.next(new Wait(this, 'AnotherWait', { time: WaitTime.duration(Duration.seconds(7)) }))
.next(new Wait(this, 'YetAnotherWait', { time: WaitTime.duration(Duration.seconds(7)) }));
const afterContestedJob = new Succeed(this, 'Succeed');
const stateMachineFragment = new Semaphore(stack, 'Semaphore', { lockName: 'life', limit: 42, job: contestedJob, nextState: afterContestedJob });
new StateMachine(this, 'StateMachine', {
definition: stateMachineFragment,
});
}
}
Click to see the state machine definition
Example 2) A state machine with multiple semaphores
Click to see code
import { Function } from 'aws-cdk-lib/aws-lambda';
import { Duration, Stack, StackProps } from 'aws-cdk-lib';
import { StateMachine, Succeed, Wait, WaitTime } from 'aws-cdk-lib/aws-stepfunctions';
import { LambdaInvoke } from 'aws-cdk-lib/aws-stepfunctions-tasks';
import { Construct } from 'constructs';
import { Semaphore } from '@dontirun/state-machine-semaphore';
export class CdkTestStack extends Stack {
constructor(scope: Construct, id: string, props?: StackProps) {
super(scope, id, props);
const contestedJob = new LambdaInvoke(this, 'ContestedJobPart1', {
lambdaFunction: Function.fromFunctionName(this, 'JobFunctionPart1', 'cool-function'),
})
const notContestedJob = new LambdaInvoke(this, 'NotContestedJob', {
lambdaFunction: Function.fromFunctionName(this, 'NotContestedJobFunction', 'cooler-function'),
})
const contestedJob2 = new LambdaInvoke(this, 'ContestedJobPart2', {
lambdaFunction: Function.fromFunctionName(this, 'JobFunctionPart2', 'coolest-function'),
})
const afterContestedJob2 = new Succeed(this, 'Succeed');
const definition = new Semaphore(stack, 'Semaphore', { lockName: 'life', limit: 42, job: contestedJob, nextState: notContestedJob })
.next(new Semaphore(stack, 'Semaphore2', { lockName: 'liberty', limit: 7, job: contestedJob2, nextState: afterContestedJob2 }));
new StateMachine(this, 'StateMachine', {
definition: definition,
});
}
}
Click to see the state machine definition
API Reference
See API.md.
License
This project is licensed under the Apache-2.0 License.