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
+21 -26
View File
@@ -1,29 +1,24 @@
[workspace]
members = [
"tonic",
"tonic-build",
"tonic-health",
"tonic-types",
"tonic-reflection",
"tonic-web",
# Non-published crates
"examples",
"interop",
# Tests
"tests/included_service",
"tests/same_name",
"tests/service_named_service",
"tests/wellknown",
"tests/wellknown-compiled",
"tests/extern_path/uuid",
"tests/ambiguous_methods",
"tests/extern_path/my_application",
"tests/integration_tests",
"tests/stream_conflict",
"tests/root-crate-path",
"tests/compression",
"tonic-web/tests/integration"
"tonic",
"tonic-build",
"tonic-health",
"tonic-types",
"tonic-reflection",
"tonic-web", # Non-published crates
"examples",
"interop", # Tests
"tests/included_service",
"tests/same_name",
"tests/service_named_service",
"tests/wellknown",
"tests/wellknown-compiled",
"tests/extern_path/uuid",
"tests/ambiguous_methods",
"tests/extern_path/my_application",
"tests/integration_tests",
"tests/stream_conflict",
"tests/root-crate-path",
"tests/compression",
"tonic-web/tests/integration",
]
+2 -2
View File
@@ -300,7 +300,7 @@ impl RouteGuide for RouteGuideService {
unimplemented!()
}
type RouteChatStream = Pin<Box<dyn Stream<Item = Result<RouteNote, Status>> + Send + Sync + 'static>>;
type RouteChatStream = Pin<Box<dyn Stream<Item = Result<RouteNote, Status>> + Send + 'static>>;
async fn route_chat(
&self,
@@ -493,7 +493,7 @@ use std::collections::HashMap;
```rust
type RouteChatStream =
Pin<Box<dyn Stream<Item = Result<RouteNote, Status>> + Send + Sync + 'static>>;
Pin<Box<dyn Stream<Item = Result<RouteNote, Status>> + Send + 'static>>;
async fn route_chat(
+1 -1
View File
@@ -8,7 +8,7 @@ use std::pin::Pin;
use tonic::{metadata::MetadataValue, transport::Server, Request, Response, Status, Streaming};
type EchoResult<T> = Result<Response<T>, Status>;
type ResponseStream = Pin<Box<dyn Stream<Item = Result<EchoResponse, Status>> + Send + Sync>>;
type ResponseStream = Pin<Box<dyn Stream<Item = Result<EchoResponse, Status>> + Send>>;
#[derive(Default)]
pub struct EchoServer;
+1 -1
View File
@@ -11,7 +11,7 @@ use tonic::{transport::Server, Request, Response, Status, Streaming};
use pb::{EchoRequest, EchoResponse};
type EchoResult<T> = Result<Response<T>, Status>;
type ResponseStream = Pin<Box<dyn Stream<Item = Result<EchoResponse, Status>> + Send + Sync>>;
type ResponseStream = Pin<Box<dyn Stream<Item = Result<EchoResponse, Status>> + Send>>;
#[derive(Debug)]
pub struct EchoServer {
+1 -1
View File
@@ -35,7 +35,7 @@ use echo::{
EchoRequest, EchoResponse,
};
type ResponseStream = Pin<Box<dyn Stream<Item = Result<EchoResponse, Status>> + Send + Sync>>;
type ResponseStream = Pin<Box<dyn Stream<Item = Result<EchoResponse, Status>> + Send>>;
#[derive(Default)]
pub struct MyGreeter {}
+1 -1
View File
@@ -11,7 +11,7 @@ use tonic::{transport::Server, Request, Response, Status, Streaming};
use pb::{EchoRequest, EchoResponse};
type EchoResult<T> = Result<Response<T>, Status>;
type ResponseStream = Pin<Box<dyn Stream<Item = Result<EchoResponse, Status>> + Send + Sync>>;
type ResponseStream = Pin<Box<dyn Stream<Item = Result<EchoResponse, Status>> + Send>>;
#[derive(Debug)]
pub struct EchoServer {
+1 -1
View File
@@ -20,7 +20,7 @@ use echo::{
EchoRequest, EchoResponse,
};
type ResponseStream = Pin<Box<dyn Stream<Item = Result<EchoResponse, Status>> + Send + Sync>>;
type ResponseStream = Pin<Box<dyn Stream<Item = Result<EchoResponse, Status>> + Send>>;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
+1 -2
View File
@@ -102,8 +102,7 @@ impl RouteGuide for RouteGuideService {
Ok(Response::new(summary))
}
type RouteChatStream =
Pin<Box<dyn Stream<Item = Result<RouteNote, Status>> + Send + Sync + 'static>>;
type RouteChatStream = Pin<Box<dyn Stream<Item = Result<RouteNote, Status>> + Send + 'static>>;
async fn route_chat(
&self,
+1 -1
View File
@@ -12,7 +12,7 @@ use tonic::{transport::Server, Request, Response, Status, Streaming};
use pb::{EchoRequest, EchoResponse};
type EchoResult<T> = Result<Response<T>, Status>;
type ResponseStream = Pin<Box<dyn Stream<Item = Result<EchoResponse, Status>> + Send + Sync>>;
type ResponseStream = Pin<Box<dyn Stream<Item = Result<EchoResponse, Status>> + Send>>;
#[derive(Debug)]
pub struct EchoServer {}
+1 -1
View File
@@ -14,7 +14,7 @@ use tonic::{
};
type EchoResult<T> = Result<Response<T>, Status>;
type ResponseStream = Pin<Box<dyn Stream<Item = Result<EchoResponse, Status>> + Send + Sync>>;
type ResponseStream = Pin<Box<dyn Stream<Item = Result<EchoResponse, Status>> + Send>>;
#[derive(Default)]
pub struct EchoServer;
+1 -1
View File
@@ -9,7 +9,7 @@ use tonic::transport::{Certificate, Identity, Server, ServerTlsConfig};
use tonic::{Request, Response, Status};
type EchoResult<T> = Result<Response<T>, Status>;
type ResponseStream = Pin<Box<dyn Stream<Item = Result<EchoResponse, Status>> + Send + Sync>>;
type ResponseStream = Pin<Box<dyn Stream<Item = Result<EchoResponse, Status>> + Send>>;
#[derive(Default)]
pub struct EchoServer;
+2 -3
View File
@@ -18,9 +18,8 @@ pub struct TestService;
type Result<T> = std::result::Result<Response<T>, Status>;
type Streaming<T> = Request<tonic::Streaming<T>>;
type Stream<T> = Pin<
Box<dyn futures_core::Stream<Item = std::result::Result<T, Status>> + Send + Sync + 'static>,
>;
type Stream<T> =
Pin<Box<dyn futures_core::Stream<Item = std::result::Result<T, Status>> + Send + 'static>>;
type BoxFuture<T, E> = Pin<Box<dyn Future<Output = std::result::Result<T, E>> + Send + 'static>>;
#[tonic::async_trait]
+2 -2
View File
@@ -69,7 +69,7 @@ impl test_server::Test for Svc {
}
type CompressOutputServerStreamStream =
Pin<Box<dyn Stream<Item = Result<SomeData, Status>> + Send + Sync + 'static>>;
Pin<Box<dyn Stream<Item = Result<SomeData, Status>> + Send + 'static>>;
async fn compress_output_server_stream(
&self,
@@ -110,7 +110,7 @@ impl test_server::Test for Svc {
}
type CompressInputOutputBidirectionalStreamStream =
Pin<Box<dyn Stream<Item = Result<SomeData, Status>> + Send + Sync + 'static>>;
Pin<Box<dyn Stream<Item = Result<SomeData, Status>> + Send + 'static>>;
async fn compress_input_output_bidirectional_stream(
&self,
+2 -1
View File
@@ -12,14 +12,15 @@ version = "0.1.0"
bytes = "1.0"
futures-util = "0.3"
prost = "0.9"
tokio = {version = "1.0", features = ["macros", "rt-multi-thread", "net"]}
tonic = {path = "../../tonic"}
[dev-dependencies]
async-stream = "0.3"
futures = "0.3"
http = "0.2"
http-body = "0.4"
hyper = "0.14"
tokio = {version = "1.0", features = ["macros", "rt-multi-thread", "net"]}
tokio-stream = {version = "0.1.5", features = ["net"]}
tower = {version = "0.4", features = []}
tower-service = "0.3"
+51
View File
@@ -2,3 +2,54 @@ pub mod pb {
tonic::include_proto!("test");
tonic::include_proto!("stream");
}
pub mod mock {
use std::{
pin::Pin,
task::{Context, Poll},
};
use tokio::io::{AsyncRead, AsyncWrite, ReadBuf};
use tonic::transport::server::Connected;
#[derive(Debug)]
pub struct MockStream(pub tokio::io::DuplexStream);
impl Connected for MockStream {
type ConnectInfo = ();
/// Create type holding information about the connection.
fn connect_info(&self) -> Self::ConnectInfo {}
}
impl AsyncRead for MockStream {
fn poll_read(
mut self: Pin<&mut Self>,
cx: &mut Context<'_>,
buf: &mut ReadBuf<'_>,
) -> Poll<std::io::Result<()>> {
Pin::new(&mut self.0).poll_read(cx, buf)
}
}
impl AsyncWrite for MockStream {
fn poll_write(
mut self: Pin<&mut Self>,
cx: &mut Context<'_>,
buf: &[u8],
) -> Poll<std::io::Result<usize>> {
Pin::new(&mut self.0).poll_write(cx, buf)
}
fn poll_flush(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<std::io::Result<()>> {
Pin::new(&mut self.0).poll_flush(cx)
}
fn poll_shutdown(
mut self: Pin<&mut Self>,
cx: &mut Context<'_>,
) -> Poll<std::io::Result<()>> {
Pin::new(&mut self.0).poll_shutdown(cx)
}
}
}
+4 -55
View File
@@ -1,6 +1,7 @@
use bytes::Bytes;
use futures_util::FutureExt;
use http::Uri;
use integration_tests::mock::MockStream;
use integration_tests::pb::{
test_client, test_server, test_stream_client, test_stream_server, Input, InputStream, Output,
OutputStream,
@@ -125,9 +126,8 @@ async fn status_with_metadata() {
jh.await.unwrap();
}
type Stream<T> = std::pin::Pin<
Box<dyn futures::Stream<Item = std::result::Result<T, Status>> + Send + Sync + 'static>,
>;
type Stream<T> =
std::pin::Pin<Box<dyn futures::Stream<Item = std::result::Result<T, Status>> + Send + 'static>>;
#[tokio::test]
async fn status_from_server_stream() {
@@ -184,7 +184,7 @@ async fn status_from_server_stream_with_source() {
let channel = Endpoint::try_from("http://[::]:50051")
.unwrap()
.connect_with_connector_lazy(tower::service_fn(move |_: Uri| async move {
Err::<mock::MockStream, _>(std::io::Error::new(std::io::ErrorKind::Other, "WTF"))
Err::<MockStream, _>(std::io::Error::new(std::io::ErrorKind::Other, "WTF"))
}))
.unwrap();
@@ -201,54 +201,3 @@ fn trace_init() {
.with_env_filter(tracing_subscriber::EnvFilter::from_default_env())
.try_init();
}
mod mock {
use std::{
pin::Pin,
task::{Context, Poll},
};
use tokio::io::{AsyncRead, AsyncWrite, ReadBuf};
use tonic::transport::server::Connected;
#[derive(Debug)]
pub struct MockStream(pub tokio::io::DuplexStream);
impl Connected for MockStream {
type ConnectInfo = ();
/// Create type holding information about the connection.
fn connect_info(&self) -> Self::ConnectInfo {}
}
impl AsyncRead for MockStream {
fn poll_read(
mut self: Pin<&mut Self>,
cx: &mut Context<'_>,
buf: &mut ReadBuf<'_>,
) -> Poll<std::io::Result<()>> {
Pin::new(&mut self.0).poll_read(cx, buf)
}
}
impl AsyncWrite for MockStream {
fn poll_write(
mut self: Pin<&mut Self>,
cx: &mut Context<'_>,
buf: &[u8],
) -> Poll<std::io::Result<usize>> {
Pin::new(&mut self.0).poll_write(cx, buf)
}
fn poll_flush(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<std::io::Result<()>> {
Pin::new(&mut self.0).poll_flush(cx)
}
fn poll_shutdown(
mut self: Pin<&mut Self>,
cx: &mut Context<'_>,
) -> Poll<std::io::Result<()>> {
Pin::new(&mut self.0).poll_shutdown(cx)
}
}
}
+47
View File
@@ -0,0 +1,47 @@
use futures::FutureExt;
use integration_tests::pb::{test_stream_server, InputStream, OutputStream};
use tonic::{transport::Server, Request, Response, Status};
type Stream<T> =
std::pin::Pin<Box<dyn futures::Stream<Item = std::result::Result<T, Status>> + Send + 'static>>;
#[tokio::test]
async fn status_from_server_stream_with_source() {
struct Svc;
#[tonic::async_trait]
impl test_stream_server::TestStream for Svc {
type StreamCallStream = Stream<OutputStream>;
async fn stream_call(
&self,
_: Request<InputStream>,
) -> Result<Response<Self::StreamCallStream>, Status> {
let s = Unsync(0 as *mut ());
Ok(Response::new(Box::pin(s) as Self::StreamCallStream))
}
}
let svc = test_stream_server::TestStreamServer::new(Svc);
Server::builder()
.add_service(svc)
.serve("127.0.0.1:1339".parse().unwrap())
.now_or_never();
}
struct Unsync(*mut ());
unsafe impl Send for Unsync {}
impl futures::Stream for Unsync {
type Item = Result<OutputStream, Status>;
fn poll_next(
self: std::pin::Pin<&mut Self>,
_cx: &mut std::task::Context<'_>,
) -> std::task::Poll<Option<Self::Item>> {
unimplemented!()
}
}
+5 -5
View File
@@ -57,7 +57,7 @@ pub fn generate<T: Service>(
impl<T> #service_ident<T>
where
T: tonic::client::GrpcService<tonic::body::BoxBody>,
T::ResponseBody: Body + Send + Sync + 'static,
T::ResponseBody: Body + Send + 'static,
T::Error: Into<StdError>,
<T::ResponseBody as Body>::Error: Into<StdError> + Send,
{
@@ -203,8 +203,8 @@ fn generate_server_streaming<T: Method>(
tonic::Status::new(tonic::Code::Unknown, format!("Service was not ready: {}", e.into()))
})?;
let codec = #codec_name::default();
let path = http::uri::PathAndQuery::from_static(#path);
self.inner.server_streaming(request.into_request(), path, codec).await
let path = http::uri::PathAndQuery::from_static(#path);
self.inner.server_streaming(request.into_request(), path, codec).await
}
}
}
@@ -255,8 +255,8 @@ fn generate_streaming<T: Method>(
tonic::Status::new(tonic::Code::Unknown, format!("Service was not ready: {}", e.into()))
})?;
let codec = #codec_name::default();
let path = http::uri::PathAndQuery::from_static(#path);
self.inner.streaming(request.into_streaming_request(), path, codec).await
let path = http::uri::PathAndQuery::from_static(#path);
self.inner.streaming(request.into_streaming_request(), path, codec).await
}
}
}
+3 -3
View File
@@ -115,7 +115,7 @@ pub fn generate<T: Service>(
impl<T, B> tonic::codegen::Service<http::Request<B>> for #server_service<T>
where
T: #server_trait,
B: Body + Send + Sync + 'static,
B: Body + Send + 'static,
B::Error: Into<StdError> + Send + 'static,
{
type Response = http::Response<tonic::body::BoxBody>;
@@ -232,7 +232,7 @@ fn generate_trait_methods<T: Service>(
quote! {
#stream_doc
type #stream: futures_core::Stream<Item = Result<#res_message, tonic::Status>> + Send + Sync + 'static;
type #stream: futures_core::Stream<Item = Result<#res_message, tonic::Status>> + Send + 'static;
#method_doc
async fn #name(&self, request: tonic::Request<#req_message>)
@@ -248,7 +248,7 @@ fn generate_trait_methods<T: Service>(
quote! {
#stream_doc
type #stream: futures_core::Stream<Item = Result<#res_message, tonic::Status>> + Send + Sync + 'static;
type #stream: futures_core::Stream<Item = Result<#res_message, tonic::Status>> + Send + 'static;
#method_doc
async fn #name(&self, request: tonic::Request<tonic::Streaming<#req_message>>)
+1 -1
View File
@@ -133,7 +133,7 @@ impl Health for HealthService {
}
type WatchStream =
Pin<Box<dyn Stream<Item = Result<HealthCheckResponse, Status>> + Send + Sync + 'static>>;
Pin<Box<dyn Stream<Item = Result<HealthCheckResponse, Status>> + Send + 'static>>;
async fn watch(
&self,
+1 -1
View File
@@ -9,7 +9,7 @@ pub mod pb {
tonic::include_proto!("test");
}
type BoxStream<T> = Pin<Box<dyn Stream<Item = Result<T, Status>> + Send + Sync + 'static>>;
type BoxStream<T> = Pin<Box<dyn Stream<Item = Result<T, Status>> + Send + 'static>>;
pub struct Svc;
+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;