Skip to content

Commit ba8fda7

Browse files
committed
refactor the attempt codes
1 parent a44427f commit ba8fda7

File tree

1 file changed

+71
-19
lines changed

1 file changed

+71
-19
lines changed

packages/amazonq/src/lsp/client.ts

Lines changed: 71 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,47 @@ import { AutoDebugFeature } from 'aws-core-vscode/amazonq'
5555
const localize = nls.loadMessageBundle()
5656
const logger = getLogger('amazonqLsp.lspClient')
5757

58+
interface RetryOptions {
59+
maxAttempts: number
60+
initialDelayMs: number
61+
maxDelayMs: number
62+
backoffMultiplier: number
63+
onRetry?: (attempt: number, error: Error) => void
64+
onFailure?: (attempts: number, lastError: Error) => void
65+
}
66+
67+
/**
68+
* Retry a function with exponential backoff
69+
*/
70+
async function retryWithExponentialBackoff<T>(fn: () => T | Promise<T>, options: RetryOptions): Promise<T> {
71+
const { maxAttempts, initialDelayMs, maxDelayMs, backoffMultiplier, onRetry, onFailure } = options
72+
73+
let lastError: Error
74+
75+
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
76+
try {
77+
return await fn()
78+
} catch (error) {
79+
lastError = error instanceof Error ? error : new Error(String(error))
80+
81+
if (attempt === maxAttempts) {
82+
onFailure?.(attempt, lastError)
83+
throw lastError
84+
}
85+
86+
onRetry?.(attempt, lastError)
87+
88+
// Calculate delay with exponential backoff
89+
const delay = Math.min(initialDelayMs * Math.pow(backoffMultiplier, attempt - 1), maxDelayMs)
90+
91+
await new Promise((resolve) => setTimeout(resolve, delay))
92+
}
93+
}
94+
95+
// This should never be reached, but TypeScript requires it
96+
throw lastError!
97+
}
98+
5899
export function hasGlibcPatch(): boolean {
59100
// Skip GLIBC patching for SageMaker environments
60101
if (isSageMaker()) {
@@ -256,27 +297,38 @@ async function onLanguageServerReady(
256297
try {
257298
getLogger('amazonqLsp').debug('Attempting to connect AutoDebug feature to language client')
258299

259-
// Function to attempt connection
260-
const attemptConnection = (attempt: number = 1): void => {
261-
const autoDebugFeature = (global as any).autoDebugFeature as AutoDebugFeature | undefined
262-
263-
if (autoDebugFeature) {
300+
await retryWithExponentialBackoff(
301+
() => {
302+
const autoDebugFeature = (global as any).autoDebugFeature as AutoDebugFeature | undefined
303+
if (!autoDebugFeature) {
304+
throw new Error('AutoDebug feature not available')
305+
}
264306
autoDebugFeature.setLanguageClient(client, encryptionKey)
265-
} else if (attempt < 5) {
266-
// Retry up to 5 times with exponential backoff
267-
const delay = Math.min(1000 * Math.pow(2, attempt - 1), 10000) // Max 10 seconds
268-
setTimeout(() => attemptConnection(attempt + 1), delay)
269-
} else {
270-
getLogger('amazonqLsp').error(
271-
'AutoDebug feature not found after %d attempts - integration will not work. ' +
272-
'This may indicate that the AutoDebug feature failed to activate or there is a timing issue.',
273-
attempt
274-
)
307+
getLogger('amazonqLsp').debug('AutoDebug feature connected successfully')
308+
},
309+
{
310+
maxAttempts: 5,
311+
initialDelayMs: 1000,
312+
maxDelayMs: 10000,
313+
backoffMultiplier: 2,
314+
onRetry: (attempt, error) => {
315+
getLogger('amazonqLsp').debug(
316+
'AutoDebug connection attempt %d failed: %s. Retrying...',
317+
attempt,
318+
error.message
319+
)
320+
},
321+
onFailure: (attempts, lastError) => {
322+
getLogger('amazonqLsp').error(
323+
'AutoDebug feature not found after %d attempts - integration will not work. ' +
324+
'This may indicate that the AutoDebug feature failed to activate or there is a timing issue. ' +
325+
'Last error: %s',
326+
attempts,
327+
lastError.message
328+
)
329+
},
275330
}
276-
}
277-
278-
// Start the connection attempts
279-
attemptConnection()
331+
)
280332
} catch (error) {
281333
getLogger('amazonqLsp').error('Failed to connect AutoDebug feature to language client: %s', error)
282334
}

0 commit comments

Comments
 (0)