diff --git a/tonic-examples/Cargo.toml b/tonic-examples/Cargo.toml index b50b560a9..285231179 100644 --- a/tonic-examples/Cargo.toml +++ b/tonic-examples/Cargo.toml @@ -14,6 +14,10 @@ path = "src/helloworld/server.rs" name = "helloworld-client" path = "src/helloworld/client.rs" +[[bin]] +name = "helloworld-client-blocking" +path = "src/helloworld/client-blocking.rs" + [[bin]] name = "routeguide-server" path = "src/routeguide/server.rs" diff --git a/tonic-examples/src/helloworld/client-blocking.rs b/tonic-examples/src/helloworld/client-blocking.rs new file mode 100644 index 000000000..549359445 --- /dev/null +++ b/tonic-examples/src/helloworld/client-blocking.rs @@ -0,0 +1,56 @@ +use tokio::runtime::{Builder, Runtime}; + +pub mod hello_world { + tonic::include_proto!("helloworld"); +} + +use hello_world::{greeter_client::GreeterClient, HelloReply, HelloRequest}; + +type StdError = Box; +type Result = ::std::result::Result; + +// The order of the fields in this struct is important. The runtime must be the first field and the +// client must be the last field so that when `BlockingClient` is dropped the client is dropped +// before the runtime. Not doing this will result in a deadlock when dropped. +struct BlockingClient { + rt: Runtime, + client: GreeterClient, +} + +impl BlockingClient { + pub fn connect(dst: D) -> Result + where + D: std::convert::TryInto, + D::Error: Into, + { + let mut rt = Builder::new() + .basic_scheduler() + .enable_all() + .build() + .unwrap(); + let client = rt.block_on(GreeterClient::connect(dst))?; + + Ok(Self { rt, client }) + } + + pub fn say_hello( + &mut self, + request: impl tonic::IntoRequest, + ) -> Result, tonic::Status> { + self.rt.block_on(self.client.say_hello(request)) + } +} + +fn main() -> Result<()> { + let mut client = BlockingClient::connect("http://[::1]:50051")?; + + let request = tonic::Request::new(HelloRequest { + name: "Tonic".into(), + }); + + let response = client.say_hello(request)?; + + println!("RESPONSE={:?}", response); + + Ok(()) +}