# irpc: Quick Reference ## Crate Info - **Name:** `irpc` - **Version:** 0.13.0 - **License:** Apache-2.0 OR MIT - **Repository:** https://github.com/n0-computer/irpc - **MSRV:** 1.89 ## Feature Flags | Feature | Default | Dependencies Added | |---|---|---| | `rpc` | ✅ | noq, postcard, smallvec, tracing, tokio/io-util | | `derive` | ✅ | irpc-derive | | `spans` | ✅ | tracing | | `stream` | ✅ | futures-util | | `noq_endpoint_setup` | ✅ | rustls, rcgen, futures-buffered | | `varint-util` | ❌ | postcard, smallvec, tokio/io-util | ## Type Quick Reference ### Core Types ``` Service trait — implemented on protocol enum, defines Message type Channels trait — implemented on request types, defines Tx/Rx types RpcMessage trait — blanket impl for Debug+Serialize+DeserializeOwned+Send+Sync+Unpin+'static Sender trait — sealed marker for sender types Receiver trait — sealed marker for receiver types WithChannels struct — wraps request I with tx/rx/span for service S Client struct — client to service S (local or remote) LocalSender struct — local sender wrapping mpsc::Sender Request enum — Local(L) or Remote(R) request RemoteSender struct — holds QUIC stream pair for sending initial message ``` ### Channel Types ``` oneshot::Sender — Tokio or Boxed; single value; async send oneshot::Receiver — Tokio or Boxed; single value; Future impl mpsc::Sender — Tokio or Arc; stream; async send/try_send mpsc::Receiver — Tokio or Box; stream; async recv NoSender — No-op sender NoReceiver — No-op receiver ``` ### Remote Types (rpc feature) ``` RemoteConnection trait — open_bi(), zero_rtt_accepted(), clone_boxed() NoqLazyRemoteConnection — lazy noq connection with cache Handler type — Arc ...> ``` ### irpc-iroh Types ``` IrohRemoteConnection — wraps iroh::Connection IrohZrttRemoteConnection — wraps iroh::OutgoingZeroRttConnection IrohLazyRemoteConnection — lazy iroh connection with cache IrohProtocol — ProtocolHandler for iroh Router Iroh0RttProtocol — ProtocolHandler with 0-RTT support IncomingRemoteConnection trait — abstraction over Connection and ZeroRttConnection ``` ## Interaction Patterns Cheatsheet ```rust // ═══════════════════════════════════════════ // Protocol Definition // ═══════════════════════════════════════════ #[rpc_requests(message = MyMessage)] #[derive(Debug, Serialize, Deserialize)] enum MyProtocol { // Unary RPC #[rpc(tx=oneshot::Sender)] #[wrap(GetReq)] Get(String), // Server streaming #[rpc(tx=mpsc::Sender)] #[wrap(ListReq)] List(ListParams), // Client streaming #[rpc(tx=oneshot::Sender, rx=mpsc::Receiver)] #[wrap(UploadReq)] Upload, // Bidirectional streaming #[rpc(tx=mpsc::Sender, rx=mpsc::Receiver)] #[wrap(ProcessReq)] Process(ProcessConfig), // Fire and forget #[rpc] #[wrap(LogReq)] Log(String), } // ═══════════════════════════════════════════ // Client Usage // ═══════════════════════════════════════════ // Local let (tx, rx) = tokio::sync::mpsc::channel(16); tokio::task::spawn(actor(rx)); let client: Client = Client::local(tx); // Remote (noq) let client: Client = Client::noq(endpoint, addr); // Remote (iroh) let client: Client = irpc_iroh::client(endpoint, addr, alpn); // ═══════════════════════════════════════════ // Making Requests // ═══════════════════════════════════════════ // Unary let result: Response = client.rpc(GetReq("key".into())).await?; // Server streaming let mut rx: mpsc::Receiver = client.server_streaming(ListReq(params), 16).await?; while let Some(item) = rx.recv().await? { ... } // Client streaming let (update_tx, response_rx): (mpsc::Sender, oneshot::Receiver) = client.client_streaming(Upload, 4).await?; update_tx.send(item).await?; let count = response_rx.await?; // Bidirectional let (update_tx, mut result_rx): (mpsc::Sender, mpsc::Receiver) = client.bidi_streaming(ProcessReq(config), 4, 16).await?; update_tx.send(update).await?; while let Some(result) = result_rx.recv().await? { ... } // Fire and forget client.notify(LogReq("message".into())).await?; // ═══════════════════════════════════════════ // Server Setup // ═══════════════════════════════════════════ // noq let handler = MyProtocol::remote_handler(local_sender); irpc::rpc::listen(endpoint, handler).await; // iroh let protocol = IrohProtocol::with_sender(local_sender); Router::builder(endpoint).accept(ALPN, protocol).spawn(); // ═══════════════════════════════════════════ // Actor Message Handling // ═══════════════════════════════════════════ async fn handle(&mut self, msg: MyMessage) { match msg { MyMessage::Get(wc) => { let WithChannels { inner, tx, .. } = wc; let result = self.db.get(&inner.0).cloned(); tx.send(result).await.ok(); } MyMessage::List(wc) => { let WithChannels { tx, .. } = wc; for item in &self.items { if tx.send(item.clone()).await.is_err() { break; } } } MyMessage::Upload(wc) => { let WithChannels { tx, mut rx, .. } = wc; let mut count = 0; while let Ok(Some(item)) = rx.recv().await { self.process(item); count += 1; } tx.send(count).await.ok(); } MyMessage::Process(wc) => { let WithChannels { tx, mut rx, inner, .. } = wc; tokio::task::spawn(async move { while let Ok(Some(update)) = rx.recv().await { if let Some(result) = process(update, &inner) { if tx.send(result).await.is_err() { break; } } } }); } MyMessage::Log(wc) => { let WithChannels { inner, .. } = wc; println!("{}", inner.0); } } } ``` ## Error Handling Quick Reference ```rust // Client-side errors use irpc::{Error, RequestError, Result}; // Request errors (connection/stream open failures) match client.rpc(GetReq("key".into())).await { Ok(result) => { ... } Err(Error::Request { source }) => { ... } // Connection failed Err(Error::OneshotRecv { source }) => { ... } // Response channel error } // Channel errors use irpc::channel::{SendError, mpsc::RecvError, oneshot::RecvError}; // SendError: ReceiverClosed | MaxMessageSizeExceeded | Io // RecvError (oneshot): SenderClosed | MaxMessageSizeExceeded | Io // RecvError (mpsc): MaxMessageSizeExceeded | Io ``` ## Constants ```rust pub const MAX_MESSAGE_SIZE: u64 = 16 * 1024 * 1024; // 16 MiB pub const ERROR_CODE_MAX_MESSAGE_SIZE_EXCEEDED: u32 = 1; pub const ERROR_CODE_INVALID_POSTCARD: u32 = 2; // Connection close code 0 = clean shutdown ```