Check if an RPC to this peer is allowed. Returns `Ok(())` if the circuit is closed or half-open (probe allowed). Returns `Err(CircuitOpen)` if the circuit is open and cooldown hasn't expired.
(&self, peer: u64)
| 80 | /// Returns `Ok(())` if the circuit is closed or half-open (probe allowed). |
| 81 | /// Returns `Err(CircuitOpen)` if the circuit is open and cooldown hasn't expired. |
| 82 | pub fn check(&self, peer: u64) -> Result<()> { |
| 83 | let mut peers = self.peers.write().unwrap_or_else(|p| p.into_inner()); |
| 84 | let breaker = peers.entry(peer).or_insert_with(PeerBreaker::new); |
| 85 | |
| 86 | match breaker.state { |
| 87 | CircuitState::Closed => Ok(()), |
| 88 | CircuitState::HalfOpen => Ok(()), // Allow probe. |
| 89 | CircuitState::Open => { |
| 90 | // Check if cooldown has expired → transition to HalfOpen. |
| 91 | if breaker.last_state_change.elapsed() >= self.config.cooldown { |
| 92 | breaker.state = CircuitState::HalfOpen; |
| 93 | breaker.last_state_change = Instant::now(); |
| 94 | Ok(()) |
| 95 | } else { |
| 96 | Err(ClusterError::CircuitOpen { |
| 97 | node_id: peer, |
| 98 | failures: breaker.consecutive_failures, |
| 99 | }) |
| 100 | } |
| 101 | } |
| 102 | } |
| 103 | } |
| 104 | |
| 105 | /// Record a successful RPC to a peer. Resets the circuit to Closed. |
| 106 | pub fn record_success(&self, peer: u64) { |