nodedb_cluster/reachability/prober.rs
1// SPDX-License-Identifier: BUSL-1.1
2
3//! [`ReachabilityProber`] — the injection seam for reachability probes.
4//!
5//! Implementations:
6//!
7//! - [`TransportProber`] wraps an `Arc<NexarTransport>` and sends a
8//! `RaftRpc::Ping` to the peer. `send_rpc` already handles the
9//! circuit-breaker check, the QUIC dial, retries, and
10//! `record_success` / `record_failure` — the prober is a one-line
11//! adapter.
12//! - [`NoopProber`] always succeeds. Useful for tests that only want
13//! to verify the loop's tick cadence and shutdown.
14//!
15//! Tests that want deterministic open→closed transitions construct
16//! their own trait impls; see `tests/reachability_loop.rs`.
17
18use std::sync::Arc;
19
20use async_trait::async_trait;
21
22use crate::error::Result;
23use crate::rpc_codec::{PingRequest, RaftRpc};
24use crate::transport::NexarTransport;
25
26/// Abstract probe operation over a single peer.
27#[async_trait]
28pub trait ReachabilityProber: Send + Sync {
29 /// Send one probe to `peer`. Returns `Ok(())` iff the probe
30 /// completed successfully (implying the peer is reachable).
31 async fn probe(&self, peer: u64) -> Result<()>;
32}
33
34/// Production prober: sends a `Ping` via the live transport. The
35/// transport's internal circuit breaker records success/failure
36/// automatically — the driver does not need to bookkeep anything.
37pub struct TransportProber {
38 transport: Arc<NexarTransport>,
39 self_node_id: u64,
40}
41
42impl TransportProber {
43 pub fn new(transport: Arc<NexarTransport>, self_node_id: u64) -> Self {
44 Self {
45 transport,
46 self_node_id,
47 }
48 }
49}
50
51#[async_trait]
52impl ReachabilityProber for TransportProber {
53 async fn probe(&self, peer: u64) -> Result<()> {
54 let rpc = RaftRpc::Ping(PingRequest {
55 sender_id: self.self_node_id,
56 topology_version: 0,
57 });
58 self.transport.send_rpc(peer, rpc).await.map(|_| ())
59 }
60}
61
62/// Always-succeeds prober for cadence/shutdown tests.
63pub struct NoopProber;
64
65#[async_trait]
66impl ReachabilityProber for NoopProber {
67 async fn probe(&self, _peer: u64) -> Result<()> {
68 Ok(())
69 }
70}