Skip to main content

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}