in source/patterns/apigw-kds-lambda.ts [28:244]
constructor(scope: cdk.Construct, id: string, props: SolutionStackProps) {
super(scope, id, props);
//---------------------------------------------------------------------
// Kinesis Data Stream configuration
const shardCount = new cdk.CfnParameter(this, 'ShardCount', {
type: 'Number',
default: 2,
minValue: 1,
maxValue: 200
});
const dataRetention = new cdk.CfnParameter(this, 'RetentionHours', {
type: 'Number',
default: 24,
minValue: 24,
maxValue: 8760
});
const enhancedMonitoring = new cdk.CfnParameter(this, 'EnableEnhancedMonitoring', {
type: 'String',
default: 'false',
allowedValues: ['true', 'false']
});
const kds = new DataStream(this, 'Kds', {
shardCount: shardCount.valueAsNumber,
retentionPeriod: cdk.Duration.hours(dataRetention.valueAsNumber),
enableEnhancedMonitoring: enhancedMonitoring.valueAsString
});
//---------------------------------------------------------------------
// API Gateway configuration
const rateLimit = new cdk.CfnParameter(this, 'ThrottlingRateLimit', {
type: 'Number',
default: 100,
minValue: 1,
maxValue: 10000
});
const burstLimit = new cdk.CfnParameter(this, 'ThrottlingBurstLimit', {
type: 'Number',
default: 50,
minValue: 0,
maxValue: 5000
});
/*
The following method will create an user pool and an app client.
If you have existing resources, you can modify this file to import them:
cognito.UserPool.fromUserPoolArn(this, 'ExistingUserPool', 'my-user-pool-arn');
cognito.UserPoolClient.fromUserPoolClientId(this, 'ExistingAppClient', 'my-client-id');
*/
const { userPool, userPoolClient } = this.createCognitoResources();
const apiGwToKds = new ApiGatewayToKinesisStreams(this, 'ApiGwKds', {
apiGatewayProps: {
restApiName: `${cdk.Aws.STACK_NAME}-kinesis-proxy`,
deployOptions: {
methodOptions: {
'/*/*': {
throttlingRateLimit: rateLimit.valueAsNumber,
throttlingBurstLimit: burstLimit.valueAsNumber
}
}
},
defaultMethodOptions: {
authorizationType: apigw.AuthorizationType.COGNITO,
authorizer: new apigw.CognitoUserPoolsAuthorizer(this, 'ApiAuthorizer', {
cognitoUserPools: [userPool]
})
}
},
existingStreamObj: kds.Stream
});
//---------------------------------------------------------------------
// Lambda function configuration
const batchSize = new cdk.CfnParameter(this, 'BatchSize', {
type: 'Number',
default: 100,
minValue: 1,
maxValue: 10000
});
const parallelization = new cdk.CfnParameter(this, 'ParallelizationFactor', {
type: 'Number',
default: 1,
minValue: 1,
maxValue: 10
});
const retryAttempts = new cdk.CfnParameter(this, 'MaxRetryAttempts', {
type: 'Number',
default: 3,
minValue: 1,
maxValue: 10000
});
const kdsToLambda = new KinesisStreamsToLambda(this, 'KdsLambda', {
existingStreamObj: kds.Stream,
createCloudWatchAlarms: false,
deploySqsDlqQueue: true,
lambdaFunctionProps: {
runtime: lambda.Runtime.NODEJS_14_X,
handler: 'index.handler',
code: lambda.Code.fromAsset('lambda/kds-lambda-consumer'),
timeout: cdk.Duration.minutes(5)
},
kinesisEventSourceProps: {
startingPosition: lambda.StartingPosition.LATEST,
batchSize: batchSize.valueAsNumber,
retryAttempts: parallelization.valueAsNumber,
parallelizationFactor: retryAttempts.valueAsNumber,
bisectBatchOnError: true
}
});
//---------------------------------------------------------------------
// Monitoring (dashboard and alarms) configuration
new DataStreamMonitoring(this, 'Monitoring', {
streamName: kds.Stream.streamName,
lambdaFunctionName: kdsToLambda.lambdaFunction.functionName
});
//---------------------------------------------------------------------
// Solution metrics
new SolutionHelper(this, 'SolutionHelper', {
solutionId: props.solutionId,
pattern: ApiGwKdsLambda.name,
shardCount: shardCount.valueAsNumber,
retentionHours: dataRetention.valueAsNumber,
enhancedMonitoring: enhancedMonitoring.valueAsString
});
//---------------------------------------------------------------------
// Template metadata
this.templateOptions.metadata = {
'AWS::CloudFormation::Interface': {
ParameterGroups: [
{
Label: { default: 'Amazon API Gateway configuration' },
Parameters: [rateLimit.logicalId, burstLimit.logicalId]
},
{
Label: { default: 'Amazon Kinesis Data Streams configuration' },
Parameters: [shardCount.logicalId, dataRetention.logicalId, enhancedMonitoring.logicalId]
},
{
Label: { default: 'AWS Lambda consumer configuration' },
Parameters: [batchSize.logicalId, parallelization.logicalId, retryAttempts.logicalId]
}
],
ParameterLabels: {
[rateLimit.logicalId]: {
default: 'Steady-state requests per second'
},
[burstLimit.logicalId]: {
default: 'Burst requests per second'
},
[shardCount.logicalId]: {
default: 'Number of open shards'
},
[dataRetention.logicalId]: {
default: 'Data retention period (hours)'
},
[enhancedMonitoring.logicalId]: {
default: 'Enable enhanced (shard-level) metrics'
},
[batchSize.logicalId]: {
default: 'Largest number of records that will be read from the stream at once'
},
[parallelization.logicalId]: {
default: 'Number of batches to process from each shard concurrently'
},
[retryAttempts.logicalId]: {
default: 'Maximum number of times to retry when the function returns an error'
}
}
}
};
//---------------------------------------------------------------------
// Stack outputs
new cdk.CfnOutput(this, 'UserPoolId', {
description: 'ID of the Amazon Cognito user pool',
value: userPool.userPoolId
});
new cdk.CfnOutput(this, 'UserPoolClientId', {
description: 'ID of the Amazon Cognito user pool client',
value: userPoolClient.userPoolClientId
});
new cdk.CfnOutput(this, 'ProxyApiId', {
description: 'ID of the proxy API',
value: apiGwToKds.apiGateway.restApiId
});
new cdk.CfnOutput(this, 'ProxyApiEndpoint', {
description: 'Deployed URL of the proxy API',
value: apiGwToKds.apiGateway.url
});
new cdk.CfnOutput(this, 'DataStreamName', {
description: 'Name of the Amazon Kinesis Data stream',
value: kds.Stream.streamName
});
new cdk.CfnOutput(this, 'LambdaConsumerArn', {
description: 'ARN of the AWS Lambda function',
value: kdsToLambda.lambdaFunction.functionArn
});
}