fix(runtime-fallback): match Volcano Engine 'exceeded the usage quota' errors
Volcano Engine sends quota exceeded errors with the words in reverse order: 'You have exceeded the 5-hour usage quota'. The existing patterns required 'quota' to precede 'exceeded', so they never matched. - Add /exceeded.*quota/i and /usage.?quota/i to RETRYABLE_ERROR_PATTERNS - Add exceeded.*quota and usage\s*quota to AUTO_RETRY_PATTERNS - Add regression tests for both detection paths Fixes: runtime-fallback not triggering on Volcano Engine quota errors
This commit is contained in:
@@ -0,0 +1,41 @@
|
|||||||
|
import { describe, expect, test } from "bun:test"
|
||||||
|
|
||||||
|
import { extractAutoRetrySignal } from "./auto-retry-signal"
|
||||||
|
|
||||||
|
describe("extractAutoRetrySignal", () => {
|
||||||
|
test("detects Volcano Engine 'exceeded the usage quota' signal", () => {
|
||||||
|
//#given
|
||||||
|
const info = {
|
||||||
|
status: "You have exceeded the 5-hour usage quota. It will reset at 2026-05-11 01:20:12 +0800 CST.",
|
||||||
|
}
|
||||||
|
|
||||||
|
//#when
|
||||||
|
const signal = extractAutoRetrySignal(info)
|
||||||
|
|
||||||
|
//#then
|
||||||
|
expect(signal).toBeDefined()
|
||||||
|
expect(signal?.signal).toContain("exceeded")
|
||||||
|
})
|
||||||
|
|
||||||
|
test("detects standard 'quota exceeded' signal", () => {
|
||||||
|
//#given
|
||||||
|
const info = { message: "Quota exceeded for model gpt-4" }
|
||||||
|
|
||||||
|
//#when
|
||||||
|
const signal = extractAutoRetrySignal(info)
|
||||||
|
|
||||||
|
//#then
|
||||||
|
expect(signal).toBeDefined()
|
||||||
|
})
|
||||||
|
|
||||||
|
test("returns undefined for non-retryable info", () => {
|
||||||
|
//#given
|
||||||
|
const info = { message: "Something went wrong" }
|
||||||
|
|
||||||
|
//#when
|
||||||
|
const signal = extractAutoRetrySignal(info)
|
||||||
|
|
||||||
|
//#then
|
||||||
|
expect(signal).toBeUndefined()
|
||||||
|
})
|
||||||
|
})
|
||||||
@@ -5,7 +5,7 @@ export interface AutoRetrySignal {
|
|||||||
const AUTO_RETRY_PATTERNS: Array<(combined: string) => boolean> = [
|
const AUTO_RETRY_PATTERNS: Array<(combined: string) => boolean> = [
|
||||||
(combined) => /retrying\s+in/i.test(combined),
|
(combined) => /retrying\s+in/i.test(combined),
|
||||||
(combined) =>
|
(combined) =>
|
||||||
/(?:too\s+many\s+requests|quota\s+will\s+reset\s+after|quota\s*exceeded|usage\s+limit|rate\s+limit|limit\s+reached|all\s+credentials\s+for\s+model|cool(?:ing)?\s*down|exhausted\s+your\s+capacity)/i.test(combined),
|
/(?:too\s+many\s+requests|quota\s+will\s+reset\s+after|quota\s*exceeded|exceeded.*quota|usage\s+limit|usage\s*quota|rate\s+limit|limit\s+reached|all\s+credentials\s+for\s+model|cool(?:ing)?\s*down|exhausted\s+your\s+capacity)/i.test(combined),
|
||||||
]
|
]
|
||||||
|
|
||||||
export function extractAutoRetrySignal(info: Record<string, unknown> | undefined): AutoRetrySignal | undefined {
|
export function extractAutoRetrySignal(info: Record<string, unknown> | undefined): AutoRetrySignal | undefined {
|
||||||
|
|||||||
@@ -27,6 +27,8 @@ export const RETRYABLE_ERROR_PATTERNS = [
|
|||||||
/too.?many.?requests/i,
|
/too.?many.?requests/i,
|
||||||
/quota\s+will\s+reset\s+after/i,
|
/quota\s+will\s+reset\s+after/i,
|
||||||
/quota.?exceeded/i,
|
/quota.?exceeded/i,
|
||||||
|
/exceeded.*quota/i,
|
||||||
|
/usage.?quota/i,
|
||||||
/exhausted\s+your\s+capacity/i,
|
/exhausted\s+your\s+capacity/i,
|
||||||
/all\s+credentials\s+for\s+model/i,
|
/all\s+credentials\s+for\s+model/i,
|
||||||
/cool(?:ing)?\s+down/i,
|
/cool(?:ing)?\s+down/i,
|
||||||
|
|||||||
@@ -56,4 +56,19 @@ describe("runtime-fallback quota error regressions", () => {
|
|||||||
// quota errors trigger fallback to next configured model
|
// quota errors trigger fallback to next configured model
|
||||||
expect(retryable).toBe(true)
|
expect(retryable).toBe(true)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
test("classifies Volcano Engine 'exceeded the usage quota' as retryable", () => {
|
||||||
|
//#given
|
||||||
|
const error = {
|
||||||
|
name: "SessionRetry",
|
||||||
|
message: "You have exceeded the 5-hour usage quota. It will reset at 2026-05-11 01:20:12 +0800 CST. We recommend using a different model.",
|
||||||
|
}
|
||||||
|
|
||||||
|
//#when
|
||||||
|
const retryable = isRetryableError(error, [429, 500, 502, 503, 504])
|
||||||
|
|
||||||
|
//#then
|
||||||
|
// Volcano Engine quota errors trigger fallback to the next model
|
||||||
|
expect(retryable).toBe(true)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user