-
Notifications
You must be signed in to change notification settings - Fork 3.9k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix(cli): excessive stack event polling during deployment (#32196)
Closes #32186 ### Reason for this change <!--What is the bug or use case behind this change?--> The CLI will poll for all stack events from the beginning of time, even though it will end up using only a fraction of them to display in the terminal. This can cause a significant slowdown of `cdk deploy`. ### Description of changes <!--What code changes did you make? Have you made any important design decisions?--> Moved the pagination to the caller side, so it can decide whether or not to poll the next page. This is how it was before `2.167.0` https://github.com/aws/aws-cdk/blob/7bb9203eb95fe894c0d40942ff49c782a9fec251/packages/aws-cdk/lib/api/util/cloudformation/stack-event-poller.ts#L73-L74 ### Description of how you validated changes <!--Have you added any unit tests and/or integration tests?--> Added unit test. ### Notes - There are several functions in the [sdk.ts](https://github.com/aws/aws-cdk/blob/main/packages/aws-cdk/lib/api/aws-auth/sdk.ts) that perform implicit pagination to retrieve all results. From a quick glance, none of them seem to be misusing it though (at least with respect to how it always was). I will investigate those functions further in a followup PR. ### Checklist - [x] My code adheres to the [CONTRIBUTING GUIDE](https://github.com/aws/aws-cdk/blob/main/CONTRIBUTING.md) and [DESIGN GUIDELINES](https://github.com/aws/aws-cdk/blob/main/docs/DESIGN_GUIDELINES.md) ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
- Loading branch information
Showing
3 changed files
with
136 additions
and
59 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
83 changes: 83 additions & 0 deletions
83
packages/aws-cdk/test/api/util/cloudformation/stack-event-poller.test.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
import { DescribeStackEventsCommand, DescribeStackEventsCommandInput, StackEvent } from '@aws-sdk/client-cloudformation'; | ||
import { StackEventPoller } from '../../../../lib/api/util/cloudformation/stack-event-poller'; | ||
import { MockSdk, mockCloudFormationClient } from '../../../util/mock-sdk'; | ||
|
||
beforeEach(() => { | ||
jest.resetAllMocks(); | ||
}); | ||
|
||
describe('poll', () => { | ||
|
||
test('polls all necessary pages', async () => { | ||
|
||
const deployTime = Date.now(); | ||
|
||
const postDeployEvent1: StackEvent = { | ||
Timestamp: new Date(deployTime + 1000), | ||
EventId: 'event-1', | ||
StackId: 'stack-id', | ||
StackName: 'stack', | ||
}; | ||
|
||
const postDeployEvent2: StackEvent = { | ||
Timestamp: new Date(deployTime + 2000), | ||
EventId: 'event-2', | ||
StackId: 'stack-id', | ||
StackName: 'stack', | ||
}; | ||
|
||
const sdk = new MockSdk(); | ||
mockCloudFormationClient.on(DescribeStackEventsCommand).callsFake((input: DescribeStackEventsCommandInput) => { | ||
const result = { | ||
StackEvents: input.NextToken === 'token' ? [postDeployEvent2] : [postDeployEvent1], | ||
NextToken: input.NextToken === 'token' ? undefined : 'token', // simulate a two page event stream. | ||
}; | ||
|
||
return result; | ||
}); | ||
|
||
const poller = new StackEventPoller(sdk.cloudFormation(), { | ||
stackName: 'stack', | ||
startTime: new Date().getTime(), | ||
}); | ||
|
||
const events = await poller.poll(); | ||
expect(events.length).toEqual(2); | ||
|
||
}); | ||
|
||
test('does not poll unnecessary pages', async () => { | ||
|
||
const deployTime = Date.now(); | ||
|
||
const preDeployTimeEvent: StackEvent = { | ||
Timestamp: new Date(deployTime - 1000), | ||
EventId: 'event-1', | ||
StackId: 'stack-id', | ||
StackName: 'stack', | ||
}; | ||
|
||
const sdk = new MockSdk(); | ||
mockCloudFormationClient.on(DescribeStackEventsCommand).callsFake((input: DescribeStackEventsCommandInput) => { | ||
|
||
// the first event we return should stop the polling. we therefore | ||
// do not expect a second page to be polled. | ||
expect(input.NextToken).toBe(undefined); | ||
|
||
return { | ||
StackEvents: [preDeployTimeEvent], | ||
NextToken: input.NextToken === 'token' ? undefined : 'token', // simulate a two page event stream. | ||
}; | ||
|
||
}); | ||
|
||
const poller = new StackEventPoller(sdk.cloudFormation(), { | ||
stackName: 'stack', | ||
startTime: new Date().getTime(), | ||
}); | ||
|
||
await poller.poll(); | ||
|
||
}); | ||
|
||
}); |