Clarify dependencies required for README example

Fixes https://github.com/google/tarpc/issues/232
This commit is contained in:
Tim Kuehn
2019-05-15 15:20:37 -07:00
parent ce9c057b1b
commit 373dcbed57
2 changed files with 40 additions and 16 deletions

View File

@@ -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

View File

@@ -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"