pub type Result = core::result::Result; pub type Error = Box; // For early dev. use rpc_router::{Handler, ResourcesBuilder, Router, RpcHandlerError, RpcParams, RpcResource}; // use serde::de::DeserializeOwned; use serde::{Deserialize, Serialize}; use serde_json::json; use tokio::task::JoinSet; // region: --- Custom Error pub type MyResult = core::result::Result; #[derive(Debug, RpcHandlerError, Serialize)] pub enum MyError { // TBC } impl core::fmt::Display for MyError { fn fmt(&self, fmt: &mut core::fmt::Formatter) -> core::result::Result<(), core::fmt::Error> { write!(fmt, "{self:?}") } } impl std::error::Error for MyError {} // endregion: --- Custom Error #[derive(Clone, RpcResource)] pub struct ModelManager {} #[derive(Deserialize, RpcParams)] pub struct ParamsIded { pub id: i64, } // impl IntoParams for ParamsForUpdate where D: DeserializeOwned + Send {} pub async fn get_task(_mm: ModelManager, params: ParamsIded) -> MyResult { Ok(params.id + 9000) } #[tokio::main] async fn main() -> Result<()> { // -- router & resources let rpc_router = Router::builder().append_dyn("get_task", get_task.into_dyn()).build(); // -- spawn calls let mut joinset = JoinSet::new(); for _ in 0..2 { let rpc_router = rpc_router.clone(); // In this example, we show the router might not have resources, and here we rebuild each time. let rpc_resources = ResourcesBuilder::default().append(ModelManager {}).build(); joinset.spawn(async move { let params = json!({"id": 123}); rpc_router .call_route_with_resources(None, "get_task", Some(params), rpc_resources) .await }); } // -- Print results while let Some(result) = joinset.join_next().await { println!("res: {result:?}"); } Ok(()) }