diff --git a/src/coding/proxy/config/config.default.yaml b/src/coding/proxy/config/config.default.yaml index 9e43ba7..05cbf4a 100644 --- a/src/coding/proxy/config/config.default.yaml +++ b/src/coding/proxy/config/config.default.yaml @@ -118,7 +118,7 @@ vendors: # === 故障转移触发条件 === failover: - status_codes: [429, 403, 503, 500] + status_codes: [429, 403, 503, 500, 529] error_types: - "rate_limit_error" - "overloaded_error" diff --git a/src/coding/proxy/config/resiliency.py b/src/coding/proxy/config/resiliency.py index 734167c..71ba258 100644 --- a/src/coding/proxy/config/resiliency.py +++ b/src/coding/proxy/config/resiliency.py @@ -24,7 +24,7 @@ class RetryConfig(BaseModel): class FailoverConfig(BaseModel): status_codes: list[int] = Field( - default=[429, 403, 503, 500], + default=[429, 403, 503, 500, 529], ) error_types: list[str] = Field( default=["rate_limit_error", "overloaded_error", "api_error"], diff --git a/src/coding/proxy/vendors/base.py b/src/coding/proxy/vendors/base.py index ef9fa6a..975d3af 100644 --- a/src/coding/proxy/vendors/base.py +++ b/src/coding/proxy/vendors/base.py @@ -268,8 +268,8 @@ def should_trigger_failover( for pattern in self._failover_config.error_message_patterns: if pattern.lower() in error_message: return True - # 429/503 即使无法解析 body 也触发故障转移 - return status_code in (429, 503) + # 429/503/529 即使无法解析 body 也触发故障转移 + return status_code in (429, 503, 529) async def check_health(self) -> bool: """检查供应商健康状态(轻量级探测). diff --git a/tests/test_vendors.py b/tests/test_vendors.py index 97eaefd..3f2fe8c 100644 --- a/tests/test_vendors.py +++ b/tests/test_vendors.py @@ -650,6 +650,31 @@ def test_base_failover_without_config_returns_false(): assert not zhipu_vendor.should_trigger_failover(503, None) +# --- 529 overloaded_error 降级测试 --- + + +def test_529_overloaded_triggers_failover(): + """529 + overloaded_error 应触发降级(FailoverConfig 默认包含 529).""" + anthropic_vendor = AnthropicVendor(AnthropicConfig(), FailoverConfig()) + + assert anthropic_vendor.should_trigger_failover( + 529, {"error": {"type": "overloaded_error", "message": "Overloaded"}} + ) + + +def test_529_without_body_triggers_failover(): + """529 无 body 也应触发降级(备用安全网逻辑).""" + anthropic_vendor = AnthropicVendor(AnthropicConfig(), FailoverConfig()) + + assert anthropic_vendor.should_trigger_failover(529, None) + + +def test_529_in_failover_config_default(): + """验证 FailoverConfig 默认 status_codes 包含 529.""" + config = FailoverConfig() + assert 529 in config.status_codes + + # --- _sanitize_headers_for_synthetic_response ---