forked from aws/aws-cdk
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix(cli): stack monitor reads complete stack history every 5 seconds (a…
…ws#9795) The stack monitor used to read all stack events on every tick (every 1-5 seconds). That's right, every 5 seconds it would page through all events that had ever happened to the stack, only to get to the last page to see if there were new events. We were quadratic in our `DescribeStackEvents` API call. This behavior has probably contributed to our users getting throttled by CloudFormation in the past, and only really shows pathological behavior on stacks with a long history (which we ourselves don't routinely manage using `cdk deploy`), which is why it had eluded detection for so long. The fix is to remember the token of the last page between calls, so that we don't have to read through all pages just to get to the last one. Fixes aws#9470. ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
- Loading branch information
1 parent
a59b7e0
commit 9b9921d
Showing
3 changed files
with
169 additions
and
87 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
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,57 @@ | ||
import { StackActivityMonitor, IActivityPrinter, StackActivity } from '../../lib/api/util/cloudformation/stack-activity-monitor'; | ||
import { sleep } from '../integ/cli/aws-helpers'; | ||
import { MockSdk } from './mock-sdk'; | ||
|
||
let sdk: MockSdk; | ||
let printer: FakePrinter; | ||
beforeEach(() => { | ||
sdk = new MockSdk(); | ||
printer = new FakePrinter(); | ||
}); | ||
|
||
test('retain page token between ticks', async () => { | ||
let finished = false; | ||
sdk.stubCloudFormation({ | ||
describeStackEvents: (jest.fn() as jest.Mock<AWS.CloudFormation.DescribeStackEventsOutput, [AWS.CloudFormation.DescribeStackEventsInput]>) | ||
// First call, return a page token | ||
.mockImplementationOnce((request) => { | ||
expect(request.NextToken).toBeUndefined(); | ||
return { NextToken: 'token' }; | ||
}) | ||
// Second call, expect page token, return no page | ||
.mockImplementationOnce(request => { | ||
expect(request.NextToken).toEqual('token'); | ||
return { }; | ||
}) | ||
// Third call, ensure we still get the same page token | ||
.mockImplementationOnce(request => { | ||
expect(request.NextToken).toEqual('token'); | ||
finished = true; | ||
return { }; | ||
}), | ||
}); | ||
|
||
const monitor = new StackActivityMonitor(sdk.cloudFormation(), 'StackName', printer).start(); | ||
await waitForCondition(() => finished); | ||
await monitor.stop(); | ||
}); | ||
|
||
|
||
class FakePrinter implements IActivityPrinter { | ||
public updateSleep: number = 0; | ||
public readonly activities: StackActivity[] = []; | ||
|
||
public addActivity(activity: StackActivity): void { | ||
this.activities.push(activity); | ||
} | ||
|
||
public print(): void { } | ||
public start(): void { } | ||
public stop(): void { } | ||
} | ||
|
||
async function waitForCondition(cb: () => boolean): Promise<void> { | ||
while (!cb()) { | ||
await sleep(10); | ||
} | ||
} |