Skip to content

Commit 75bcd5e

Browse files
authored
Reduce standard waiter times (#316)
1 parent f581628 commit 75bcd5e

File tree

5 files changed

+127
-34
lines changed

5 files changed

+127
-34
lines changed

src/services/CfnService.ts

Lines changed: 28 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -60,11 +60,14 @@ import {
6060
ChangeSetType,
6161
} from '@aws-sdk/client-cloudformation';
6262
import { WaiterConfiguration, WaiterResult } from '@smithy/util-waiter';
63+
import { AwsClientSettings, DefaultSettings } from '../settings/Settings';
6364
import { DeploymentMode } from '../stacks/actions/StackActionRequestType';
6465
import { Count } from '../telemetry/TelemetryDecorator';
6566
import { AwsClient } from './AwsClient';
6667

6768
export class CfnService {
69+
private readonly awsClientSettings: AwsClientSettings = DefaultSettings.awsClient;
70+
6871
public constructor(private readonly awsClient: AwsClient) {}
6972

7073
protected async withClient<T>(request: (client: CloudFormationClient) => Promise<T>): Promise<T> {
@@ -334,66 +337,66 @@ export class CfnService {
334337
return await this.withClient((client) => client.send(new DeleteStackCommand(params)));
335338
}
336339

337-
public async waitUntilChangeSetCreateComplete(
338-
params: DescribeChangeSetCommandInput,
339-
timeoutMinutes: number = 5,
340-
): Promise<WaiterResult> {
340+
public async waitUntilChangeSetCreateComplete(params: DescribeChangeSetCommandInput): Promise<WaiterResult> {
341341
return await this.withClient(async (client) => {
342+
const settings = this.awsClientSettings;
342343
const waiterConfig: WaiterConfiguration<CloudFormationClient> = {
343344
client,
344-
maxWaitTime: timeoutMinutes * 60,
345+
maxWaitTime: settings.cloudformation.waiter.changeSet.maxWaitTime,
346+
minDelay: settings.cloudformation.waiter.changeSet.minDelay,
347+
maxDelay: settings.cloudformation.waiter.changeSet.maxDelay,
345348
};
346349
return await waitUntilChangeSetCreateComplete(waiterConfig, params);
347350
});
348351
}
349352

350-
public async waitUntilStackCreateComplete(
351-
params: DescribeStacksCommandInput,
352-
timeoutMinutes: number = 30,
353-
): Promise<WaiterResult> {
353+
public async waitUntilStackCreateComplete(params: DescribeStacksCommandInput): Promise<WaiterResult> {
354354
return await this.withClient(async (client) => {
355+
const settings = this.awsClientSettings;
355356
const waiterConfig: WaiterConfiguration<CloudFormationClient> = {
356357
client,
357-
maxWaitTime: timeoutMinutes * 60,
358+
maxWaitTime: settings.cloudformation.waiter.stack.maxWaitTime,
359+
minDelay: settings.cloudformation.waiter.stack.minDelay,
360+
maxDelay: settings.cloudformation.waiter.stack.maxDelay,
358361
};
359362
return await waitUntilStackCreateComplete(waiterConfig, params);
360363
});
361364
}
362365

363-
public async waitUntilStackUpdateComplete(
364-
params: DescribeStacksCommandInput,
365-
timeoutMinutes: number = 30,
366-
): Promise<WaiterResult> {
366+
public async waitUntilStackUpdateComplete(params: DescribeStacksCommandInput): Promise<WaiterResult> {
367367
return await this.withClient(async (client) => {
368+
const settings = this.awsClientSettings;
368369
const waiterConfig: WaiterConfiguration<CloudFormationClient> = {
369370
client,
370-
maxWaitTime: timeoutMinutes * 60,
371+
maxWaitTime: settings.cloudformation.waiter.stack.maxWaitTime,
372+
minDelay: settings.cloudformation.waiter.stack.minDelay,
373+
maxDelay: settings.cloudformation.waiter.stack.maxDelay,
371374
};
372375
return await waitUntilStackUpdateComplete(waiterConfig, params);
373376
});
374377
}
375378

376-
public async waitUntilStackImportComplete(
377-
params: DescribeStacksCommandInput,
378-
timeoutMinutes: number = 30,
379-
): Promise<WaiterResult> {
379+
public async waitUntilStackImportComplete(params: DescribeStacksCommandInput): Promise<WaiterResult> {
380380
return await this.withClient(async (client) => {
381+
const settings = this.awsClientSettings;
381382
const waiterConfig: WaiterConfiguration<CloudFormationClient> = {
382383
client,
383-
maxWaitTime: timeoutMinutes * 60,
384+
maxWaitTime: settings.cloudformation.waiter.stack.maxWaitTime,
385+
minDelay: settings.cloudformation.waiter.stack.minDelay,
386+
maxDelay: settings.cloudformation.waiter.stack.maxDelay,
384387
};
385388
return await waitUntilStackImportComplete(waiterConfig, params);
386389
});
387390
}
388391

389-
public async waitUntilStackDeleteComplete(
390-
params: DescribeStacksCommandInput,
391-
timeoutMinutes: number = 30,
392-
): Promise<WaiterResult> {
392+
public async waitUntilStackDeleteComplete(params: DescribeStacksCommandInput): Promise<WaiterResult> {
393393
return await this.withClient(async (client) => {
394+
const settings = this.awsClientSettings;
394395
const waiterConfig: WaiterConfiguration<CloudFormationClient> = {
395396
client,
396-
maxWaitTime: timeoutMinutes * 60,
397+
maxWaitTime: settings.cloudformation.waiter.stack.maxWaitTime,
398+
minDelay: settings.cloudformation.waiter.stack.minDelay,
399+
maxDelay: settings.cloudformation.waiter.stack.maxDelay,
397400
};
398401
return await waitUntilStackDeleteComplete(waiterConfig, params);
399402
});

src/settings/Settings.ts

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,12 +65,30 @@ export type EditorSettings = {
6565
detectIndentation: boolean;
6666
};
6767

68+
export type AwsClientSettings = {
69+
cloudformation: {
70+
waiter: {
71+
changeSet: {
72+
minDelay: number;
73+
maxDelay: number;
74+
maxWaitTime: number;
75+
};
76+
stack: {
77+
minDelay: number;
78+
maxDelay: number;
79+
maxWaitTime: number;
80+
};
81+
};
82+
};
83+
};
84+
6885
export interface Settings {
6986
profile: ProfileSettings;
7087
hover: HoverSettings;
7188
completion: CompletionSettings;
7289
diagnostics: DiagnosticsSettings;
7390
editor: EditorSettings;
91+
awsClient: AwsClientSettings;
7492
}
7593

7694
export const DefaultSettings: DeepReadonly<Settings> = {
@@ -126,6 +144,22 @@ export const DefaultSettings: DeepReadonly<Settings> = {
126144
insertSpaces: true,
127145
detectIndentation: true,
128146
},
147+
awsClient: {
148+
cloudformation: {
149+
waiter: {
150+
changeSet: {
151+
minDelay: 1,
152+
maxDelay: 8,
153+
maxWaitTime: 600,
154+
},
155+
stack: {
156+
minDelay: 3,
157+
maxDelay: 10,
158+
maxWaitTime: 1800,
159+
},
160+
},
161+
},
162+
},
129163
} as const;
130164

131165
export class SettingsState implements Settings {
@@ -134,6 +168,7 @@ export class SettingsState implements Settings {
134168
completion = structuredClone(DefaultSettings.completion);
135169
diagnostics = structuredClone(DefaultSettings.diagnostics);
136170
editor = structuredClone(DefaultSettings.editor);
171+
awsClient = structuredClone(DefaultSettings.awsClient);
137172

138173
update(settings: Settings): void {
139174
Object.assign(this, structuredClone(settings));

src/settings/SettingsParser.ts

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,46 @@ function createSettingsSchema(defaults: Settings) {
148148
completion: createCompletionSchema(defaults.completion),
149149
diagnostics: createDiagnosticsSchema(defaults.diagnostics),
150150
editor: createEditorSchema(defaults.editor),
151+
awsClient: z
152+
.object({
153+
cloudformation: z
154+
.object({
155+
waiter: z
156+
.object({
157+
changeSet: z
158+
.object({
159+
minDelay: z
160+
.number()
161+
.default(defaults.awsClient.cloudformation.waiter.changeSet.minDelay),
162+
maxDelay: z
163+
.number()
164+
.default(defaults.awsClient.cloudformation.waiter.changeSet.maxDelay),
165+
maxWaitTime: z
166+
.number()
167+
.default(
168+
defaults.awsClient.cloudformation.waiter.changeSet.maxWaitTime,
169+
),
170+
})
171+
.default(defaults.awsClient.cloudformation.waiter.changeSet),
172+
stack: z
173+
.object({
174+
minDelay: z
175+
.number()
176+
.default(defaults.awsClient.cloudformation.waiter.stack.minDelay),
177+
maxDelay: z
178+
.number()
179+
.default(defaults.awsClient.cloudformation.waiter.stack.maxDelay),
180+
maxWaitTime: z
181+
.number()
182+
.default(defaults.awsClient.cloudformation.waiter.stack.maxWaitTime),
183+
})
184+
.default(defaults.awsClient.cloudformation.waiter.stack),
185+
})
186+
.default(defaults.awsClient.cloudformation.waiter),
187+
})
188+
.default(defaults.awsClient.cloudformation),
189+
})
190+
.default(defaults.awsClient),
151191
})
152192
.default(defaults);
153193
}

tst/unit/services/CfnService.test.ts

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -631,12 +631,12 @@ describe('CfnService', () => {
631631
vi.mocked(waitUntilChangeSetCreateComplete).mockResolvedValue(mockWaiterResult);
632632

633633
const params = { ChangeSetName: 'test-changeset', StackName: 'test-stack' };
634-
const result = await service.waitUntilChangeSetCreateComplete(params, 10);
634+
const result = await service.waitUntilChangeSetCreateComplete(params);
635635

636636
expect(waitUntilChangeSetCreateComplete).toHaveBeenCalledWith(
637637
expect.objectContaining({
638638
client: expect.any(Object),
639-
maxWaitTime: 600, // 10 minutes * 60 seconds
639+
maxWaitTime: 600,
640640
}),
641641
params,
642642
);
@@ -652,7 +652,7 @@ describe('CfnService', () => {
652652

653653
expect(waitUntilChangeSetCreateComplete).toHaveBeenCalledWith(
654654
expect.objectContaining({
655-
maxWaitTime: 300, // 5 minutes * 60 seconds
655+
maxWaitTime: 600,
656656
}),
657657
params,
658658
);
@@ -666,12 +666,12 @@ describe('CfnService', () => {
666666
vi.mocked(waitUntilStackUpdateComplete).mockResolvedValue(mockWaiterResult);
667667

668668
const params = { StackName: 'test-stack' };
669-
const result = await service.waitUntilStackUpdateComplete(params, 60);
669+
const result = await service.waitUntilStackUpdateComplete(params);
670670

671671
expect(waitUntilStackUpdateComplete).toHaveBeenCalledWith(
672672
expect.objectContaining({
673673
client: expect.any(Object),
674-
maxWaitTime: 3600, // 60 minutes * 60 seconds
674+
maxWaitTime: 1800,
675675
}),
676676
params,
677677
);
@@ -727,18 +727,17 @@ describe('CfnService', () => {
727727
expect(result).toBe(mockWaiterResult);
728728
});
729729

730-
it('should use custom timeout when provided', async () => {
730+
it('should use timeout from settings', async () => {
731731
const params = { StackName: 'test-stack' };
732-
const timeoutMinutes = 15;
733732
const mockWaiterResult = { state: WaiterState.SUCCESS };
734733

735734
vi.mocked(waitUntilStackCreateComplete).mockResolvedValue(mockWaiterResult);
736735

737-
const result = await service.waitUntilStackCreateComplete(params, timeoutMinutes);
736+
const result = await service.waitUntilStackCreateComplete(params);
738737

739738
expect(waitUntilStackCreateComplete).toHaveBeenCalledWith(
740739
expect.objectContaining({
741-
maxWaitTime: timeoutMinutes * 60,
740+
maxWaitTime: 1800,
742741
}),
743742
params,
744743
);

tst/unit/settings/Settings.test.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,22 @@ describe('SettingsState', () => {
6363
insertSpaces: false,
6464
detectIndentation: true,
6565
},
66+
awsClient: {
67+
cloudformation: {
68+
waiter: {
69+
changeSet: {
70+
minDelay: 1,
71+
maxDelay: 8,
72+
maxWaitTime: 600,
73+
},
74+
stack: {
75+
minDelay: 3,
76+
maxDelay: 10,
77+
maxWaitTime: 1800,
78+
},
79+
},
80+
},
81+
},
6682
};
6783

6884
settingsState.update(newSettings);

0 commit comments

Comments
 (0)