Skip to content
This repository has been archived by the owner on Apr 16, 2020. It is now read-only.

returning a Client<T> while abstracting T #192

Open
ian-p-cooke opened this issue Jul 17, 2019 · 3 comments
Open

returning a Client<T> while abstracting T #192

ian-p-cooke opened this issue Jul 17, 2019 · 3 comments

Comments

@ian-p-cooke
Copy link

if this is an inappropriate place to ask this question please close the issue and redirect me if possible; I thought that it might help to ask those most familiar with the types involved.

So in my project I have a service with two methods and I want to call them from two different places. Setting up the transport is common to both so I wanted to refactor that part. That led to a five hour battle with the type system which I was able to solve but not to my satisfaction.

see: https://github.com/ian-p-cooke/tower-grpc/blob/4e6a02c08f4613c4e317590752fe63fbdd48f3d8/tower-grpc-examples/src/helloworld/client.rs#L20

What I really want my signature to say is that the Future's Item is hello_world::client::Greeter for some T that the caller doesn't have to worry about. all the caller should have to worry about is that it can call say_hello. If I have to box it and use some higher-level trait definition and/or introduce a generic type that would be fine but I haven't been able to figure that out yet.

This is important to me because if I changed make_client to do TLS instead I want the signature to stay the same but as-is I would have to redefine Client. I would guess that most people have a service with more than one method on it and the desire for something like my make_client function would be common.

@LucioFranco
Copy link
Member

You should be able to do

fn make_client<T: GrpcService>(...) -> impl Future<Item = Greeter<T>, Error = ...>

I believe that should work since greeter is generic over some GrpcService.

@ian-p-cooke
Copy link
Author

Ah, but GrpcService is generic too. I tried:

use tower_grpc::generic::client::GrpcService;
fn make_client<R, T: GrpcService<R>>(uri: http::Uri) -> Result<Box<dyn Future<Item=hello_world::client::Greeter<T>, Error=tower_grpc::Status> + Send>, Box<dyn Error>> {

but that results in

error[E0271]: type mismatch resolving `<futures::future::and_then::AndThen<futures::future::map_err::MapErr<tower_hyper::client::connect::ConnectFuture<hyper::client::connect::Destination, _, tower_hyper::util::Connector<hyper::client::connect::http::HttpConnector>, tokio_executor::global::DefaultExecutor>, [closure@tower-grpc-examples\src/helloworld/client.rs:29:18: 29:54]>, impl futures::future::Future, [closure@tower-grpc-examples\src/helloworld/client.rs:30:19: 40:10 uri:_]> as futures::future::Future>::Item == hello_world::client::Greeter<T>`
  --> tower-grpc-examples\src/helloworld/client.rs:41:8
   |
41 |     Ok(Box::new(say_hello))
   |        ^^^^^^^^^^^^^^^^^^^ expected struct `tower_request_modifier::RequestModifier`, found type parameter
   |
   = note: expected type `hello_world::client::Greeter<tower_request_modifier::RequestModifier<tower_hyper::client::connection::Connection<_>, _>>`
              found type `hello_world::client::Greeter<T>`
   = note: required for the cast to the object type `dyn futures::future::Future<Error = tower_grpc::status::Status, Item = hello_world::client::Greeter<T>> + std::marker::Send```

@uschen
Copy link

uschen commented Aug 7, 2019

it will be really nice we can have go grpc like client or something like this:

https://github.com/mesalock-linux/brpc-rs/blob/master/examples/echo/client.rs

fn main() {
    let mut options = ChannelOptions::new();
    options.set_timeout_ms(100);
    let addr = "127.0.0.1:50000".parse().expect("Invalid socket address");
    let ch = Channel::with_options(&addr, &options);
    let client = echo::EchoServiceStub::with_channel(&ch);
    let request = echo::EchoRequest {
        message: "hello".to_owned(),
    };
    match client.echo(&request) {
        Ok(r) => println!("Response: {:?}", r),
        Err(e) => eprintln!("Error: {:?}", e),
    }

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants