Record a failed RPC to a peer. May open the circuit.
(&self, peer: u64)
| 115 | |
| 116 | /// Record a failed RPC to a peer. May open the circuit. |
| 117 | pub fn record_failure(&self, peer: u64) { |
| 118 | let mut peers = self.peers.write().unwrap_or_else(|p| p.into_inner()); |
| 119 | let breaker = peers.entry(peer).or_insert_with(PeerBreaker::new); |
| 120 | breaker.consecutive_failures += 1; |
| 121 | |
| 122 | match breaker.state { |
| 123 | CircuitState::Closed => { |
| 124 | if breaker.consecutive_failures >= self.config.failure_threshold { |
| 125 | breaker.state = CircuitState::Open; |
| 126 | breaker.last_state_change = Instant::now(); |
| 127 | } |
| 128 | } |
| 129 | CircuitState::HalfOpen => { |
| 130 | // Probe failed → back to Open. |
| 131 | breaker.state = CircuitState::Open; |
| 132 | breaker.last_state_change = Instant::now(); |
| 133 | } |
| 134 | CircuitState::Open => { |
| 135 | // Already open — refresh the timestamp to extend cooldown. |
| 136 | breaker.last_state_change = Instant::now(); |
| 137 | } |
| 138 | } |
| 139 | } |
| 140 | |
| 141 | /// Get the current circuit state for a peer (for observability). |
| 142 | pub fn state(&self, peer: u64) -> CircuitState { |