Shared client

Open the lib.rs source file and add two generated modules:

mod ring;
mod ring_grpc;

Import some types we need to create a wrapper for a gRPC client:

use crate::ring::Empty;
use crate::ring_grpc::{Ring, RingClient};
use grpc::{ClientConf, ClientStubExt, Error as GrpcError, RequestOptions};
use std::net::SocketAddr;

As you can see, the generated modules contain types we declared in the ring.proto file. The ring module contains the Empty struct, and the ring_grpc module contains the Ring trait, which represents an interface of a remote service. Also, protoc_rust_grpc in the build script generated the RingClient type. This type is a client that can be used to call remote methods. We wrap it with our own struct, because RingClient generates Future instances and we will use the Remote wrapper to perform them and get the result.

We also use types from the grpc crate. The Error type is imported as GrpcError
RequestOptions, which is necessary to prepare method call requests; ClientConf, which is used to add extra configuration parameters for the HTTP/2 connection (we will use the default values); and ClientStubExt, which provides connection methods for clients.

Add the Remote struct holding the RingClient instance inside:

pub struct Remote {
client: RingClient,
}

We use this struct for both client and server. Add a new method to construct new instances of Remote from the provided SocketAddr:

impl Remote {
pub fn new(addr: SocketAddr) -> Result<Self, GrpcError> {
let host = addr.ip().to_string();
let port = addr.port();
let conf = ClientConf::default();
let client = RingClient::new_plain(&host, port, conf)?;
Ok(Self {
client
})
}
}

Since generated clients expect separate host and port values, we extract them from the SocketAddr value. Also, we create the default ClientConf configuration and use all these values to create the RingClient instance to put it to the new Remote instance.

We create the Remote struct to have simple methods to call remote methods. Add the start_roll_call method to the Remote implementation to call the StartRollCall gRPC method:

pub fn start_roll_call(&self) -> Result<Empty, GrpcError> {
self.client.start_roll_call(RequestOptions::new(), Empty::new())
.wait()
.map(|(_, value, _)| value)
}

RingClient already has this method, but it expects parameters that we want to hide, and returns a Future instance that we want to perform immediately using the wait method call. The Future returns a tuple with three items, but we need only one value, because other values contain metadata that we don't need.

Implement the mark_itself method in a similar way to call the MarkItself gRPC method:

pub fn mark_itself(&self) -> Result<Empty, GrpcError> {
self.client.mark_itself(RequestOptions::new(), Empty::new())
.wait()
.map(|(_, value, _)| value)
}

Now we can implement a client and a server, because both need the Remote struct to perform RPC calls.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.117.73.127