diff --git a/README.md b/README.md index d38d75e..7f84be0 100644 --- a/README.md +++ b/README.md @@ -45,12 +45,23 @@ races! ## Example -Here's a small service. +For this example, in addition to tarpc, also add two other dependencies to +your `Cargo.toml`: + +```toml +futures-preview = { version = "0.3.0-alpha.16", features = ["compat"] } +tokio = "0.1" +``` + +In the following example, we use an in-process channel for communication between +client and server. In real code, you will likely communicate over the network. +For a more real-world example, see [example-service](example-service). + +First, let's set up the dependencies and service definition. ```rust #![feature(arbitrary_self_types, async_await, proc_macro_hygiene)] - use futures::{ compat::Executor01CompatExt, future::{self, Ready}, @@ -68,7 +79,12 @@ tarpc::service! { /// Returns a greeting for name. rpc hello(name: String) -> String; } +``` +This service definition generates a trait called `Service`. Next we need to +implement it for our Server struct. + +```rust // This is the type that implements the generated Service trait. It is the business logic // and is used to start the server. #[derive(Clone)] @@ -84,31 +100,33 @@ impl Service for HelloServer { future::ready(format!("Hello, {}!", name)) } } +``` +Next let's write a function to start our server. While this example uses an +[in-process +channel](https://docs.rs/tarpc/0.18.0/tarpc/transport/channel/struct.UnboundedChannel.html), +tarpc also ships a +[transport](https://docs.rs/tarpc-bincode-transport/0.7.0/tarpc_bincode_transport/) +that uses bincode over TCP. + +```rust async fn run() -> io::Result<()> { - // bincode_transport is provided by the associated crate bincode-transport. It makes it easy - // to start up a serde-powered bincode serialization strategy over TCP. - let transport = bincode_transport::listen(&"0.0.0.0:0".parse().unwrap())?; - let addr = transport.local_addr(); + let (client_transport, server_transport) = tarpc::transport::channel::unbounded(); - // The server is configured with the defaults. let server = server::new(server::Config::default()) - // Server can listen on any type that implements the Transport trait. - .incoming(transport) - // Close the stream after the client connects - .take(1) + // incoming() takes a stream of transports such as would be returned by + // TcpListener::incoming (but a stream instead of an iterator). + .incoming(stream::once(future::ready(Ok(server_transport)))) // serve is generated by the service! macro. It takes as input any type implementing // the generated Service trait. .respond_with(serve(HelloServer)); - tokio_executor::spawn(server.unit_error().boxed().compat()); - - let transport = bincode_transport::connect(&addr).await?; + tokio::spawn(server.unit_error().boxed().compat()); // new_stub is generated by the service! macro. Like Server, it takes a config and any // Transport as input, and returns a Client, also generated by the macro. // by the service mcro. - let mut client = new_stub(client::Config::default(), transport).await?; + let mut client = new_stub(client::Config::default(), client_transport).await?; // The client has an RPC method for each RPC defined in service!. It takes the same args // as defined, with the addition of a Context, which is always the first arg. The Context @@ -119,7 +137,13 @@ async fn run() -> io::Result<()> { Ok(()) } +``` +Lastly, we'll call `run()` from `main`. Before running a tarpc server or client, +call `tarpc::init()` to initialize the executor tarpc uses internally to run +background tasks for the client and server. + +```rust fn main() { tarpc::init(tokio::executor::DefaultExecutor::current().compat()); tokio::run(run() @@ -128,6 +152,7 @@ fn main() { .compat(), ); } + ``` ## Service Documentation diff --git a/example-service/Cargo.toml b/example-service/Cargo.toml index fff599a..f25cd89 100644 --- a/example-service/Cargo.toml +++ b/example-service/Cargo.toml @@ -19,7 +19,6 @@ futures-preview = { version = "0.3.0-alpha.16", features = ["compat"] } serde = { version = "1.0" } tarpc = { version = "0.18", path = "../tarpc", features = ["serde1"] } tokio = "0.1" -tokio-executor = "0.1" [lib] name = "service"