fix(build): Allow creating multiple services in the same package (#173)
BREAKING CHANGE: Build will now generate each service client and server into their own modules.
This commit is contained in:
@@ -5,4 +5,4 @@ pub mod pb {
|
|||||||
// Ensure that an RPC service, defined before including a file that defines
|
// Ensure that an RPC service, defined before including a file that defines
|
||||||
// another service in a different protocol buffer package, is not incorrectly
|
// another service in a different protocol buffer package, is not incorrectly
|
||||||
// cleared from the context of its package.
|
// cleared from the context of its package.
|
||||||
type _Test = dyn pb::server::TopService;
|
type _Test = dyn pb::topservice_server::TopService;
|
||||||
|
|||||||
@@ -5,12 +5,18 @@ use quote::{format_ident, quote};
|
|||||||
|
|
||||||
pub(crate) fn generate(service: &Service, proto: &str) -> TokenStream {
|
pub(crate) fn generate(service: &Service, proto: &str) -> TokenStream {
|
||||||
let service_ident = quote::format_ident!("{}Client", service.name);
|
let service_ident = quote::format_ident!("{}Client", service.name);
|
||||||
|
let client_mod = quote::format_ident!("{}_client", service.name.to_ascii_lowercase());
|
||||||
let methods = generate_methods(service, proto);
|
let methods = generate_methods(service, proto);
|
||||||
|
|
||||||
let connect = generate_connect(&service_ident);
|
let connect = generate_connect(&service_ident);
|
||||||
let service_doc = generate_doc_comments(&service.comments.leading);
|
let service_doc = generate_doc_comments(&service.comments.leading);
|
||||||
|
|
||||||
quote! {
|
quote! {
|
||||||
|
/// Generated server implementations.
|
||||||
|
pub mod #client_mod {
|
||||||
|
#![allow(unused_variables, dead_code, missing_docs)]
|
||||||
|
use tonic::codegen::*;
|
||||||
|
|
||||||
#service_doc
|
#service_doc
|
||||||
pub struct #service_ident<T> {
|
pub struct #service_ident<T> {
|
||||||
inner: tonic::client::Grpc<T>,
|
inner: tonic::client::Grpc<T>,
|
||||||
@@ -22,8 +28,7 @@ pub(crate) fn generate(service: &Service, proto: &str) -> TokenStream {
|
|||||||
where T: tonic::client::GrpcService<tonic::body::BoxBody>,
|
where T: tonic::client::GrpcService<tonic::body::BoxBody>,
|
||||||
T::ResponseBody: Body + HttpBody + Send + 'static,
|
T::ResponseBody: Body + HttpBody + Send + 'static,
|
||||||
T::Error: Into<StdError>,
|
T::Error: Into<StdError>,
|
||||||
<T::ResponseBody as HttpBody>::Error: Into<StdError> + Send,
|
<T::ResponseBody as HttpBody>::Error: Into<StdError> + Send, {
|
||||||
{
|
|
||||||
pub fn new(inner: T) -> Self {
|
pub fn new(inner: T) -> Self {
|
||||||
let inner = tonic::client::Grpc::new(inner);
|
let inner = tonic::client::Grpc::new(inner);
|
||||||
Self { inner }
|
Self { inner }
|
||||||
@@ -48,6 +53,7 @@ pub(crate) fn generate(service: &Service, proto: &str) -> TokenStream {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(feature = "transport")]
|
#[cfg(feature = "transport")]
|
||||||
fn generate_connect(service_ident: &syn::Ident) -> TokenStream {
|
fn generate_connect(service_ident: &syn::Ident) -> TokenStream {
|
||||||
|
|||||||
@@ -251,13 +251,7 @@ impl prost_build::ServiceGenerator for ServiceGenerator {
|
|||||||
let clients = &self.clients;
|
let clients = &self.clients;
|
||||||
|
|
||||||
let client_service = quote::quote! {
|
let client_service = quote::quote! {
|
||||||
/// Generated client implementations.
|
|
||||||
pub mod client {
|
|
||||||
#![allow(unused_variables, dead_code, missing_docs)]
|
|
||||||
use tonic::codegen::*;
|
|
||||||
|
|
||||||
#clients
|
#clients
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let code = format!("{}", client_service);
|
let code = format!("{}", client_service);
|
||||||
@@ -270,13 +264,7 @@ impl prost_build::ServiceGenerator for ServiceGenerator {
|
|||||||
let servers = &self.servers;
|
let servers = &self.servers;
|
||||||
|
|
||||||
let server_service = quote::quote! {
|
let server_service = quote::quote! {
|
||||||
/// Generated server implementations.
|
|
||||||
pub mod server {
|
|
||||||
#![allow(unused_variables, dead_code, missing_docs)]
|
|
||||||
use tonic::codegen::*;
|
|
||||||
|
|
||||||
#servers
|
#servers
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let code = format!("{}", server_service);
|
let code = format!("{}", server_service);
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ pub(crate) fn generate(service: &Service, proto_path: &str) -> TokenStream {
|
|||||||
|
|
||||||
let server_service = quote::format_ident!("{}Server", service.name);
|
let server_service = quote::format_ident!("{}Server", service.name);
|
||||||
let server_trait = quote::format_ident!("{}", service.name);
|
let server_trait = quote::format_ident!("{}", service.name);
|
||||||
|
let server_mod = quote::format_ident!("{}_server", service.name.to_ascii_lowercase());
|
||||||
let generated_trait = generate_trait(service, proto_path, server_trait.clone());
|
let generated_trait = generate_trait(service, proto_path, server_trait.clone());
|
||||||
let service_doc = generate_doc_comments(&service.comments.leading);
|
let service_doc = generate_doc_comments(&service.comments.leading);
|
||||||
|
|
||||||
@@ -17,6 +18,11 @@ pub(crate) fn generate(service: &Service, proto_path: &str) -> TokenStream {
|
|||||||
let transport = generate_transport(&server_service, &server_trait, &path);
|
let transport = generate_transport(&server_service, &server_trait, &path);
|
||||||
|
|
||||||
quote! {
|
quote! {
|
||||||
|
/// Generated server implementations.
|
||||||
|
pub mod #server_mod {
|
||||||
|
#![allow(unused_variables, dead_code, missing_docs)]
|
||||||
|
use tonic::codegen::*;
|
||||||
|
|
||||||
#generated_trait
|
#generated_trait
|
||||||
|
|
||||||
#service_doc
|
#service_doc
|
||||||
@@ -69,6 +75,7 @@ pub(crate) fn generate(service: &Service, proto_path: &str) -> TokenStream {
|
|||||||
#transport
|
#transport
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn generate_trait(service: &Service, proto_path: &str, server_trait: Ident) -> TokenStream {
|
fn generate_trait(service: &Service, proto_path: &str, server_trait: Ident) -> TokenStream {
|
||||||
let methods = generate_trait_methods(service, proto_path);
|
let methods = generate_trait_methods(service, proto_path);
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ pub mod pb {
|
|||||||
}
|
}
|
||||||
|
|
||||||
use http::header::HeaderValue;
|
use http::header::HeaderValue;
|
||||||
use pb::{client::EchoClient, EchoRequest};
|
use pb::{echo_client::EchoClient, EchoRequest};
|
||||||
use tonic::transport::Channel;
|
use tonic::transport::Channel;
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ type ResponseStream = Pin<Box<dyn Stream<Item = Result<EchoResponse, Status>> +
|
|||||||
pub struct EchoServer;
|
pub struct EchoServer;
|
||||||
|
|
||||||
#[tonic::async_trait]
|
#[tonic::async_trait]
|
||||||
impl pb::server::Echo for EchoServer {
|
impl pb::echo_server::Echo for EchoServer {
|
||||||
async fn unary_echo(&self, request: Request<EchoRequest>) -> EchoResult<EchoResponse> {
|
async fn unary_echo(&self, request: Request<EchoRequest>) -> EchoResult<EchoResponse> {
|
||||||
let message = request.into_inner().message;
|
let message = request.into_inner().message;
|
||||||
Ok(Response::new(EchoResponse { message }))
|
Ok(Response::new(EchoResponse { message }))
|
||||||
@@ -79,7 +79,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.add_service(pb::server::EchoServer::new(server))
|
.add_service(pb::echo_server::EchoServer::new(server))
|
||||||
.serve(addr)
|
.serve(addr)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ pub mod api {
|
|||||||
tonic::include_proto!("google.pubsub.v1");
|
tonic::include_proto!("google.pubsub.v1");
|
||||||
}
|
}
|
||||||
|
|
||||||
use api::{client::PublisherClient, ListTopicsRequest};
|
use api::{publisher_client::PublisherClient, ListTopicsRequest};
|
||||||
use http::header::HeaderValue;
|
use http::header::HeaderValue;
|
||||||
use tonic::{
|
use tonic::{
|
||||||
transport::{Certificate, Channel, ClientTlsConfig},
|
transport::{Certificate, Channel, ClientTlsConfig},
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ pub mod hello_world {
|
|||||||
tonic::include_proto!("helloworld");
|
tonic::include_proto!("helloworld");
|
||||||
}
|
}
|
||||||
|
|
||||||
use hello_world::{client::GreeterClient, HelloRequest};
|
use hello_world::{greeter_client::GreeterClient, HelloRequest};
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ pub mod hello_world {
|
|||||||
}
|
}
|
||||||
|
|
||||||
use hello_world::{
|
use hello_world::{
|
||||||
server::{Greeter, GreeterServer},
|
greeter_server::{Greeter, GreeterServer},
|
||||||
HelloReply, HelloRequest,
|
HelloReply, HelloRequest,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ pub mod pb {
|
|||||||
tonic::include_proto!("grpc.examples.echo");
|
tonic::include_proto!("grpc.examples.echo");
|
||||||
}
|
}
|
||||||
|
|
||||||
use pb::{client::EchoClient, EchoRequest};
|
use pb::{echo_client::EchoClient, EchoRequest};
|
||||||
use tonic::transport::Channel;
|
use tonic::transport::Channel;
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ pub struct EchoServer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[tonic::async_trait]
|
#[tonic::async_trait]
|
||||||
impl pb::server::Echo for EchoServer {
|
impl pb::echo_server::Echo for EchoServer {
|
||||||
async fn unary_echo(&self, request: Request<EchoRequest>) -> EchoResult<EchoResponse> {
|
async fn unary_echo(&self, request: Request<EchoRequest>) -> EchoResult<EchoResponse> {
|
||||||
let message = format!("{} (from {})", request.into_inner().message, self.addr);
|
let message = format!("{} (from {})", request.into_inner().message, self.addr);
|
||||||
|
|
||||||
@@ -64,7 +64,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
|
|
||||||
let server = EchoServer { addr };
|
let server = EchoServer { addr };
|
||||||
let serve = Server::builder()
|
let serve = Server::builder()
|
||||||
.add_service(pb::server::EchoServer::new(server))
|
.add_service(pb::echo_server::EchoServer::new(server))
|
||||||
.serve(addr);
|
.serve(addr);
|
||||||
|
|
||||||
tokio::spawn(async move {
|
tokio::spawn(async move {
|
||||||
|
|||||||
@@ -6,8 +6,8 @@ pub mod echo {
|
|||||||
tonic::include_proto!("grpc.examples.echo");
|
tonic::include_proto!("grpc.examples.echo");
|
||||||
}
|
}
|
||||||
|
|
||||||
use echo::{client::EchoClient, EchoRequest};
|
use echo::{echo_client::EchoClient, EchoRequest};
|
||||||
use hello_world::{client::GreeterClient, HelloRequest};
|
use hello_world::{greeter_client::GreeterClient, HelloRequest};
|
||||||
use tonic::transport::Endpoint;
|
use tonic::transport::Endpoint;
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
|
|||||||
@@ -11,12 +11,12 @@ pub mod echo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
use hello_world::{
|
use hello_world::{
|
||||||
server::{Greeter, GreeterServer},
|
greeter_server::{Greeter, GreeterServer},
|
||||||
HelloReply, HelloRequest,
|
HelloReply, HelloRequest,
|
||||||
};
|
};
|
||||||
|
|
||||||
use echo::{
|
use echo::{
|
||||||
server::{Echo, EchoServer},
|
echo_server::{Echo, EchoServer},
|
||||||
EchoRequest, EchoResponse,
|
EchoRequest, EchoResponse,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ pub mod route_guide {
|
|||||||
tonic::include_proto!("routeguide");
|
tonic::include_proto!("routeguide");
|
||||||
}
|
}
|
||||||
|
|
||||||
use route_guide::client::RouteGuideClient;
|
use route_guide::routeguide_client::RouteGuideClient;
|
||||||
|
|
||||||
async fn print_features(client: &mut RouteGuideClient<Channel>) -> Result<(), Box<dyn Error>> {
|
async fn print_features(client: &mut RouteGuideClient<Channel>) -> Result<(), Box<dyn Error>> {
|
||||||
let rectangle = Rectangle {
|
let rectangle = Rectangle {
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ pub mod routeguide {
|
|||||||
tonic::include_proto!("routeguide");
|
tonic::include_proto!("routeguide");
|
||||||
}
|
}
|
||||||
|
|
||||||
use routeguide::{server, Feature, Point, Rectangle, RouteNote, RouteSummary};
|
use routeguide::{routeguide_server, Feature, Point, Rectangle, RouteNote, RouteSummary};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct RouteGuide {
|
pub struct RouteGuide {
|
||||||
@@ -22,7 +22,7 @@ pub struct RouteGuide {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[tonic::async_trait]
|
#[tonic::async_trait]
|
||||||
impl server::RouteGuide for RouteGuide {
|
impl routeguide_server::RouteGuide for RouteGuide {
|
||||||
async fn get_feature(&self, request: Request<Point>) -> Result<Response<Feature>, Status> {
|
async fn get_feature(&self, request: Request<Point>) -> Result<Response<Feature>, Status> {
|
||||||
println!("GetFeature = {:?}", request);
|
println!("GetFeature = {:?}", request);
|
||||||
|
|
||||||
@@ -154,7 +154,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
features: Arc::new(data::load()),
|
features: Arc::new(data::load()),
|
||||||
};
|
};
|
||||||
|
|
||||||
let svc = server::RouteGuideServer::new(route_guide);
|
let svc = routeguide_server::RouteGuideServer::new(route_guide);
|
||||||
|
|
||||||
Server::builder().add_service(svc).serve(addr).await?;
|
Server::builder().add_service(svc).serve(addr).await?;
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ pub mod pb {
|
|||||||
tonic::include_proto!("/grpc.examples.echo");
|
tonic::include_proto!("/grpc.examples.echo");
|
||||||
}
|
}
|
||||||
|
|
||||||
use pb::{client::EchoClient, EchoRequest};
|
use pb::{echo_client::EchoClient, EchoRequest};
|
||||||
use tonic::transport::{Certificate, Channel, ClientTlsConfig};
|
use tonic::transport::{Certificate, Channel, ClientTlsConfig};
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ type ResponseStream = Pin<Box<dyn Stream<Item = Result<EchoResponse, Status>> +
|
|||||||
pub struct EchoServer;
|
pub struct EchoServer;
|
||||||
|
|
||||||
#[tonic::async_trait]
|
#[tonic::async_trait]
|
||||||
impl pb::server::Echo for EchoServer {
|
impl pb::echo_server::Echo for EchoServer {
|
||||||
async fn unary_echo(&self, request: Request<EchoRequest>) -> EchoResult<EchoResponse> {
|
async fn unary_echo(&self, request: Request<EchoRequest>) -> EchoResult<EchoResponse> {
|
||||||
let message = request.into_inner().message;
|
let message = request.into_inner().message;
|
||||||
Ok(Response::new(EchoResponse { message }))
|
Ok(Response::new(EchoResponse { message }))
|
||||||
@@ -61,7 +61,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
|
|
||||||
Server::builder()
|
Server::builder()
|
||||||
.tls_config(ServerTlsConfig::with_rustls().identity(identity))
|
.tls_config(ServerTlsConfig::with_rustls().identity(identity))
|
||||||
.add_service(pb::server::EchoServer::new(server))
|
.add_service(pb::echo_server::EchoServer::new(server))
|
||||||
.serve(addr)
|
.serve(addr)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ pub mod pb {
|
|||||||
tonic::include_proto!("grpc.examples.echo");
|
tonic::include_proto!("grpc.examples.echo");
|
||||||
}
|
}
|
||||||
|
|
||||||
use pb::{client::EchoClient, EchoRequest};
|
use pb::{echo_client::EchoClient, EchoRequest};
|
||||||
use tonic::transport::{Certificate, Channel, ClientTlsConfig, Identity};
|
use tonic::transport::{Certificate, Channel, ClientTlsConfig, Identity};
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ type ResponseStream = Pin<Box<dyn Stream<Item = Result<EchoResponse, Status>> +
|
|||||||
pub struct EchoServer;
|
pub struct EchoServer;
|
||||||
|
|
||||||
#[tonic::async_trait]
|
#[tonic::async_trait]
|
||||||
impl pb::server::Echo for EchoServer {
|
impl pb::echo_server::Echo for EchoServer {
|
||||||
async fn unary_echo(&self, request: Request<EchoRequest>) -> EchoResult<EchoResponse> {
|
async fn unary_echo(&self, request: Request<EchoRequest>) -> EchoResult<EchoResponse> {
|
||||||
let message = request.into_inner().message;
|
let message = request.into_inner().message;
|
||||||
Ok(Response::new(EchoResponse { message }))
|
Ok(Response::new(EchoResponse { message }))
|
||||||
@@ -43,7 +43,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
|
|
||||||
Server::builder()
|
Server::builder()
|
||||||
.tls_config(tls)
|
.tls_config(tls)
|
||||||
.add_service(pb::server::EchoServer::new(server))
|
.add_service(pb::echo_server::EchoServer::new(server))
|
||||||
.serve(addr)
|
.serve(addr)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,7 @@
|
|||||||
use crate::{pb::client::*, pb::*, test_assert, TestAssertion};
|
use crate::{
|
||||||
|
pb::testservice_client::*, pb::unimplementedservice_client::*, pb::*, test_assert,
|
||||||
|
TestAssertion,
|
||||||
|
};
|
||||||
use futures_util::{future, stream, StreamExt};
|
use futures_util::{future, stream, StreamExt};
|
||||||
use tokio::sync::mpsc;
|
use tokio::sync::mpsc;
|
||||||
use tonic::transport::Channel;
|
use tonic::transport::Channel;
|
||||||
|
|||||||
@@ -5,7 +5,8 @@ use std::pin::Pin;
|
|||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
use tonic::{Code, Request, Response, Status};
|
use tonic::{Code, Request, Response, Status};
|
||||||
|
|
||||||
pub use pb::server::{TestServiceServer, UnimplementedServiceServer};
|
pub use pb::testservice_server::TestServiceServer;
|
||||||
|
pub use pb::unimplementedservice_server::UnimplementedServiceServer;
|
||||||
|
|
||||||
#[derive(Default, Clone)]
|
#[derive(Default, Clone)]
|
||||||
pub struct TestService;
|
pub struct TestService;
|
||||||
@@ -17,7 +18,7 @@ type Stream<T> = Pin<
|
|||||||
>;
|
>;
|
||||||
|
|
||||||
#[tonic::async_trait]
|
#[tonic::async_trait]
|
||||||
impl pb::server::TestService for TestService {
|
impl pb::testservice_server::TestService for TestService {
|
||||||
async fn empty_call(&self, _request: Request<Empty>) -> Result<Empty> {
|
async fn empty_call(&self, _request: Request<Empty>) -> Result<Empty> {
|
||||||
Ok(Response::new(Empty {}))
|
Ok(Response::new(Empty {}))
|
||||||
}
|
}
|
||||||
@@ -153,7 +154,7 @@ impl pb::server::TestService for TestService {
|
|||||||
pub struct UnimplementedService;
|
pub struct UnimplementedService;
|
||||||
|
|
||||||
#[tonic::async_trait]
|
#[tonic::async_trait]
|
||||||
impl pb::server::UnimplementedService for UnimplementedService {
|
impl pb::unimplementedservice_server::UnimplementedService for UnimplementedService {
|
||||||
async fn unimplemented_call(&self, _req: Request<Empty>) -> Result<Empty> {
|
async fn unimplemented_call(&self, _req: Request<Empty>) -> Result<Empty> {
|
||||||
Err(Status::unimplemented(""))
|
Err(Status::unimplemented(""))
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user