Record a request failure for circuit breaker
(&self)
| 367 | |
| 368 | /// Record a request failure for circuit breaker |
| 369 | pub fn record_failure(&self) { |
| 370 | if !self.circuit_config.enabled { |
| 371 | return; |
| 372 | } |
| 373 | |
| 374 | let current_nanos = SystemTime::now() |
| 375 | .duration_since(UNIX_EPOCH) |
| 376 | .unwrap_or_default() |
| 377 | .as_nanos() as u64; |
| 378 | |
| 379 | self.circuit_state.last_failure_time_nanos.store(current_nanos, Ordering::Release); |
| 380 | |
| 381 | loop { |
| 382 | let packed = self.circuit_state.packed_state.load(Ordering::Acquire); |
| 383 | let (state, failure_count, success_count) = CircuitBreakerState::unpack_state(packed); |
| 384 | |
| 385 | let new_failure_count = failure_count.saturating_add(1); |
| 386 | |
| 387 | // Check if we should open the circuit |
| 388 | let (new_state, new_success_count) = if new_failure_count >= self.circuit_config.failure_threshold && state == CircuitState::Closed { |
| 389 | // Set next attempt time |
| 390 | let next_attempt_nanos = current_nanos + self.circuit_config.timeout_duration.as_nanos() as u64; |
| 391 | self.circuit_state.next_attempt_time_nanos.store(next_attempt_nanos, Ordering::Release); |
| 392 | |
| 393 | warn!( |
| 394 | "Circuit breaker opened due to {} failures (threshold: {})", |
| 395 | new_failure_count, |
| 396 | self.circuit_config.failure_threshold |
| 397 | ); |
| 398 | |
| 399 | // Log security event for circuit breaker opening |
| 400 | events::circuit_breaker_opened(new_failure_count, self.circuit_config.failure_threshold); |
| 401 | |
| 402 | (CircuitState::Open, 0) |
| 403 | } else { |
| 404 | (state, success_count) |
| 405 | }; |
| 406 | |
| 407 | let new_packed = CircuitBreakerState::pack_state(new_state, new_failure_count, new_success_count); |
| 408 | |
| 409 | // Atomic compare-exchange to update state |
| 410 | if self.circuit_state.packed_state.compare_exchange_weak( |
| 411 | packed, |
| 412 | new_packed, |
| 413 | Ordering::Release, |
| 414 | Ordering::Relaxed |
| 415 | ).is_ok() { |
| 416 | break; |
| 417 | } |
| 418 | // If CAS failed, retry |
| 419 | } |
| 420 | } |
| 421 | |
| 422 | /// Record a successful request for circuit breaker |
| 423 | fn record_success(&self) { |