fix(tonic): Remove Sync requirement for streams (#804)

This commit is contained in:
Lucio Franco
2021-10-24 21:48:05 -04:00
committed by GitHub
parent 1f3df8db9e
commit 23c1392fb7
31 changed files with 207 additions and 165 deletions
+2 -2
View File
@@ -55,7 +55,7 @@ http = "0.2"
tracing = "0.1"
async-stream = "0.3"
http-body = "0.4.2"
http-body = "0.4.4"
percent-encoding = "2.1"
pin-project = "1.0"
tokio-util = {version = "0.6", features = ["codec"]}
@@ -71,7 +71,7 @@ async-trait = {version = "0.1.13", optional = true}
# transport
h2 = {version = "0.3", optional = true}
hyper = {version = "0.14.2", features = ["full"], optional = true}
hyper = {version = "0.14.4", features = ["full"], optional = true}
hyper-timeout = {version = "0.4", optional = true}
tokio = {version = "1.0.1", features = ["net"], optional = true}
tokio-stream = "0.1"
+4 -2
View File
@@ -3,11 +3,13 @@
use http_body::Body;
/// A type erased HTTP body used for tonic services.
pub type BoxBody = http_body::combinators::BoxBody<bytes::Bytes, crate::Status>;
pub type BoxBody = http_body::combinators::UnsyncBoxBody<bytes::Bytes, crate::Status>;
// this also exists in `crate::codegen` but we need it here since `codegen` has
// `#[cfg(feature = "codegen")]`.
/// Create an empty `BoxBody`
pub fn empty_body() -> BoxBody {
http_body::Empty::new().map_err(|err| match err {}).boxed()
http_body::Empty::new()
.map_err(|err| match err {})
.boxed_unsync()
}
+6 -6
View File
@@ -150,7 +150,7 @@ impl<T> Grpc<T> {
) -> Result<Response<M2>, Status>
where
T: GrpcService<BoxBody>,
T::ResponseBody: Body + Send + Sync + 'static,
T::ResponseBody: Body + Send + 'static,
<T::ResponseBody as Body>::Error: Into<crate::Error>,
C: Codec<Encode = M1, Decode = M2>,
M1: Send + Sync + 'static,
@@ -169,9 +169,9 @@ impl<T> Grpc<T> {
) -> Result<Response<M2>, Status>
where
T: GrpcService<BoxBody>,
T::ResponseBody: Body + Send + Sync + 'static,
T::ResponseBody: Body + Send + 'static,
<T::ResponseBody as Body>::Error: Into<crate::Error>,
S: Stream<Item = M1> + Send + Sync + 'static,
S: Stream<Item = M1> + Send + 'static,
C: Codec<Encode = M1, Decode = M2>,
M1: Send + Sync + 'static,
M2: Send + Sync + 'static,
@@ -206,7 +206,7 @@ impl<T> Grpc<T> {
) -> Result<Response<Streaming<M2>>, Status>
where
T: GrpcService<BoxBody>,
T::ResponseBody: Body + Send + Sync + 'static,
T::ResponseBody: Body + Send + 'static,
<T::ResponseBody as Body>::Error: Into<crate::Error>,
C: Codec<Encode = M1, Decode = M2>,
M1: Send + Sync + 'static,
@@ -225,9 +225,9 @@ impl<T> Grpc<T> {
) -> Result<Response<Streaming<M2>>, Status>
where
T: GrpcService<BoxBody>,
T::ResponseBody: Body + Send + Sync + 'static,
T::ResponseBody: Body + Send + 'static,
<T::ResponseBody as Body>::Error: Into<crate::Error>,
S: Stream<Item = M1> + Send + Sync + 'static,
S: Stream<Item = M1> + Send + 'static,
C: Codec<Encode = M1, Decode = M2>,
M1: Send + Sync + 'static,
M2: Send + Sync + 'static,
+12 -12
View File
@@ -21,7 +21,7 @@ const BUFFER_SIZE: usize = 8 * 1024;
/// This will wrap some inner [`Body`] and [`Decoder`] and provide an interface
/// to fetch the message stream and trailing metadata
pub struct Streaming<T> {
decoder: Box<dyn Decoder<Item = T, Error = Status> + Send + Sync + 'static>,
decoder: Box<dyn Decoder<Item = T, Error = Status> + Send + 'static>,
body: BoxBody,
state: State,
direction: Direction,
@@ -56,9 +56,9 @@ impl<T> Streaming<T> {
#[cfg(feature = "compression")] encoding: Option<CompressionEncoding>,
) -> Self
where
B: Body + Send + Sync + 'static,
B: Body + Send + 'static,
B::Error: Into<crate::Error>,
D: Decoder<Item = T, Error = Status> + Send + Sync + 'static,
D: Decoder<Item = T, Error = Status> + Send + 'static,
{
Self::new(
decoder,
@@ -71,9 +71,9 @@ impl<T> Streaming<T> {
pub(crate) fn new_empty<B, D>(decoder: D, body: B) -> Self
where
B: Body + Send + Sync + 'static,
B: Body + Send + 'static,
B::Error: Into<crate::Error>,
D: Decoder<Item = T, Error = Status> + Send + Sync + 'static,
D: Decoder<Item = T, Error = Status> + Send + 'static,
{
Self::new(
decoder,
@@ -91,9 +91,9 @@ impl<T> Streaming<T> {
#[cfg(feature = "compression")] encoding: Option<CompressionEncoding>,
) -> Self
where
B: Body + Send + Sync + 'static,
B: Body + Send + 'static,
B::Error: Into<crate::Error>,
D: Decoder<Item = T, Error = Status> + Send + Sync + 'static,
D: Decoder<Item = T, Error = Status> + Send + 'static,
{
Self::new(
decoder,
@@ -111,16 +111,16 @@ impl<T> Streaming<T> {
#[cfg(feature = "compression")] encoding: Option<CompressionEncoding>,
) -> Self
where
B: Body + Send + Sync + 'static,
B: Body + Send + 'static,
B::Error: Into<crate::Error>,
D: Decoder<Item = T, Error = Status> + Send + Sync + 'static,
D: Decoder<Item = T, Error = Status> + Send + 'static,
{
Self {
decoder: Box::new(decoder),
body: body
.map_data(|mut buf| buf.copy_to_bytes(buf.remaining()))
.map_err(|err| Status::map_error(err.into()))
.boxed(),
.boxed_unsync(),
state: State::ReadHeader,
direction,
buf: BytesMut::with_capacity(BUFFER_SIZE),
@@ -140,7 +140,7 @@ impl<T> Streaming<T> {
/// # use std::fmt::Debug;
/// # async fn next_message_ex<T, D>(mut request: Streaming<T>) -> Result<(), Status>
/// # where T: Debug,
/// # D: Decoder<Item = T, Error = Status> + Send + Sync + 'static,
/// # D: Decoder<Item = T, Error = Status> + Send + 'static,
/// # {
/// if let Some(next_message) = request.message().await? {
/// println!("{:?}", next_message);
@@ -378,4 +378,4 @@ impl<T> fmt::Debug for Streaming<T> {
}
#[cfg(test)]
static_assertions::assert_impl_all!(Streaming<()>: Send, Sync);
static_assertions::assert_impl_all!(Streaming<()>: Send);
+5 -7
View File
@@ -22,9 +22,8 @@ pub(crate) fn encode_server<T, U>(
#[cfg(feature = "compression")] compression_override: SingleMessageCompressionOverride,
) -> EncodeBody<impl Stream<Item = Result<Bytes, Status>>>
where
T: Encoder<Error = Status> + Send + Sync + 'static,
T::Item: Send + Sync,
U: Stream<Item = Result<T::Item, Status>> + Send + Sync + 'static,
T: Encoder<Error = Status>,
U: Stream<Item = Result<T::Item, Status>>,
{
let stream = encode(
encoder,
@@ -45,9 +44,8 @@ pub(crate) fn encode_client<T, U>(
#[cfg(feature = "compression")] compression_encoding: Option<CompressionEncoding>,
) -> EncodeBody<impl Stream<Item = Result<Bytes, Status>>>
where
T: Encoder<Error = Status> + Send + Sync + 'static,
T::Item: Send + Sync,
U: Stream<Item = T::Item> + Send + Sync + 'static,
T: Encoder<Error = Status>,
U: Stream<Item = T::Item>,
{
let stream = encode(
encoder,
@@ -157,7 +155,7 @@ pub(crate) struct EncodeBody<S> {
impl<S> EncodeBody<S>
where
S: Stream<Item = Result<Bytes, Status>> + Send + Sync + 'static,
S: Stream<Item = Result<Bytes, Status>>,
{
pub(crate) fn new_client(inner: S) -> Self {
Self {
+2 -2
View File
@@ -40,9 +40,9 @@ pub trait Codec: Default {
type Decode: Send + 'static;
/// The encoder that can encode a message.
type Encoder: Encoder<Item = Self::Encode, Error = Status> + Send + Sync + 'static;
type Encoder: Encoder<Item = Self::Encode, Error = Status> + Send + 'static;
/// The encoder that can decode a message.
type Decoder: Decoder<Item = Self::Decode, Error = Status> + Send + Sync + 'static;
type Decoder: Decoder<Item = Self::Decode, Error = Status> + Send + 'static;
/// Fetch the encoder.
fn encoder(&mut self) -> Self::Encoder;
+3 -1
View File
@@ -35,5 +35,7 @@ impl std::fmt::Display for Never {
impl std::error::Error for Never {}
pub fn empty_body() -> crate::body::BoxBody {
http_body::Empty::new().map_err(|err| match err {}).boxed()
http_body::Empty::new()
.map_err(|err| match err {})
.boxed_unsync()
}
+3 -3
View File
@@ -86,7 +86,7 @@ pub trait IntoRequest<T>: sealed::Sealed {
/// ```
pub trait IntoStreamingRequest: sealed::Sealed {
/// The RPC request stream type
type Stream: Stream<Item = Self::Message> + Send + Sync + 'static;
type Stream: Stream<Item = Self::Message> + Send + 'static;
/// The RPC request type
type Message;
@@ -357,7 +357,7 @@ impl<T> IntoRequest<T> for Request<T> {
impl<T> IntoStreamingRequest for T
where
T: Stream + Send + Sync + 'static,
T: Stream + Send + 'static,
{
type Stream = T;
type Message = T::Item;
@@ -369,7 +369,7 @@ where
impl<T> IntoStreamingRequest for Request<T>
where
T: Stream + Send + Sync + 'static,
T: Stream + Send + 'static,
{
type Stream = T;
type Message = T::Item;
+9 -10
View File
@@ -44,7 +44,6 @@ pub struct Grpc<T> {
impl<T> Grpc<T>
where
T: Codec,
T::Encode: Sync,
{
/// Creates a new gRPC server with the provided [`Codec`].
pub fn new(codec: T) -> Self {
@@ -173,7 +172,7 @@ where
) -> http::Response<BoxBody>
where
S: UnaryService<T::Decode, Response = T::Encode>,
B: Body + Send + Sync + 'static,
B: Body + Send + 'static,
B::Error: Into<crate::Error> + Send,
{
#[cfg(feature = "compression")]
@@ -221,8 +220,8 @@ where
) -> http::Response<BoxBody>
where
S: ServerStreamingService<T::Decode, Response = T::Encode>,
S::ResponseStream: Send + Sync + 'static,
B: Body + Send + Sync + 'static,
S::ResponseStream: Send + 'static,
B: Body + Send + 'static,
B::Error: Into<crate::Error> + Send,
{
#[cfg(feature = "compression")]
@@ -265,7 +264,7 @@ where
) -> http::Response<BoxBody>
where
S: ClientStreamingService<T::Decode, Response = T::Encode>,
B: Body + Send + Sync + 'static,
B: Body + Send + 'static,
B::Error: Into<crate::Error> + Send + 'static,
{
#[cfg(feature = "compression")]
@@ -301,8 +300,8 @@ where
) -> http::Response<BoxBody>
where
S: StreamingService<T::Decode, Response = T::Encode> + Send,
S::ResponseStream: Send + Sync + 'static,
B: Body + Send + Sync + 'static,
S::ResponseStream: Send + 'static,
B: Body + Send + 'static,
B::Error: Into<crate::Error> + Send,
{
#[cfg(feature = "compression")]
@@ -329,7 +328,7 @@ where
request: http::Request<B>,
) -> Result<Request<T::Decode>, Status>
where
B: Body + Send + Sync + 'static,
B: Body + Send + 'static,
B::Error: Into<crate::Error> + Send,
{
#[cfg(feature = "compression")]
@@ -365,7 +364,7 @@ where
request: http::Request<B>,
) -> Result<Request<Streaming<T::Decode>>, Status>
where
B: Body + Send + Sync + 'static,
B: Body + Send + 'static,
B::Error: Into<crate::Error> + Send,
{
#[cfg(feature = "compression")]
@@ -388,7 +387,7 @@ where
#[cfg(feature = "compression")] compression_override: SingleMessageCompressionOverride,
) -> http::Response<BoxBody>
where
B: TryStream<Ok = T::Encode, Error = Status> + Send + Sync + 'static,
B: TryStream<Ok = T::Encode, Error = Status> + Send + 'static,
{
let response = match response {
Ok(r) => r,
+11 -11
View File
@@ -54,7 +54,7 @@ use tower::{
Service, ServiceBuilder,
};
type BoxHttpBody = http_body::combinators::BoxBody<Bytes, crate::Error>;
type BoxHttpBody = http_body::combinators::UnsyncBoxBody<Bytes, crate::Error>;
type BoxService = tower::util::BoxService<Request<Body>, Response<BoxHttpBody>, crate::Error>;
type TraceInterceptor = Arc<dyn Fn(&http::Request<()>) -> tracing::Span + Send + Sync + 'static>;
@@ -465,7 +465,7 @@ impl<L> Server<L> {
IO::ConnectInfo: Clone + Send + Sync + 'static,
IE: Into<crate::Error>,
F: Future<Output = ()>,
ResBody: http_body::Body<Data = Bytes> + Send + Sync + 'static,
ResBody: http_body::Body<Data = Bytes> + Send + 'static,
ResBody::Error: Into<crate::Error>,
{
let trace_interceptor = self.trace_interceptor.clone();
@@ -627,7 +627,7 @@ where
Send + 'static,
<<L as Layer<Routes<A, B, Request<Body>>>>::Service as Service<Request<Body>>>::Error:
Into<crate::Error> + Send,
ResBody: http_body::Body<Data = Bytes> + Send + Sync + 'static,
ResBody: http_body::Body<Data = Bytes> + Send + 'static,
ResBody::Error: Into<crate::Error>,
{
let incoming = TcpIncoming::new(addr, self.server.tcp_nodelay, self.server.tcp_keepalive)
@@ -659,7 +659,7 @@ where
Send + 'static,
<<L as Layer<Routes<A, B, Request<Body>>>>::Service as Service<Request<Body>>>::Error:
Into<crate::Error> + Send,
ResBody: http_body::Body<Data = Bytes> + Send + Sync + 'static,
ResBody: http_body::Body<Data = Bytes> + Send + 'static,
ResBody::Error: Into<crate::Error>,
{
let incoming = TcpIncoming::new(addr, self.server.tcp_nodelay, self.server.tcp_keepalive)
@@ -688,7 +688,7 @@ where
Send + 'static,
<<L as Layer<Routes<A, B, Request<Body>>>>::Service as Service<Request<Body>>>::Error:
Into<crate::Error> + Send,
ResBody: http_body::Body<Data = Bytes> + Send + Sync + 'static,
ResBody: http_body::Body<Data = Bytes> + Send + 'static,
ResBody::Error: Into<crate::Error>,
{
self.server
@@ -723,7 +723,7 @@ where
Send + 'static,
<<L as Layer<Routes<A, B, Request<Body>>>>::Service as Service<Request<Body>>>::Error:
Into<crate::Error> + Send,
ResBody: http_body::Body<Data = Bytes> + Send + Sync + 'static,
ResBody: http_body::Body<Data = Bytes> + Send + 'static,
ResBody::Error: Into<crate::Error>,
{
self.server
@@ -740,7 +740,7 @@ where
Send + 'static,
<<L as Layer<Routes<A, B, Request<Body>>>>::Service as Service<Request<Body>>>::Error:
Into<crate::Error> + Send,
ResBody: http_body::Body<Data = Bytes> + Send + Sync + 'static,
ResBody: http_body::Body<Data = Bytes> + Send + 'static,
ResBody::Error: Into<crate::Error>,
{
let inner = self.server.layer.layer(self.routes);
@@ -763,7 +763,7 @@ impl<S, ResBody> Service<Request<Body>> for Svc<S>
where
S: Service<Request<Body>, Response = Response<ResBody>>,
S::Error: Into<crate::Error>,
ResBody: http_body::Body<Data = Bytes> + Send + Sync + 'static,
ResBody: http_body::Body<Data = Bytes> + Send + 'static,
ResBody::Error: Into<crate::Error>,
{
type Response = Response<BoxHttpBody>;
@@ -807,7 +807,7 @@ impl<F, E, ResBody> Future for SvcFuture<F>
where
F: Future<Output = Result<Response<ResBody>, E>>,
E: Into<crate::Error>,
ResBody: http_body::Body<Data = Bytes> + Send + Sync + 'static,
ResBody: http_body::Body<Data = Bytes> + Send + 'static,
ResBody::Error: Into<crate::Error>,
{
type Output = Result<Response<BoxHttpBody>, crate::Error>;
@@ -817,7 +817,7 @@ where
let _guard = this.span.enter();
let response: Response<ResBody> = ready!(this.inner.poll(cx)).map_err(Into::into)?;
let response = response.map(|body| body.map_err(Into::into).boxed());
let response = response.map(|body| body.map_err(Into::into).boxed_unsync());
Poll::Ready(Ok(response))
}
}
@@ -842,7 +842,7 @@ where
S: Service<Request<Body>, Response = Response<ResBody>> + Clone + Send + 'static,
S::Future: Send + 'static,
S::Error: Into<crate::Error> + Send,
ResBody: http_body::Body<Data = Bytes> + Send + Sync + 'static,
ResBody: http_body::Body<Data = Bytes> + Send + 'static,
ResBody::Error: Into<crate::Error>,
{
type Response = BoxService;