multi_rpc/builder.rs
1use std::future::Future;
2use std::pin::Pin;
3use std::sync::Arc;
4
5use crate::runner::ServerRunner;
6
7/// A type alias for a future that can be spawned as a server task.
8pub type ServerTask = Pin<Box<dyn Future<Output = ()> + Send>>;
9
10/// A builder for configuring and launching multiple RPC servers from a single service implementation.
11///
12/// This provides a fluent interface to add different protocol servers that all delegate
13/// to the same shared service logic.
14pub struct ServerBuilder<S> {
15 service: Arc<S>,
16 task_factories: Vec<Box<dyn FnOnce(Arc<S>) -> ServerTask + Send>>,
17}
18
19impl<S> ServerBuilder<S>
20where
21 S: Send + Sync + 'static,
22{
23 /// Creates a new `ServerBuilder`.
24 ///
25 /// # Arguments
26 ///
27 /// * `service` - The service implementation that will be shared across all protocols.
28 pub fn new(service: S) -> Self {
29 Self {
30 service: Arc::new(service),
31 task_factories: Vec::new(),
32 }
33 }
34
35 /// Adds a protocol server to the builder.
36 ///
37 /// The `#[multi_rpc_impl]` macro generates protocol-specific factory functions
38 /// (e.g., `greeter_impls::tarpc_tcp(...)`) that can be passed to this method.
39 ///
40 /// # Arguments
41 ///
42 /// * `factory` - A function that takes the shared service instance and returns a future
43 /// representing the running server task.
44 pub fn add_protocol<F>(mut self, factory: F) -> Self
45 where
46 F: FnOnce(Arc<S>) -> ServerTask + Send + 'static,
47 {
48 self.task_factories.push(Box::new(factory));
49 self
50 }
51
52 /// Consumes the builder, spawning all configured protocol servers on the Tokio runtime.
53 ///
54 /// Returns a `ServerRunner` which can be used to keep the application alive
55 /// until a shutdown signal is received.
56 pub fn build(self) -> Result<ServerRunner, std::io::Error> {
57 println!("🚀 Launching servers...");
58 let handles = self
59 .task_factories
60 .into_iter()
61 .map(|task_fn| {
62 let task = task_fn(self.service.clone());
63 tokio::spawn(task)
64 })
65 .collect();
66 Ok(ServerRunner { handles })
67 }
68}