fix(failover): patch P1-P3 reliability gaps surfaced by team review

- Forwarder buffers non-streaming bodies and primes streaming first
  chunk before signaling success, so body timeouts and SSE first-chunk
  failures route through the circuit breaker instead of being recorded
  as success on response-header arrival
- Atomic enable-failover: switch to P1 before persisting the flag, and
  roll back auto-added queue entries when the switch is rejected
  (e.g. official providers)
- Hot-reload circuit breaker config on per-app proxy config change
  instead of waiting for a proxy restart
- FailoverToggle / FailoverQueueManager / AutoFailoverConfigPanel
  require proxy takeover for the active app; the backend command also
  rejects enabling when takeover is off
- ProviderHealthBadge consumes the backend is_healthy flag instead of
  hardcoding the 5-failure threshold

Cleanup:
- impl From<&AppProxyConfig> for CircuitBreakerConfig and use it from
  the command layer
- Collapse three identical TabsContent blocks into a single map
This commit is contained in:
Jason
2026-05-14 21:35:02 +08:00
parent 940161fb0e
commit b642ef0633
14 changed files with 389 additions and 98 deletions
+13
View File
@@ -3,6 +3,7 @@
//! 实现熔断器模式,用于防止向不健康的供应商发送请求
use super::log_codes::cb as log_cb;
use super::types::AppProxyConfig;
use serde::{Deserialize, Serialize};
use std::sync::atomic::{AtomicU32, Ordering};
use std::sync::Arc;
@@ -47,6 +48,18 @@ pub struct CircuitBreakerConfig {
pub min_requests: u32,
}
impl From<&AppProxyConfig> for CircuitBreakerConfig {
fn from(config: &AppProxyConfig) -> Self {
Self {
failure_threshold: config.circuit_failure_threshold,
success_threshold: config.circuit_success_threshold,
timeout_seconds: config.circuit_timeout_seconds as u64,
error_rate_threshold: config.circuit_error_rate_threshold,
min_requests: config.circuit_min_requests,
}
}
}
impl Default for CircuitBreakerConfig {
fn default() -> Self {
Self {