Skip to main content

rpc_api/
sender.rs

1//! Trait for making outgoing RPC calls.
2
3use crate::{CallBuf, ProgVers, RpcError, RpcResponse};
4use async_trait::async_trait;
5
6/// Trait for making outgoing RPC calls.
7///
8/// `rpc_driver` implements this for real TCP connections
9/// (`ConnectionHandle`, `ClientConnection`) and for its pooled connections
10/// (`FixedSerialPool`, `DynamicPool`, `CpuSetPool`). Inside an
11/// [`RpcHandler`](crate::RpcHandler) dispatch, the per-connection sender is
12/// available via `rpc_driver::peer()`.
13///
14/// Generated protocol clients hold an `Arc<dyn RpcSender>` and are agnostic
15/// to which implementation backs it. Implement on a mock struct for unit
16/// testing without TCP.
17#[async_trait]
18pub trait RpcSender: Send + Sync {
19    /// A buffer to encode the next call into.
20    ///
21    /// Senders that recycle record buffers hand back a spent one, so a
22    /// steady stream of calls allocates nothing. A sender with nothing to
23    /// recycle returns [`CallBuf::new`]. Encode the arguments into the
24    /// buffer and pass it to [`send_call`](Self::send_call).
25    fn call_buf(&self) -> CallBuf;
26
27    /// Send an RPC call and return the response.
28    ///
29    /// The call's arguments arrive encoded in a [`CallBuf`], which the
30    /// driver frames in place and hands to the socket without copying. The
31    /// returned [`RpcResponse`] derefs to `&[u8]` for zero-copy
32    /// deserialization, or can be copied to an owned `Vec<u8>` via
33    /// `.to_vec()`.
34    async fn send_call(
35        &self,
36        progvers: ProgVers,
37        proc: u32,
38        call: CallBuf,
39    ) -> Result<RpcResponse, RpcError>;
40
41    /// Send an RPC call without waiting for the response.
42    ///
43    /// Default implementation calls [`send_call`](Self::send_call) and
44    /// discards the response. Implementations may override this to return
45    /// after queueing the request, in which case success does not confirm
46    /// socket delivery or peer-side dispatch.
47    async fn send_fire_and_forget(
48        &self,
49        progvers: ProgVers,
50        proc: u32,
51        call: CallBuf,
52    ) -> Result<(), RpcError> {
53        self.send_call(progvers, proc, call).await.map(|_| ())
54    }
55}