From 0a2a2f3ac56705b3efe3265d650d5794e936eab7 Mon Sep 17 00:00:00 2001 From: Ben Sully Date: Tue, 23 Aug 2022 15:31:37 +0100 Subject: [PATCH] tonic-health: commit generated code (#1065) * tonic-health: commit generated code rather than generating at build time This saves users from needing protoc available on their path if they're not generating other tonic code at build time, either. The generated modules can be regenerated by enabling the `gen-proto` feature, which will trigger the relevant part of the build script. * Check generated code for tonic-health matches in CI * Use bootstrap test to generate/check validity of generated code As suggested by @LucioFranco in https://github.com/hyperium/tonic/pull/1065\#discussion_r951580189. This avoids the need for a feature which would show up in docs.rs, and achieves the same goals via CI. --- tonic-health/Cargo.toml | 4 +- tonic-health/build.rs | 14 - tonic-health/src/generated/grpc.health.v1.rs | 379 ++++++++++++++++++ tonic-health/src/generated/grpc_health_v1.bin | Bin 0 -> 2875 bytes tonic-health/src/lib.rs | 6 +- tonic-health/tests/bootstrap.rs | 30 ++ 6 files changed, 413 insertions(+), 20 deletions(-) delete mode 100644 tonic-health/build.rs create mode 100644 tonic-health/src/generated/grpc.health.v1.rs create mode 100644 tonic-health/src/generated/grpc_health_v1.bin create mode 100644 tonic-health/tests/bootstrap.rs diff --git a/tonic-health/Cargo.toml b/tonic-health/Cargo.toml index 5b89de2..c3bc523 100644 --- a/tonic-health/Cargo.toml +++ b/tonic-health/Cargo.toml @@ -16,7 +16,7 @@ version = "0.7.0" [features] default = ["transport"] -transport = ["tonic/transport", "tonic-build/transport"] +transport = ["tonic/transport"] [dependencies] async-stream = "0.3" @@ -28,6 +28,4 @@ tonic = {version = "0.8", path = "../tonic", features = ["codegen", "prost"]} [dev-dependencies] tokio = {version = "1.0", features = ["rt-multi-thread", "macros"]} - -[build-dependencies] tonic-build = {version = "0.8", path = "../tonic-build", features = ["prost"]} diff --git a/tonic-health/build.rs b/tonic-health/build.rs deleted file mode 100644 index 5b04330..0000000 --- a/tonic-health/build.rs +++ /dev/null @@ -1,14 +0,0 @@ -use std::env; -use std::path::PathBuf; - -fn main() -> Result<(), Box> { - let grpc_health_v1_descriptor_set_path: PathBuf = - PathBuf::from(env::var("OUT_DIR").unwrap()).join("grpc_health_v1.bin"); - tonic_build::configure() - .file_descriptor_set_path(grpc_health_v1_descriptor_set_path) - .build_server(true) - .build_client(true) - .compile(&["proto/health.proto"], &["proto/"])?; - - Ok(()) -} diff --git a/tonic-health/src/generated/grpc.health.v1.rs b/tonic-health/src/generated/grpc.health.v1.rs new file mode 100644 index 0000000..634201e --- /dev/null +++ b/tonic-health/src/generated/grpc.health.v1.rs @@ -0,0 +1,379 @@ +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct HealthCheckRequest { + #[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")] + 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)] + #[repr(i32)] + pub enum ServingStatus { + Unknown = 0, + Serving = 1, + NotServing = 2, + /// Used only by the Watch method. + ServiceUnknown = 3, + } + impl ServingStatus { + /// String value of the enum field names used in the ProtoBuf definition. + /// + /// The values are not transformed in any way and thus are considered stable + /// (if the ProtoBuf definition does not change) and safe for programmatic use. + pub fn as_str_name(&self) -> &'static str { + match self { + ServingStatus::Unknown => "UNKNOWN", + ServingStatus::Serving => "SERVING", + ServingStatus::NotServing => "NOT_SERVING", + ServingStatus::ServiceUnknown => "SERVICE_UNKNOWN", + } + } + } +} +/// Generated client implementations. +pub mod health_client { + #![allow(unused_variables, dead_code, missing_docs, clippy::let_unit_value)] + use tonic::codegen::*; + use tonic::codegen::http::Uri; + #[derive(Debug, Clone)] + pub struct HealthClient { + inner: tonic::client::Grpc, + } + impl HealthClient { + /// Attempt to create a new client by connecting to a given endpoint. + pub async fn connect(dst: D) -> Result + where + D: std::convert::TryInto, + D::Error: Into, + { + let conn = tonic::transport::Endpoint::new(dst)?.connect().await?; + Ok(Self::new(conn)) + } + } + impl HealthClient + where + T: tonic::client::GrpcService, + T::Error: Into, + T::ResponseBody: Body + Send + 'static, + ::Error: Into + Send, + { + pub fn new(inner: T) -> Self { + let inner = tonic::client::Grpc::new(inner); + Self { inner } + } + pub fn with_origin(inner: T, origin: Uri) -> Self { + let inner = tonic::client::Grpc::with_origin(inner, origin); + Self { inner } + } + pub fn with_interceptor( + inner: T, + interceptor: F, + ) -> HealthClient> + where + F: tonic::service::Interceptor, + T::ResponseBody: Default, + T: tonic::codegen::Service< + http::Request, + Response = http::Response< + >::ResponseBody, + >, + >, + , + >>::Error: Into + Send + Sync, + { + HealthClient::new(InterceptedService::new(inner, interceptor)) + } + /// Compress requests with the given encoding. + /// + /// This requires the server to support it otherwise it might respond with an + /// error. + #[must_use] + pub fn send_compressed(mut self, encoding: CompressionEncoding) -> Self { + self.inner = self.inner.send_compressed(encoding); + self + } + /// Enable decompressing responses. + #[must_use] + pub fn accept_compressed(mut self, encoding: CompressionEncoding) -> Self { + self.inner = self.inner.accept_compressed(encoding); + self + } + /// If the requested service is unknown, the call will fail with status + /// NOT_FOUND. + pub async fn check( + &mut self, + request: impl tonic::IntoRequest, + ) -> Result, tonic::Status> { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::new( + tonic::Code::Unknown, + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/grpc.health.v1.Health/Check", + ); + 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. + /// + /// 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. + pub async fn watch( + &mut self, + request: impl tonic::IntoRequest, + ) -> Result< + tonic::Response>, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::new( + tonic::Code::Unknown, + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/grpc.health.v1.Health/Watch", + ); + self.inner.server_streaming(request.into_request(), path, codec).await + } + } +} +/// Generated server implementations. +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. + #[async_trait] + pub trait Health: Send + Sync + 'static { + /// If the requested service is unknown, the call will fail with status + /// NOT_FOUND. + async fn check( + &self, + request: tonic::Request, + ) -> Result, tonic::Status>; + ///Server streaming response type for the Watch method. + type WatchStream: futures_core::Stream< + Item = Result, + > + + 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. + /// + /// 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. + async fn watch( + &self, + request: tonic::Request, + ) -> Result, tonic::Status>; + } + #[derive(Debug)] + pub struct HealthServer { + inner: _Inner, + accept_compression_encodings: EnabledCompressionEncodings, + send_compression_encodings: EnabledCompressionEncodings, + } + struct _Inner(Arc); + impl HealthServer { + pub fn new(inner: T) -> Self { + Self::from_arc(Arc::new(inner)) + } + pub fn from_arc(inner: Arc) -> Self { + let inner = _Inner(inner); + Self { + inner, + accept_compression_encodings: Default::default(), + send_compression_encodings: Default::default(), + } + } + pub fn with_interceptor( + inner: T, + interceptor: F, + ) -> InterceptedService + where + F: tonic::service::Interceptor, + { + InterceptedService::new(Self::new(inner), interceptor) + } + /// Enable decompressing requests with the given encoding. + #[must_use] + pub fn accept_compressed(mut self, encoding: CompressionEncoding) -> Self { + self.accept_compression_encodings.enable(encoding); + self + } + /// Compress responses with the given encoding, if the client supports it. + #[must_use] + pub fn send_compressed(mut self, encoding: CompressionEncoding) -> Self { + self.send_compression_encodings.enable(encoding); + self + } + } + impl tonic::codegen::Service> for HealthServer + where + T: Health, + B: Body + Send + 'static, + B::Error: Into + Send + 'static, + { + type Response = http::Response; + type Error = std::convert::Infallible; + type Future = BoxFuture; + fn poll_ready( + &mut self, + _cx: &mut Context<'_>, + ) -> Poll> { + Poll::Ready(Ok(())) + } + fn call(&mut self, req: http::Request) -> Self::Future { + let inner = self.inner.clone(); + match req.uri().path() { + "/grpc.health.v1.Health/Check" => { + #[allow(non_camel_case_types)] + struct CheckSvc(pub Arc); + impl< + T: Health, + > tonic::server::UnaryService + for CheckSvc { + type Response = super::HealthCheckResponse; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; + fn call( + &mut self, + request: tonic::Request, + ) -> Self::Future { + let inner = self.0.clone(); + let fut = async move { (*inner).check(request).await }; + Box::pin(fut) + } + } + let accept_compression_encodings = self.accept_compression_encodings; + let send_compression_encodings = self.send_compression_encodings; + let inner = self.inner.clone(); + let fut = async move { + let inner = inner.0; + let method = CheckSvc(inner); + let codec = tonic::codec::ProstCodec::default(); + let mut grpc = tonic::server::Grpc::new(codec) + .apply_compression_config( + accept_compression_encodings, + send_compression_encodings, + ); + let res = grpc.unary(method, req).await; + Ok(res) + }; + Box::pin(fut) + } + "/grpc.health.v1.Health/Watch" => { + #[allow(non_camel_case_types)] + struct WatchSvc(pub Arc); + impl< + T: Health, + > tonic::server::ServerStreamingService + for WatchSvc { + type Response = super::HealthCheckResponse; + type ResponseStream = T::WatchStream; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; + fn call( + &mut self, + request: tonic::Request, + ) -> Self::Future { + let inner = self.0.clone(); + let fut = async move { (*inner).watch(request).await }; + Box::pin(fut) + } + } + let accept_compression_encodings = self.accept_compression_encodings; + let send_compression_encodings = self.send_compression_encodings; + let inner = self.inner.clone(); + let fut = async move { + let inner = inner.0; + let method = WatchSvc(inner); + let codec = tonic::codec::ProstCodec::default(); + let mut grpc = tonic::server::Grpc::new(codec) + .apply_compression_config( + accept_compression_encodings, + send_compression_encodings, + ); + let res = grpc.server_streaming(method, req).await; + Ok(res) + }; + Box::pin(fut) + } + _ => { + Box::pin(async move { + Ok( + http::Response::builder() + .status(200) + .header("grpc-status", "12") + .header("content-type", "application/grpc") + .body(empty_body()) + .unwrap(), + ) + }) + } + } + } + } + impl Clone for HealthServer { + fn clone(&self) -> Self { + let inner = self.inner.clone(); + Self { + inner, + accept_compression_encodings: self.accept_compression_encodings, + send_compression_encodings: self.send_compression_encodings, + } + } + } + impl Clone for _Inner { + fn clone(&self) -> Self { + Self(self.0.clone()) + } + } + impl std::fmt::Debug for _Inner { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{:?}", self.0) + } + } + impl tonic::server::NamedService for HealthServer { + const NAME: &'static str = "grpc.health.v1.Health"; + } +} diff --git a/tonic-health/src/generated/grpc_health_v1.bin b/tonic-health/src/generated/grpc_health_v1.bin new file mode 100644 index 0000000000000000000000000000000000000000..52efb312248858eba8a5024742a401fbc68b32fb GIT binary patch literal 2875 zcmb_e&2ke*5Y|d-*^G^C*8CVlLL+`ngk(FFOA=FMga8GQ97)DS4soqkBWa7(&SqxT z!pA&C-XVun<&-=@&Uu17OS)%wB^xLzhxi~*PxthHf4%I_%WP@H-9V2jkrY}u%R?D? zmGtU(yHsJ$bHlHVxc9cre~P)%&N`b{Tps%#U$?-zf3BU8rQa>KcIJVKM5wsaU`3@} z9V_!-d1t$F)==dmk18Fq5e_@%VLMe&YO(WY7|tS_KWM&awho)CIU+js_UlIT*{bEN zu*GJpdz4+|oi(;%h+6$9ds5i>&0@vGytB{dOrTEblm3}3Y~1>!Od5Eb%^kYh8~tw@ zx2(r5yWorWj6YsXLfEG=?pr^Uhe8YkUKxtO4TlvWhgHgWb!4h(&PU1l=y?0r{PHuZ zd!nN9di%Ry99DGf3%N%Y`)iI_OHScJ&e{3HhMI^@q(2;K*xB0t3c4c>!}fj+_F_E} zQZWWEu`RIVeTc(8m!MH%FLFKnmvYMRnoH%25OykCaGwN9DXX;k4TBRA!`MB6P-uu1 zM-9G$fgf<-?>ru9@I&y#I0}3>^f*j>Ju+5O9Tf&|QVpV~T@-dvJURg}I4uUQMrY}7 zq;>RlwK|zhDz0(VWGhI*P}P@>TD{q+KSXEo!9f^sr9k2&_!5Kcoq!vmE1ug!2LpEk zLV`P#9C=!hs}t#K?BX&gG0+oNat3{0Y3cW3eI`q(|A5h+7Qj5YA(Zwy(CC!l@m{CV zDKj{1bf32lx^TGHZtpd_jd}-KZK$=HPa54utBKT8*lWIl7menVGH}ch)`Gu_Bzcc6 z`jkK3$7FRlrFdE$7$BEu6>-lW_#Oro4r6zSg%-zLh8PP(T#kK3HB{(apF!Y{eH>GB zF{}HuB0E1@rd2#Q6d~p+0Muk!z!U`|Ht++;haN{4PzM#r)J9=(h8RHHt6zNf#_AouF_ndY4PLjwAmAAV{Cz0d8e?JyF#Z0r*J9v1v|&`3wM%Za(OvdGnb1_ zfsV=Lm0ZbOGN(Yt+ZK+yirIIR!d0mbY_`eJ%Hyh3A5u!~1Is8*Gu; zb}pZD3fJ?O*bEm2^B389RwN!7yJ@eoWj3FX$i8VW&S*@{&E=J;II>Hp#K}_WlsILwbV?k_TlU4N zwmgd8vR7s_@ezHisWTYQZF{{0a6mvI!r+7kiMq~!C5$-!sw%2AfD!hI9 zibn8VO?1u;bc8Pt&bOBN~TqLoo@<#%t{80D%a92Ch#hgrsEOF`y0fv~|#Yg5jVS zq#v!7i;EeBp_G?C&nWb;y!kErr)XS3$=!T?7Vt8O zumaG~i9#%32rBL=N?52fwJwBwGSxakA&x$<1Z9%%hBFicDTZ%{g*NTX`Ph< z>m#|x{bSxY1xkF*;x@6)!c<&OV>}xgA~@nBeNN0i7yw~AiS_|5s0V}fImjCAH+JA93tU|I_Z}8jHG+X+~Pj#aYQ+;VAftA_5MssvlW=?_#m67vS?a$ z>a;rDt8mb4yxM$o*cIXzqxp;qX_NW=l6vQqIlUCPOr(lpSnR&f*wNn?U5 zArmKt>kmQGk{iD9PA+BoV%B-XB`=J-aeQLwji%r~psY{uOsrp2p89v;} zQbdxPo3@?^F$N#k4t2N~45p(