fix(tonic): Remove Sync requirement for streams (#804)
This commit is contained in:
+21
-26
@@ -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",
|
||||
]
|
||||
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 {}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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>> {
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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 {}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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]
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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!()
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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>>)
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
@@ -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
@@ -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()
|
||||
}
|
||||
|
||||
@@ -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
@@ -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);
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user