Skip to content

Commit 22358a3

Browse files
committed
fix(amazonq): added abortController back
1 parent 2e59395 commit 22358a3

File tree

3 files changed

+48
-33
lines changed

3 files changed

+48
-33
lines changed

package-lock.json

Lines changed: 0 additions & 27 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

server/aws-lsp-codewhisperer/src/language-server/agenticChat/retry/retryConfig.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,6 @@ export class AdaptiveRetryConfig {
8686

8787
/**
8888
* Calculate exponential backoff delay with jitter
89-
* Matches CLI's calculate_exponential_backoff logic
9089
*/
9190
static calculateExponentialBackoff(
9291
baseMultiplier: number,
@@ -100,7 +99,7 @@ export class AdaptiveRetryConfig {
10099

101100
/**
102101
* Generate jitter base multiplier
103-
* Matches CLI's fastrand::f64() behavior
102+
* Matches fastrand::f64() behavior
104103
*/
105104
static generateJitterBase(useStatic: boolean): number {
106105
return useStatic ? 1.0 : Math.random()

server/aws-lsp-codewhisperer/src/language-server/chat/chatSessionService.ts

Lines changed: 47 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,11 @@ export class ChatSessionService {
188188
const client = this.#serviceManager.getStreamingClient()
189189

190190
// Execute with retry logic
191-
return await this.#executeWithRetry(() => client.sendMessage(request), 'sendMessage', TokenCost.InitialRequest)
191+
return await this.#executeWithRetry(
192+
() => client.sendMessage(request, this.#abortController),
193+
'sendMessage',
194+
TokenCost.InitialRequest
195+
)
192196
}
193197

194198
private isModelSelectionEnabled(): boolean {
@@ -218,13 +222,13 @@ export class ChatSessionService {
218222

219223
async #performChatRequest(client: any, request: ChatCommandInput): Promise<ChatCommandOutput> {
220224
if (client instanceof StreamingClientServiceToken) {
221-
return await client.generateAssistantResponse(request)
225+
return await client.generateAssistantResponse(request, this.#abortController)
222226
} else if (client instanceof StreamingClientServiceIAM) {
223227
// @ts-ignore
224228
// SendMessageStreaming checks for origin from request source
225229
// https://code.amazon.com/packages/AWSVectorConsolasRuntimeService/blobs/ac917609a28dbcb6757a8427bcc585a42fd15bf2/--/src/com/amazon/aws/vector/consolas/runtimeservice/activity/SendMessageStreamingActivity.java#L246
226230
request.source = this.#origin ? this.#origin : 'IDE'
227-
return await client.sendMessage(request)
231+
return await client.sendMessage(request, this.#abortController)
228232
} else {
229233
// error
230234
return Promise.reject(
@@ -305,19 +309,45 @@ export class ChatSessionService {
305309
const startTime = Date.now()
306310

307311
while (attempt <= this.#retryConfig.maxAttempts) {
312+
// Check if request was aborted before each attempt
313+
if (this.#abortController?.signal.aborted) {
314+
const abortError = new Error('Request aborted')
315+
abortError.name = 'AbortError'
316+
throw abortError
317+
}
318+
308319
try {
309320
// Check rate limiter and apply delay if needed
310321
const rateLimitDelayMs = this.#rateLimiter.checkAndCalculateDelay(tokenCost)
311322
if (rateLimitDelayMs > 0) {
312323
if (attempt === 1) {
313324
this.#delayTracker.trackInitialDelay(rateLimitDelayMs)
314325
}
326+
// Check abort before applying delay
327+
if (this.#abortController?.signal.aborted) {
328+
const abortError = new Error('Request aborted')
329+
abortError.name = 'AbortError'
330+
throw abortError
331+
}
315332
await this.#rateLimiter.applyDelayAndConsumeTokens(rateLimitDelayMs, tokenCost)
316333
} else if (this.#rateLimiter.isEnabled()) {
317334
// Consume tokens even if no delay
318335
await this.#rateLimiter.applyDelayAndConsumeTokens(0, tokenCost)
319336
}
320337

338+
// TEST: Throw throttling exception on first attempt
339+
if (attempt === 1) {
340+
const throttlingError = new Error(
341+
'Encountered unexpectedly high load when processing the request, please try again.'
342+
)
343+
;(throttlingError as any).cause = {
344+
$metadata: {
345+
httpStatusCode: 500,
346+
},
347+
}
348+
throw throttlingError
349+
}
350+
321351
const response = await operation()
322352

323353
// Track success for rate limiter recovery
@@ -341,6 +371,13 @@ export class ChatSessionService {
341371
break
342372
}
343373

374+
// Check abort before continuing with retry logic
375+
if (this.#abortController?.signal.aborted) {
376+
const abortError = new Error('Request aborted')
377+
abortError.name = 'AbortError'
378+
throw abortError
379+
}
380+
344381
// Activate rate limiter for throttling errors
345382
if (retryAction === RetryAction.ThrottlingError) {
346383
const wasEnabled = this.#rateLimiter.isEnabled()
@@ -380,8 +417,14 @@ export class ChatSessionService {
380417
this.#delayTracker.trackRetryDelay(totalDelayMs, attempt + 1, previousDelayMs)
381418
previousDelayMs = totalDelayMs
382419

383-
// Apply the delay
420+
// Apply the delay with abort checking
384421
if (totalDelayMs > 0) {
422+
// Check abort before delay
423+
if (this.#abortController?.signal.aborted) {
424+
const abortError = new Error('Request aborted')
425+
abortError.name = 'AbortError'
426+
throw abortError
427+
}
385428
await new Promise(resolve => setTimeout(resolve, totalDelayMs))
386429
}
387430

0 commit comments

Comments
 (0)