Skip to content

Commit

Permalink
feat(build): Add build_transport builder option (#1130)
Browse files Browse the repository at this point in the history
  • Loading branch information
LucioFranco authored Nov 4, 2022
1 parent 6667ace commit 1f5bc9b
Show file tree
Hide file tree
Showing 9 changed files with 130 additions and 74 deletions.
4 changes: 4 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,7 @@ members = [
"tests/compression",
"tonic-web/tests/integration",
]

[patch.crates-io]
prost-build = { git = "https://github.com/tokio-rs/prost/", branch = "lucio/format" }

2 changes: 1 addition & 1 deletion tonic-build/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ version = "0.8.2"
[dependencies]
prettyplease = { version = "0.1" }
proc-macro2 = "1.0"
prost-build = { version = "0.11", optional = true }
prost-build = { version = "0.11.1", optional = true }
quote = "1.0"
syn = "1.0"

Expand Down
15 changes: 11 additions & 4 deletions tonic-build/src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,14 @@ pub fn generate<T: Service>(
emit_package: bool,
proto_path: &str,
compile_well_known_types: bool,
build_transport: bool,
attributes: &Attributes,
) -> TokenStream {
let service_ident = quote::format_ident!("{}Client", service.name());
let client_mod = quote::format_ident!("{}_client", naive_snake_case(service.name()));
let methods = generate_methods(service, emit_package, proto_path, compile_well_known_types);

let connect = generate_connect(&service_ident);
let connect = generate_connect(&service_ident, build_transport);
let service_doc = generate_doc_comments(service.comment());

let package = if emit_package { service.package() } else { "" };
Expand Down Expand Up @@ -109,8 +110,8 @@ pub fn generate<T: Service>(
}

#[cfg(feature = "transport")]
fn generate_connect(service_ident: &syn::Ident) -> TokenStream {
quote! {
fn generate_connect(service_ident: &syn::Ident, enabled: bool) -> TokenStream {
let connect_impl = quote! {
impl #service_ident<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>
Expand All @@ -122,11 +123,17 @@ fn generate_connect(service_ident: &syn::Ident) -> TokenStream {
Ok(Self::new(conn))
}
}
};

if enabled {
connect_impl
} else {
TokenStream::new()
}
}

#[cfg(not(feature = "transport"))]
fn generate_connect(_service_ident: &syn::Ident) -> TokenStream {
fn generate_connect(_service_ident: &syn::Ident, _enabled: bool) -> TokenStream {
TokenStream::new()
}

Expand Down
8 changes: 8 additions & 0 deletions tonic-build/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,14 @@ fn generate_attributes<'a>(

// Generate a singular line of a doc comment
fn generate_doc_comment<S: AsRef<str>>(comment: S) -> TokenStream {
let comment = comment.as_ref();

let comment = if !comment.starts_with(" ") {
format!(" {}", comment)
} else {
comment.to_string()
};

let mut doc_stream = TokenStream::new();

doc_stream.append(Ident::new("doc", Span::call_site()));
Expand Down
12 changes: 12 additions & 0 deletions tonic-build/src/manual.rs
Original file line number Diff line number Diff line change
Expand Up @@ -367,6 +367,7 @@ impl ServiceGenerator {
true, // emit_package,
"", // proto_path, -- not used
false, // compile_well_known_types, -- not used
self.builder.build_transport,
&Attributes::default(),
);
self.clients.extend(client);
Expand Down Expand Up @@ -409,6 +410,7 @@ impl ServiceGenerator {
pub struct Builder {
build_server: bool,
build_client: bool,
build_transport: bool,

out_dir: Option<PathBuf>,
}
Expand All @@ -418,6 +420,7 @@ impl Default for Builder {
Self {
build_server: true,
build_client: true,
build_transport: true,
out_dir: None,
}
}
Expand Down Expand Up @@ -445,6 +448,15 @@ impl Builder {
self
}

/// Enable or disable generated clients and servers to have built-in tonic
/// transport features.
///
/// When the `transport` feature is disabled this does nothing.
pub fn build_transport(mut self, enable: bool) -> Self {
self.build_transport = enable;
self
}

/// Set the output directory to generate code to.
///
/// Defaults to the `OUT_DIR` environment variable.
Expand Down
12 changes: 12 additions & 0 deletions tonic-build/src/prost.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ pub fn configure() -> Builder {
Builder {
build_client: true,
build_server: true,
build_transport: true,
file_descriptor_set_path: None,
out_dir: None,
extern_path: Vec::new(),
Expand Down Expand Up @@ -172,6 +173,7 @@ impl prost_build::ServiceGenerator for ServiceGenerator {
self.builder.emit_package,
&self.builder.proto_path,
self.builder.compile_well_known_types,
self.builder.build_transport,
&self.builder.client_attributes,
);
self.clients.extend(client);
Expand Down Expand Up @@ -214,6 +216,7 @@ impl prost_build::ServiceGenerator for ServiceGenerator {
pub struct Builder {
pub(crate) build_client: bool,
pub(crate) build_server: bool,
pub(crate) build_transport: bool,
pub(crate) file_descriptor_set_path: Option<PathBuf>,
pub(crate) extern_path: Vec<(String, String)>,
pub(crate) field_attributes: Vec<(String, String)>,
Expand Down Expand Up @@ -243,6 +246,15 @@ impl Builder {
self
}

/// Enable or disable generated clients and servers to have built-in tonic
/// transport features.
///
/// When the `transport` feature is disabled this does nothing.
pub fn build_transport(mut self, enable: bool) -> Self {
self.build_transport = enable;
self
}

/// Generate a file containing the encoded `prost_types::FileDescriptorSet` for protocol buffers
/// modules. This is required for implementing gRPC Server Reflection.
pub fn file_descriptor_set_path(mut self, path: impl AsRef<Path>) -> Self {
Expand Down
6 changes: 3 additions & 3 deletions tonic-build/src/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@ fn generate_trait<T: Service>(
) -> TokenStream {
let methods = generate_trait_methods(service, proto_path, compile_well_known_types);
let trait_doc = generate_doc_comment(&format!(
"Generated trait containing gRPC methods that should be implemented for use with {}Server.",
" Generated trait containing gRPC methods that should be implemented for use with {}Server.",
service.name()
));

Expand Down Expand Up @@ -219,7 +219,7 @@ fn generate_trait_methods<T: Service>(
(false, true) => {
let stream = quote::format_ident!("{}Stream", method.identifier());
let stream_doc = generate_doc_comment(&format!(
"Server streaming response type for the {} method.",
" Server streaming response type for the {} method.",
method.identifier()
));

Expand All @@ -235,7 +235,7 @@ fn generate_trait_methods<T: Service>(
(true, true) => {
let stream = quote::format_ident!("{}Stream", method.identifier());
let stream_doc = generate_doc_comment(&format!(
"Server streaming response type for the {} method.",
" Server streaming response type for the {} method.",
method.identifier()
));

Expand Down
80 changes: 45 additions & 35 deletions tonic-health/src/generated/grpc.health.v1.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,26 @@
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct HealthCheckRequest {
#[prost(string, tag="1")]
#[prost(string, tag = "1")]
pub service: ::prost::alloc::string::String,
}
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct HealthCheckResponse {
#[prost(enumeration="health_check_response::ServingStatus", tag="1")]
#[prost(enumeration = "health_check_response::ServingStatus", tag = "1")]
pub status: i32,
}
/// Nested message and enum types in `HealthCheckResponse`.
pub mod health_check_response {
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)]
#[derive(
Clone,
Copy,
Debug,
PartialEq,
Eq,
Hash,
PartialOrd,
Ord,
::prost::Enumeration
)]
#[repr(i32)]
pub enum ServingStatus {
Unknown = 0,
Expand Down Expand Up @@ -103,8 +113,8 @@ pub mod health_client {
self.inner = self.inner.accept_compressed(encoding);
self
}
///If the requested service is unknown, the call will fail with status
///NOT_FOUND.
/// If the requested service is unknown, the call will fail with status
/// NOT_FOUND.
pub async fn check(
&mut self,
request: impl tonic::IntoRequest<super::HealthCheckRequest>,
Expand All @@ -124,21 +134,21 @@ pub mod health_client {
);
self.inner.unary(request.into_request(), path, codec).await
}
///Performs a watch for the serving status of the requested service.
///The server will immediately send back a message indicating the current
///serving status. It will then subsequently send a new message whenever
///the service's serving status changes.
/// Performs a watch for the serving status of the requested service.
/// The server will immediately send back a message indicating the current
/// serving status. It will then subsequently send a new message whenever
/// the service's serving status changes.
///
///If the requested service is unknown when the call is received, the
///server will send a message setting the serving status to
///SERVICE_UNKNOWN but will *not* terminate the call. If at some
///future point, the serving status of the service becomes known, the
///server will send a new message with the service's serving status.
/// If the requested service is unknown when the call is received, the
/// server will send a message setting the serving status to
/// SERVICE_UNKNOWN but will *not* terminate the call. If at some
/// future point, the serving status of the service becomes known, the
/// server will send a new message with the service's serving status.
///
///If the call terminates with status UNIMPLEMENTED, then clients
///should assume this method is not supported and should not retry the
///call. If the call terminates with any other status (including OK),
///clients should retry the call with appropriate exponential backoff.
/// If the call terminates with status UNIMPLEMENTED, then clients
/// should assume this method is not supported and should not retry the
/// call. If the call terminates with any other status (including OK),
/// clients should retry the call with appropriate exponential backoff.
pub async fn watch(
&mut self,
request: impl tonic::IntoRequest<super::HealthCheckRequest>,
Expand Down Expand Up @@ -167,36 +177,36 @@ pub mod health_client {
pub mod health_server {
#![allow(unused_variables, dead_code, missing_docs, clippy::let_unit_value)]
use tonic::codegen::*;
///Generated trait containing gRPC methods that should be implemented for use with HealthServer.
/// Generated trait containing gRPC methods that should be implemented for use with HealthServer.
#[async_trait]
pub trait Health: Send + Sync + 'static {
///If the requested service is unknown, the call will fail with status
///NOT_FOUND.
/// If the requested service is unknown, the call will fail with status
/// NOT_FOUND.
async fn check(
&self,
request: tonic::Request<super::HealthCheckRequest>,
) -> Result<tonic::Response<super::HealthCheckResponse>, tonic::Status>;
///Server streaming response type for the Watch method.
/// Server streaming response type for the Watch method.
type WatchStream: futures_core::Stream<
Item = Result<super::HealthCheckResponse, tonic::Status>,
>
+ Send
+ 'static;
///Performs a watch for the serving status of the requested service.
///The server will immediately send back a message indicating the current
///serving status. It will then subsequently send a new message whenever
///the service's serving status changes.
/// Performs a watch for the serving status of the requested service.
/// The server will immediately send back a message indicating the current
/// serving status. It will then subsequently send a new message whenever
/// the service's serving status changes.
///
///If the requested service is unknown when the call is received, the
///server will send a message setting the serving status to
///SERVICE_UNKNOWN but will *not* terminate the call. If at some
///future point, the serving status of the service becomes known, the
///server will send a new message with the service's serving status.
/// If the requested service is unknown when the call is received, the
/// server will send a message setting the serving status to
/// SERVICE_UNKNOWN but will *not* terminate the call. If at some
/// future point, the serving status of the service becomes known, the
/// server will send a new message with the service's serving status.
///
///If the call terminates with status UNIMPLEMENTED, then clients
///should assume this method is not supported and should not retry the
///call. If the call terminates with any other status (including OK),
///clients should retry the call with appropriate exponential backoff.
/// If the call terminates with status UNIMPLEMENTED, then clients
/// should assume this method is not supported and should not retry the
/// call. If the call terminates with any other status (including OK),
/// clients should retry the call with appropriate exponential backoff.
async fn watch(
&self,
request: tonic::Request<super::HealthCheckRequest>,
Expand Down
Loading

0 comments on commit 1f5bc9b

Please sign in to comment.