Skip to content

Commit 12a118c

Browse files
jogoldElad Ben-Israel
authored andcommitted
fix(lambda): avoid OperationAbortedException when using log retention (#2237)
If multiple LogRetention constructs are present in the stack, they will try to act on the provider's log group at the same time. This can sometime result in an OperationAbortedException. To avoid this and because this operation is not critical it is better to catch all errors when acting on the provider's log group
1 parent 8f0468a commit 12a118c

File tree

2 files changed

+45
-3
lines changed

2 files changed

+45
-3
lines changed

packages/@aws-cdk/aws-lambda/lib/log-retention-provider/index.ts

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,9 +49,16 @@ export async function handler(event: AWSLambda.CloudFormationCustomResourceEvent
4949
// group for this function should already exist at this stage because we
5050
// already logged the event but due to the async nature of Lambda logging
5151
// there could be a race condition. So we also try to create the log group
52-
// of this function first.
53-
await createLogGroupSafe(`/aws/lambda/${context.functionName}`);
54-
await setRetentionPolicy(`/aws/lambda/${context.functionName}`, 1);
52+
// of this function first. If multiple LogRetention constructs are present
53+
// in the stack, they will try to act on this function's log group at the
54+
// same time. This can sometime result in an OperationAbortedException. To
55+
// avoid this and because this operation is not critical we catch all errors.
56+
try {
57+
await createLogGroupSafe(`/aws/lambda/${context.functionName}`);
58+
await setRetentionPolicy(`/aws/lambda/${context.functionName}`, 1);
59+
} catch (e) {
60+
console.log(e);
61+
}
5562
}
5663
}
5764

packages/@aws-cdk/aws-lambda/test/test.log-retention-provider.ts

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import AWSSDK = require('aws-sdk');
12
import AWS = require('aws-sdk-mock');
23
import nock = require('nock');
34
import { Test } from 'nodeunit';
@@ -227,4 +228,38 @@ export = {
227228

228229
test.done();
229230
},
231+
232+
async 'does not fail when operations on provider log group fail'(test: Test) {
233+
const createLogGroupFake = (params: AWSSDK.CloudWatchLogs.CreateLogGroupRequest) => {
234+
if (params.logGroupName === '/aws/lambda/provider') {
235+
return Promise.reject(new Error('OperationAbortedException'));
236+
}
237+
return Promise.resolve({});
238+
};
239+
240+
const putRetentionPolicyFake = sinon.fake.resolves({});
241+
const deleteRetentionPolicyFake = sinon.fake.resolves({});
242+
243+
AWS.mock('CloudWatchLogs', 'createLogGroup', createLogGroupFake);
244+
AWS.mock('CloudWatchLogs', 'putRetentionPolicy', putRetentionPolicyFake);
245+
AWS.mock('CloudWatchLogs', 'deleteRetentionPolicy', deleteRetentionPolicyFake);
246+
247+
const event = {
248+
...eventCommon,
249+
RequestType: 'Create',
250+
ResourceProperties: {
251+
ServiceToken: 'token',
252+
RetentionInDays: '30',
253+
LogGroupName: 'group'
254+
}
255+
};
256+
257+
const request = createRequest('SUCCESS');
258+
259+
await provider.handler(event as AWSLambda.CloudFormationCustomResourceCreateEvent, context);
260+
261+
test.equal(request.isDone(), true);
262+
263+
test.done();
264+
}
230265
};

0 commit comments

Comments
 (0)