-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Description
Feature Request
Crates
tonic-build, possibly tonic
Motivation
I have a service that runs as a cluster of nodes and exposes 2 APIs: an external API that clients use to talk to the cluster and an internal API that the cluster nodes use to talk to each other. In order to keep the internal API separate from the external, I've made each one a separate gRPC service. Using Tonic, this gives me an ExternalClient type and an InternalClient type.
I'd like to be able to write helper code that's generic over the two different flavors of client. The motivating example here is to allow nodes (and external clients) to keep a lazily-initiated cache of connections to all the nodes in the cluster. The external clients will keep a map of ExternalClients and the cluster nodes will keep a map of InternalClients. The cache needs to be able to create new clients, so it needs to be able to call the connect method.
Right now, it looks like the generated code initializes each flavor of client as a separate struct and defines connect on the struct:
pub mod internal_client {
#![allow(unused_variables, dead_code, missing_docs)]
use tonic::codegen::*;
pub struct InternalClient<T> {
inner: tonic::client::Grpc<T>,
}
impl InternalClient<tonic::transport::Channel> {
/// Attempt to create a new client by connecting to a given endpoint.
pub async fn connect<D>(dst: D) -> Result<Self, tonic::transport::Error>
where
D: std::convert::TryInto<tonic::transport::Endpoint>,
D::Error: Into<StdError>,
{
let conn = tonic::transport::Endpoint::new(dst)?.connect().await?;
Ok(Self::new(conn))
}
}
impl<T> InternalClient<T>
...
I can get the behavior I want by writing my own CanConnect trait and implementing it manually for InternalClient and ExternalClient, then making my cache take a T: CanConnect type arg, but it would be nice to have a generic Client trait implemented automatically by Tonic (that way it can also include any other methods that end up being common among all clients).
Proposal
- Add a new public
Clienttrait (possibly as part oftonic::transport::channel?) that defines aconnectmethod (and any other methods that are common across all derived gRPC clients) - During codegen, generate an implementation of this trait for each derived gRPC client struct (this could either replace the
impl FooClient<tonic::transport::Channel>block or delegate to it)