Skip to content

Commit 33ecd9b

Browse files
(Fix): SM jitter (#1050)
* exponential backoff fix * exponential backoff fix * Fixed backoff for lambdas * added backoff in other location * fixed lambda timeouts and added timeout aspect * fixed typo * tweak default max jitter delay to 2s from 5s Co-authored-by: hickeydh-aws <hickeydh@amazon.com> Co-authored-by: Brian969 <56414362+Brian969@users.noreply.github.com>
1 parent 5f02a9a commit 33ecd9b

File tree

18 files changed

+103
-13
lines changed

18 files changed

+103
-13
lines changed

reference-artifacts/Add-ons/opensiem/lambdas/common/src/backoff.ts

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,24 @@ export function throttlingBackOff<T>(
2020
request: () => Promise<T>,
2121
options?: Partial<Omit<IBackOffOptions, 'retry'>>,
2222
): Promise<T> {
23+
const defaultDelay = 500;
24+
let maxDelayValue = 2000;
25+
26+
if (process.env.BACKOFF_START_DELAY) {
27+
const backoffStartDelay = parseInt(process.env.BACKOFF_START_DELAY, 10);
28+
if (Number.isInteger(backoffStartDelay)) {
29+
maxDelayValue = backoffStartDelay;
30+
}
31+
}
32+
33+
// Add jitter to the starting delay
34+
const startingDelay = Math.random() * (maxDelayValue - defaultDelay + 1) + defaultDelay;
35+
36+
console.log(`throttlingBackOff delay set to ${startingDelay}`);
37+
2338
return backOff(request, {
24-
startingDelay: 500,
39+
startingDelay,
40+
delayFirstAttempt: true,
2541
jitter: 'full',
2642
retry: isThrottlingError,
2743
...options,
@@ -34,6 +50,7 @@ export const isThrottlingError = (e: any) =>
3450
e.code === 'ConcurrentModificationException' || // Retry for AWS Organizations
3551
e.code === 'InsufficientDeliveryPolicyException' || // Retry for ConfigService
3652
e.code === 'NoAvailableDeliveryChannelException' || // Retry for ConfigService
53+
e.code === 'ConcurrentModifications' || // Retry for AssociateHostedZone
3754
e.code === 'TooManyRequestsException' ||
3855
e.code === 'Throttling' ||
3956
e.code === 'ThrottlingException' ||

src/core/cdk/src/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ async function main() {
3939
env.CONFIG_S3_BUCKET || `${acceleratorPrefix.toLowerCase()}${cdk.Aws.ACCOUNT_ID}-${cdk.Aws.REGION}-config`;
4040
const codebuildComputeType = env.BUILD_COMPUTE_TYPE || 'BUILD_GENERAL1_LARGE';
4141
const pageSize = env.DEPLOY_STACK_PAGE_SIZE || '900';
42+
const backoff = env.BACKOFF_START_DELAY;
4243
const enablePrebuiltProject = 'ENABLE_PREBUILT_PROJECT' in env;
4344
const notificationEmail = env.NOTIFICATION_EMAIL || 'notify@example.com';
4445
const installerCmk = env.INSTALLER_CMK || `alias/${acceleratorPrefix}Installer-Key`;
@@ -70,6 +71,7 @@ async function main() {
7071
installerCmk,
7172
codebuildComputeType,
7273
pageSize,
74+
backoff,
7375
});
7476
}
7577

src/core/cdk/src/initial-setup.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ export namespace InitialSetup {
5757
// eslint-disable-next-line @typescript-eslint/no-explicit-any
5858
codebuildComputeType: any;
5959
pageSize: string;
60+
backoff: string | undefined;
6061
/**
6162
* Current Accelerator version
6263
*/
@@ -264,6 +265,7 @@ export namespace InitialSetup {
264265
SUBNET_CIDR_ASSIGNED_POOL: subnetCidrPoolTable.tableName,
265266
CIDR_POOL: cidrPoolTable.tableName,
266267
DEPLOY_STACK_PAGE_SIZE: props.pageSize,
268+
BACKOFF_START_DELAY: props.backoff || '',
267269
COMPUTE_TYPE: props.codebuildComputeType,
268270
},
269271
});

src/deployments/cdk/src/common/alb-ip-forwarding.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ export class AlbIpForwarding extends Construct {
5959
runtime: lambda.Runtime.NODEJS_14_X,
6060
code: lambdaCode,
6161
handler: 'index.albIpMonitor',
62-
timeout: Duration.seconds(30),
62+
timeout: Duration.seconds(60),
6363
environment: {
6464
LOOKUP_TABLE: ddbTable.tableName,
6565
},
@@ -82,7 +82,7 @@ export class AlbIpForwarding extends Construct {
8282
runtime: lambda.Runtime.NODEJS_14_X,
8383
handler: 'index.albTargetRecordMonitor',
8484
code: lambdaCode,
85-
timeout: Duration.seconds(30),
85+
timeout: Duration.seconds(60),
8686
environment: {
8787
LOOKUP_TABLE: ddbTable.tableName,
8888
},

src/installer/cdk/src/index.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,12 @@ class Installer extends cdk.Stack {
115115
default: 680,
116116
});
117117

118+
const backoffStartDelay = new cdk.CfnParameter(this, 'Backoff Start Delay', {
119+
description:
120+
'The start delay for exponential backoff of API calls in milliseconds. Leave at the default of 2000 unless needed.',
121+
default: 2000,
122+
});
123+
118124
const stateMachineName = `${acceleratorPrefix}MainStateMachine_sm`;
119125

120126
// The state machine name has to match the name of the state machine in initial setup
@@ -322,6 +328,10 @@ class Installer extends cdk.Stack {
322328
type: codebuild.BuildEnvironmentVariableType.PLAINTEXT,
323329
value: stackDeployPageSize.valueAsString,
324330
},
331+
BACKOFF_START_DELAY: {
332+
type: codebuild.BuildEnvironmentVariableType.PLAINTEXT,
333+
value: backoffStartDelay.valueAsString,
334+
},
325335
},
326336
},
327337
cache: codebuild.Cache.local(codebuild.LocalCacheMode.SOURCE),

src/lib/cdk-accelerator/src/core/accelerator-stack.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
*/
1313

1414
import * as cdk from '@aws-cdk/core';
15-
import { AcceleratorNameTagger, AcceleratorProtectedTagger } from '.';
15+
import { AcceleratorNameTagger, AcceleratorProtectedTagger, LambdaEnvironmentVariables, LambdaDefaultTimeout } from '.';
1616

1717
export interface AcceleratorStackProps extends cdk.StackProps {
1818
acceleratorName: string;
@@ -34,6 +34,8 @@ export class AcceleratorStack extends cdk.Stack {
3434
cdk.Aspects.of(this).add(new cdk.Tag('Accelerator', this.acceleratorName));
3535
cdk.Aspects.of(this).add(new AcceleratorNameTagger());
3636
cdk.Aspects.of(this).add(new AcceleratorProtectedTagger(this.acceleratorName));
37+
cdk.Aspects.of(this).add(new LambdaEnvironmentVariables());
38+
cdk.Aspects.of(this).add(new LambdaDefaultTimeout());
3739
}
3840

3941
static of(construct: cdk.IConstruct): AcceleratorStack {

src/lib/cdk-accelerator/src/core/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,5 @@
1414
export * from './cfn-include';
1515
export * from './name-tagger';
1616
export * from './accelerator-protected-tagger';
17+
export * from './lambda-env-variables';
18+
export * from './lambda-default-timeout';
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import * as cdk from '@aws-cdk/core';
2+
import * as lambda from '@aws-cdk/aws-lambda';
3+
4+
export class LambdaDefaultTimeout implements cdk.IAspect {
5+
visit(node: cdk.IConstruct): void {
6+
if (node instanceof lambda.CfnFunction) {
7+
if (!node.timeout) {
8+
node.timeout = 60;
9+
}
10+
}
11+
}
12+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import * as cdk from '@aws-cdk/core';
2+
import * as lambda from '@aws-cdk/aws-lambda';
3+
4+
export class LambdaEnvironmentVariables implements cdk.IAspect {
5+
visit(node: cdk.IConstruct): void {
6+
if (node instanceof lambda.Function) {
7+
node.addEnvironment('BACKOFF_START_DELAY', process.env['BACKOFF_START_DELAY'] || '2000');
8+
}
9+
}
10+
}

src/lib/common/src/aws/backoff.ts

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,24 @@ export function throttlingBackOff<T>(
2020
request: () => Promise<T>,
2121
options?: Partial<Omit<IBackOffOptions, 'retry'>>,
2222
): Promise<T> {
23+
const defaultDelay = 500;
24+
let maxDelayValue = 2000;
25+
26+
if (process.env.BACKOFF_START_DELAY) {
27+
const backoffStartDelay = parseInt(process.env.BACKOFF_START_DELAY, 10);
28+
if (Number.isInteger(backoffStartDelay)) {
29+
maxDelayValue = backoffStartDelay;
30+
}
31+
}
32+
33+
// Add jitter to the starting delay
34+
const startingDelay = Math.random() * (maxDelayValue - defaultDelay + 1) + defaultDelay;
35+
36+
console.log(`throttlingBackOff delay set to ${startingDelay}`);
37+
2338
return backOff(request, {
24-
startingDelay: 500,
39+
startingDelay,
40+
delayFirstAttempt: true,
2541
jitter: 'full',
2642
retry: isThrottlingError,
2743
...options,
@@ -34,6 +50,7 @@ export const isThrottlingError = (e: any) =>
3450
e.code === 'ConcurrentModificationException' || // Retry for AWS Organizations
3551
e.code === 'InsufficientDeliveryPolicyException' || // Retry for ConfigService
3652
e.code === 'NoAvailableDeliveryChannelException' || // Retry for ConfigService
53+
e.code === 'ConcurrentModifications' || // Retry for AssociateHostedZone
3754
e.code === 'TooManyRequestsException' ||
3855
e.code === 'Throttling' ||
3956
e.code === 'ThrottlingException' ||

0 commit comments

Comments
 (0)