occams_rpc/lib.rs
1#![cfg_attr(docsrs, feature(doc_cfg))]
2#![cfg_attr(docsrs, allow(unused_attributes))]
3
4//! # razor-rpc
5//!
6//! This crate provides a high-level remote API call interface for `razor-rpc`.
7//! It is part of a modular, pluggable RPC for high throughput scenarios that supports various async runtimes.
8//!
9//! If you are looking for streaming interface, use [razor-stream](https://docs.rs/razor-stream) instead.
10//!
11//! ## Feature
12//!
13//! - Independent from async runtime (with plugins)
14//! - With service trait very similar to grpc / tarpc (stream in API interface is not supported
15//! currently)
16//! - Support latest `impl Future` definition of rust since 1.75, also support legacy `async_trait`
17//! wrapper
18//! - Each method can have different custom error type (requires the type implements
19//! [RpcErrCodec](crate::error::RpcErrCodec))
20//! - based on [razor-stream](https://docs.rs/razor-stream): Full duplex in each connection, with sliding window threshold, allow maximizing throughput and lower cpu usage.
21//!
22//! (Warning: The API and feature is still evolving, might changed in the future)
23//!
24//! ## Components
25//!
26//! `razor-rpc` is built from a collection of crates that provide different functionalities:
27//!
28//! - Async runtime support by [`orb`](https://docs.rs/orb):
29//! - [`orb-tokio`](https://docs.rs/orb-tokio): A runtime adapter for the `tokio` runtime.
30//! - [`orb-smol`](https://docs.rs/orb-smol): A runtime adapter for the `smol` runtime.
31//! - codec [`razor-rpc-codec`](https://docs.rs/razor-rpc-codec): Provides codecs for serialization, such as `msgpack`.
32//! - transports:
33//! - [`razor-rpc-tcp`](https://docs.rs/razor-rpc-tcp): A TCP transport implementation.
34//!
35//! ## Usage
36//!
37//! 1. Choose your async runtime, and the codec.
38//! 2. Choose underlying transport, like [`razor-rpc-tcp`](https://docs.rs/razor-rpc-tcp)
39//! 3. define your service trait, the client is also generated along with the trait
40//! 4. impl your service trait at server-side
41//! 5. Initialize ServerFacts (with configuration and runtime)
42//! 6. choose request dispatch method: [crate::server::dispatch]
43//! 7. Start listening for connection
44//! 8. Initialize ClientFacts (with configuration, runtime, and codec)
45//! 9. Setup a connection pool: [ClientPool](crate::client::ClientPool) or
46//! [FailoverPool](crate::client::FailoverPool)
47//!
48//! ## Example
49//!
50//! ```rust
51//! use razor_rpc::client::{endpoint_async, APIClientReq, ClientConfig};
52//! use razor_rpc::server::{service, ServerConfig};
53//! use razor_rpc::error::RpcError;
54//! use razor_rpc_tcp::{TcpClient, TcpServer};
55//! use nix::errno::Errno;
56//! use std::future::Future;
57//! use std::sync::Arc;
58//!
59//! // 1. Choose the async runtime, and the codec
60//! type OurRt = orb_tokio::TokioRT;
61//! type OurCodec = razor_rpc_codec::MsgpCodec;
62//! // 2. Choose transport
63//! type ServerProto = TcpServer<OurRt>;
64//! type ClientProto = TcpClient<OurRt>;
65//!
66//! // 3. Define a service trait, and generate the client struct
67//! #[endpoint_async(CalculatorClient)]
68//! pub trait CalculatorService {
69//! // Method with unit error type using impl Future
70//! fn add(&self, args: (i32, i32)) -> impl Future<Output = Result<i32, RpcError<()>>> + Send;
71//!
72//! // Method with string error type using impl Future
73//! fn div(&self, args: (i32, i32)) -> impl Future<Output = Result<i32, RpcError<String>>> + Send;
74//!
75//! // Method with errno error type using impl Future
76//! fn might_fail_with_errno(&self, value: i32) -> impl Future<Output = Result<i32, RpcError<Errno>>> + Send;
77//! }
78//!
79//! // 4. Server implementation, can use Arc with internal context, but we are a simple demo
80//! #[derive(Clone)]
81//! pub struct CalculatorServer;
82//!
83//! #[service]
84//! impl CalculatorService for CalculatorServer {
85//! async fn add(&self, args: (i32, i32)) -> Result<i32, RpcError<()>> {
86//! let (a, b) = args;
87//! Ok(a + b)
88//! }
89//!
90//! async fn div(&self, args: (i32, i32)) -> Result<i32, RpcError<String>> {
91//! let (a, b) = args;
92//! if b == 0 {
93//! Err(RpcError::User("division by zero".to_string()))
94//! } else {
95//! Ok(a / b)
96//! }
97//! }
98//!
99//! async fn might_fail_with_errno(&self, value: i32) -> Result<i32, RpcError<Errno>> {
100//! if value < 0 {
101//! Err(RpcError::User(Errno::EINVAL))
102//! } else {
103//! Ok(value * 2)
104//! }
105//! }
106//! }
107//!
108//! async fn setup_server() -> std::io::Result<String> {
109//! // 5. Server setup with default ServerFacts
110//! use razor_rpc::server::{RpcServer, ServerDefault};
111//! let server_config = ServerConfig::default();
112//! let mut server = RpcServer::new(ServerDefault::new(server_config, OurRt::new_multi_thread(8)));
113//! // 6. dispatch
114//! use razor_rpc::server::dispatch::Inline;
115//! let disp = Inline::<OurCodec, _>::new(CalculatorServer);
116//! // 7. Start listening
117//! let actual_addr = server.listen::<ServerProto, _>("127.0.0.1:8082", disp).await?;
118//! Ok(actual_addr)
119//! }
120//!
121//! async fn use_client(server_addr: &str) {
122//! use razor_rpc::client::*;
123//! // 8. ClientFacts
124//! let mut client_config = ClientConfig::default();
125//! client_config.task_timeout = 5;
126//! let rt = OurRt::new_multi_thread(8);
127//! type OurFacts = APIClientDefault<OurRt, OurCodec>;
128//! let client_facts = OurFacts::new(client_config, rt);
129//! // 9. Create client connection pool
130//! let pool: ClientPool<OurFacts, ClientProto> =
131//! client_facts.create_pool_async::<ClientProto>(server_addr);
132//! let client = CalculatorClient::new(pool);
133//! // Call methods with different error types
134//! if let Ok(r) = client.add((10, 20)).await {
135//! assert_eq!(r, 30);
136//! }
137//! // This will return a string error, but connect might fail, who knows
138//! if let Err(e) = client.div((10, 0)).await {
139//! println!("error occurred: {}", e);
140//! }
141//! }
142//! ```
143
144pub mod client;
145pub mod server;
146
147// re-export for macros, so that user don't need to use multiple crates
148pub use razor_stream::{Codec, error};