Skip to content

Commit 62f1946

Browse files
authored
fix(codecatalyst): skip DevEnv connect if quota exceeded #3446
Problem: When customer's Space has reached quota, trying to connect to a DevEnv waits a long time instead of failing immediately. Solution: Cancel the wait loop if `ServiceQuotaExceededException` is detected.
1 parent 9fa97a1 commit 62f1946

File tree

2 files changed

+36
-22
lines changed

2 files changed

+36
-22
lines changed
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"type": "Bug Fix",
3+
"description": "CodeCatalyst: When a Space has reached quota, trying to connect to a DevEnv waits a long time instead of failing immediately."
4+
}

src/shared/clients/codecatalystClient.ts

Lines changed: 32 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -630,9 +630,10 @@ class CodeCatalystClientInternal {
630630
return shortname
631631
}
632632

633-
function failedStartMsg() {
633+
function failedStartMsg(serviceMsg?: string) {
634634
const lastStatus = statuses[statuses.length - 1]?.status
635-
return `Dev Environment failed to start (${lastStatus}): ${getName()}`
635+
const serviceMsg_ = serviceMsg ? `${serviceMsg}: ` : ''
636+
return `Dev Environment failed to start (${lastStatus}): ${serviceMsg_}${getName()}`
636637
}
637638

638639
const doLog = (kind: 'debug' | 'error' | 'info', msg: string) => {
@@ -680,17 +681,25 @@ class CodeCatalystClientInternal {
680681
const lastStatus = statuses[statuses.length - 1]
681682
const elapsed = Date.now() - lastStatus.start
682683
const resp = await this.getDevEnvironment(args)
684+
const serviceReason = (resp.statusReason ?? '').trim()
683685
alias = resp.alias
684686

685687
if (
686-
lastStatus &&
688+
startAttempts > 2 &&
689+
elapsed > 10000 &&
687690
['STOPPED', 'FAILED'].includes(lastStatus.status) &&
688-
['STOPPED', 'FAILED'].includes(resp.status) &&
689-
elapsed > 60000 &&
690-
startAttempts > 2
691+
['STOPPED', 'FAILED'].includes(resp.status)
691692
) {
692-
// If still STOPPED/FAILED after 60+ seconds, don't keep retrying for 1 hour...
693-
throw new ToolkitError(failedStartMsg(), { code: 'FailedDevEnv' })
693+
const fails = statuses.filter(o => o.status === 'FAILED').length
694+
const code = fails === 0 ? 'BadDevEnvState' : 'FailedDevEnv'
695+
696+
if (serviceReason !== '') {
697+
// Service gave a status reason like "Compute limit exceeded", show it to the user.
698+
throw new ToolkitError(failedStartMsg(resp.statusReason), { code: code })
699+
}
700+
701+
// If still STOPPED/FAILED after 10+ seconds, don't keep retrying for 1 hour...
702+
throw new ToolkitError(failedStartMsg(), { code: code })
694703
} else if (['STOPPED', 'FAILED'].includes(resp.status)) {
695704
progress.report({
696705
message: localize('AWS.CodeCatalyst.devenv.resuming', 'Resuming Dev Environment...'),
@@ -700,9 +709,16 @@ class CodeCatalystClientInternal {
700709
await this.startDevEnvironment(args)
701710
} catch (e) {
702711
const err = e as AWS.AWSError
712+
// - ServiceQuotaExceededException: account billing limit reached
703713
// - ValidationException: "… creation has failed, cannot start"
704714
// - ConflictException: "Cannot start … because update process is still going on"
705715
// (can happen after "Update Dev Environment")
716+
if (err.code === 'ServiceQuotaExceededException') {
717+
throw new ToolkitError('Dev Environment failed: quota exceeded', {
718+
code: 'ServiceQuotaExceeded',
719+
cause: err,
720+
})
721+
}
706722
doLog('info', `devenv not started (${err.code}), waiting`)
707723
// Continue retrying...
708724
}
@@ -729,23 +745,17 @@ class CodeCatalystClientInternal {
729745
)
730746

731747
const devenv = await waitTimeout(pollDevEnv, timeout).catch(e => {
732-
const err = e as Error
733-
const starts = statuses.filter(o => o.status === 'STARTING').length
734-
const fails = statuses.filter(o => o.status === 'FAILED').length
735-
736-
if (!isUserCancelledError(e)) {
737-
doLog('error', 'devenv failed to start')
738-
} else {
748+
if (isUserCancelledError(e)) {
739749
doLog('info', 'devenv failed to start (user cancelled)')
740-
err.message = failedStartMsg()
741-
throw err
750+
e.message = failedStartMsg()
751+
throw e
752+
} else if (e instanceof ToolkitError) {
753+
doLog('error', 'devenv failed to start')
754+
throw e
742755
}
743756

744-
if (starts > 1 && fails === 0) {
745-
throw new ToolkitError(failedStartMsg(), { code: 'BadDevEnvState', cause: err })
746-
} else if (fails > 0) {
747-
throw new ToolkitError(failedStartMsg(), { code: 'FailedDevEnv', cause: err })
748-
}
757+
doLog('error', 'devenv failed to start')
758+
throw new ToolkitError(failedStartMsg(), { code: 'Unknown', cause: e })
749759
})
750760

751761
if (!devenv) {

0 commit comments

Comments
 (0)