Upgrade to Tokio 1.0.0 ecosystem (#530)

* Upgrade Tonic to Tokio 1.0

Work in progress for updating Tonic to Tokio 1.0. Since tower has not
been released to crates.io, a git dependency is taken instead.

* Upgrade Tonic to Tokio 1.0 phase 2

* tonic: remove tower-* deps

* Apply suggestions from code review

Co-authored-by: Ed Marshall <[email protected]>
Co-authored-by: Lucio Franco <[email protected]>
This commit is contained in:
Quentin Perez
2021-01-11 12:18:34 -05:00
committed by GitHub
co-authored by Ed Marshall Lucio Franco
parent fe4d5b9d9a
commit fdda5ae26a
42 changed files with 185 additions and 185 deletions
+11 -10
View File
@@ -148,28 +148,29 @@ path = "src/hyper_warp_multiplex/server.rs"
[dependencies]
tonic = { path = "../tonic", features = ["tls"] }
prost = "0.6"
tokio = { version = "0.2", features = ["rt-threaded", "time", "stream", "fs", "macros", "uds"] }
prost = "0.7"
tokio = { version = "1.0", features = ["rt-multi-thread", "time", "fs", "macros", "net"] }
tokio-stream = { version = "0.1", features = ["net"] }
async-stream = "0.3"
futures = { version = "0.3", default-features = false, features = ["alloc"] }
async-stream = "0.2"
tower = "0.3"
tower = { version = "0.4" }
# Required for routeguide
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
rand = "0.7"
rand = "0.8"
# Tracing
tracing = "0.1.16"
tracing-subscriber = { version = "0.2", features = ["tracing-log"] }
tracing-attributes = "0.1"
tracing-futures = "0.2"
# Required for wellknown types
prost-types = "0.6"
prost-types = "0.7"
# Hyper example
hyper = "0.13"
warp = { version = "0.2", default-features = false }
hyper = "0.14"
warp = { git = "https://github.com/aknuds1/warp", branch = "chore/upgrade-tokio", default-features = false }
http = "0.2"
http-body = "0.3"
pin-project = "0.4.17"
http-body = "0.4"
pin-project = "1.0"
# Health example
tonic-health = { path = "../tonic-health" }
listenfd = "0.3"
+3 -3
View File
@@ -702,7 +702,7 @@ use futures_util::stream;
```rust
async fn run_record_route(client: &mut RouteGuideClient<Channel>) -> Result<(), Box<dyn Error>> {
let mut rng = rand::thread_rng();
let point_count: i32 = rng.gen_range(2, 100);
let point_count: i32 = rng.gen_range(2..100);
let mut points = vec![];
for _ in 0..=point_count {
@@ -723,8 +723,8 @@ async fn run_record_route(client: &mut RouteGuideClient<Channel>) -> Result<(),
```rust
fn random_point(rng: &mut ThreadRng) -> Point {
let latitude = (rng.gen_range(0, 180) - 90) * 10_000_000;
let longitude = (rng.gen_range(0, 360) - 180) * 10_000_000;
let latitude = (rng.gen_range(0..180) - 90) * 10_000_000;
let longitude = (rng.gen_range(0..360) - 180) * 10_000_000;
Point {
latitude,
longitude,
+4 -2
View File
@@ -36,9 +36,11 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
match listenfd::ListenFd::from_env().take_tcp_listener(0)? {
Some(listener) => {
let mut listener = tokio::net::TcpListener::from_std(listener)?;
let listener = tokio_stream::wrappers::TcpListenerStream::new(
tokio::net::TcpListener::from_std(listener)?,
);
server.serve_with_incoming(listener.incoming()).await?;
server.serve_with_incoming(listener).await?;
}
None => {
server.serve(addr).await?;
+1 -5
View File
@@ -24,11 +24,7 @@ impl BlockingClient {
D: std::convert::TryInto<tonic::transport::Endpoint>,
D::Error: Into<StdError>,
{
let mut rt = Builder::new()
.basic_scheduler()
.enable_all()
.build()
.unwrap();
let rt = Builder::new_multi_thread().enable_all().build().unwrap();
let client = rt.block_on(GreeterClient::connect(dst))?;
Ok(Self { rt, client })
+8 -8
View File
@@ -18,42 +18,42 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
let e1 = Endpoint::from_static("http://[::1]:50051");
let e2 = Endpoint::from_static("http://[::1]:50052");
let (channel, mut rx) = Channel::balance_channel(10);
let (channel, rx) = Channel::balance_channel(10);
let mut client = EchoClient::new(channel);
let done = Arc::new(AtomicBool::new(false));
let demo_done = done.clone();
tokio::spawn(async move {
tokio::time::delay_for(tokio::time::Duration::from_secs(5)).await;
tokio::time::sleep(tokio::time::Duration::from_secs(5)).await;
println!("Added first endpoint");
let change = Change::Insert("1", e1);
let res = rx.send(change).await;
println!("{:?}", res);
tokio::time::delay_for(tokio::time::Duration::from_secs(5)).await;
tokio::time::sleep(tokio::time::Duration::from_secs(5)).await;
println!("Added second endpoint");
let change = Change::Insert("2", e2);
let res = rx.send(change).await;
println!("{:?}", res);
tokio::time::delay_for(tokio::time::Duration::from_secs(5)).await;
tokio::time::sleep(tokio::time::Duration::from_secs(5)).await;
println!("Removed first endpoint");
let change = Change::Remove("1");
let res = rx.send(change).await;
println!("{:?}", res);
tokio::time::delay_for(tokio::time::Duration::from_secs(5)).await;
tokio::time::sleep(tokio::time::Duration::from_secs(5)).await;
println!("Removed second endpoint");
let change = Change::Remove("2");
let res = rx.send(change).await;
println!("{:?}", res);
tokio::time::delay_for(tokio::time::Duration::from_secs(5)).await;
tokio::time::sleep(tokio::time::Duration::from_secs(5)).await;
println!("Added third endpoint");
let e3 = Endpoint::from_static("http://[::1]:50051");
let change = Change::Insert("3", e3);
let res = rx.send(change).await;
println!("{:?}", res);
tokio::time::delay_for(tokio::time::Duration::from_secs(5)).await;
tokio::time::sleep(tokio::time::Duration::from_secs(5)).await;
println!("Removed third endpoint");
let change = Change::Remove("3");
let res = rx.send(change).await;
@@ -62,7 +62,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
});
while !done.load(SeqCst) {
tokio::time::delay_for(tokio::time::Duration::from_millis(500)).await;
tokio::time::sleep(tokio::time::Duration::from_millis(500)).await;
let request = tonic::Request::new(EchoRequest {
message: "hello".into(),
});
+1 -2
View File
@@ -3,7 +3,6 @@ use tonic::{transport::Server, Request, Response, Status};
use hello_world::greeter_server::{Greeter, GreeterServer};
use hello_world::{HelloReply, HelloRequest};
use std::time::Duration;
use tokio::time::delay_for;
use tonic_health::server::HealthReporter;
pub mod hello_world {
@@ -34,7 +33,7 @@ async fn twiddle_service_status(mut reporter: HealthReporter) {
let mut iter = 0u64;
loop {
iter += 1;
delay_for(Duration::from_secs(1)).await;
tokio::time::sleep(Duration::from_secs(1)).await;
if iter % 2 == 0 {
reporter.set_serving::<GreeterServer<MyGreeter>>().await;
+3 -3
View File
@@ -41,7 +41,7 @@ async fn print_features(client: &mut RouteGuideClient<Channel>) -> Result<(), Bo
async fn run_record_route(client: &mut RouteGuideClient<Channel>) -> Result<(), Box<dyn Error>> {
let mut rng = rand::thread_rng();
let point_count: i32 = rng.gen_range(2, 100);
let point_count: i32 = rng.gen_range(2..100);
let mut points = vec![];
for _ in 0..=point_count {
@@ -115,8 +115,8 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
}
fn random_point(rng: &mut ThreadRng) -> Point {
let latitude = (rng.gen_range(0, 180) - 90) * 10_000_000;
let longitude = (rng.gen_range(0, 360) - 180) * 10_000_000;
let latitude = (rng.gen_range(0..180) - 90) * 10_000_000;
let longitude = (rng.gen_range(0..360) - 180) * 10_000_000;
Point {
latitude,
longitude,
+6 -3
View File
@@ -36,7 +36,8 @@ impl RouteGuide for RouteGuideService {
Ok(Response::new(Feature::default()))
}
type ListFeaturesStream = mpsc::Receiver<Result<Feature, Status>>;
type ListFeaturesStream =
Pin<Box<dyn Stream<Item = Result<Feature, Status>> + Send + Sync + 'static>>;
async fn list_features(
&self,
@@ -44,7 +45,7 @@ impl RouteGuide for RouteGuideService {
) -> Result<Response<Self::ListFeaturesStream>, Status> {
println!("ListFeatures = {:?}", request);
let (mut tx, rx) = mpsc::channel(4);
let (tx, rx) = mpsc::channel(4);
let features = self.features.clone();
tokio::spawn(async move {
@@ -58,7 +59,9 @@ impl RouteGuide for RouteGuideService {
println!(" /// done sending");
});
Ok(Response::new(rx))
Ok(Response::new(Box::pin(
tokio_stream::wrappers::ReceiverStream::new(rx),
)))
}
async fn record_route(
+2 -2
View File
@@ -1,5 +1,5 @@
use std::time::Duration;
use tokio::time::delay_for;
use tokio::time::sleep;
use tonic::{transport::Server, Request, Response, Status};
use hello_world::greeter_server::{Greeter, GreeterServer};
@@ -20,7 +20,7 @@ impl Greeter for MyGreeter {
) -> Result<Response<HelloReply>, Status> {
println!("Got a request from {:?}", request.remote_addr());
delay_for(Duration::from_millis(5000)).await;
sleep(Duration::from_millis(5000)).await;
let reply = hello_world::HelloReply {
message: format!("Hello {}!", request.into_inner().name),
+15 -7
View File
@@ -1,6 +1,6 @@
#![cfg_attr(not(unix), allow(unused_imports))]
use futures::stream::TryStreamExt;
use futures::TryFutureExt;
use std::path::Path;
#[cfg(unix)]
use tokio::net::UnixListener;
@@ -40,13 +40,21 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
tokio::fs::create_dir_all(Path::new(path).parent().unwrap()).await?;
let mut uds = UnixListener::bind(path)?;
let greeter = MyGreeter::default();
let incoming = {
let uds = UnixListener::bind(path)?;
async_stream::stream! {
while let item = uds.accept().map_ok(|(st, _)| unix::UnixStream(st)).await {
yield item;
}
}
};
Server::builder()
.add_service(GreeterServer::new(greeter))
.serve_with_incoming(uds.incoming().map_ok(unix::UnixStream))
.serve_with_incoming(incoming)
.await?;
Ok(())
@@ -59,7 +67,7 @@ mod unix {
task::{Context, Poll},
};
use tokio::io::{AsyncRead, AsyncWrite};
use tokio::io::{AsyncRead, AsyncWrite, ReadBuf};
use tonic::transport::server::Connected;
#[derive(Debug)]
@@ -71,8 +79,8 @@ mod unix {
fn poll_read(
mut self: Pin<&mut Self>,
cx: &mut Context<'_>,
buf: &mut [u8],
) -> Poll<std::io::Result<usize>> {
buf: &mut ReadBuf<'_>,
) -> Poll<std::io::Result<()>> {
Pin::new(&mut self.0).poll_read(cx, buf)
}
}
+12 -11
View File
@@ -15,23 +15,24 @@ name = "server"
path = "src/bin/server.rs"
[dependencies]
tokio = { version = "0.2", features = ["rt-threaded", "time", "macros", "stream", "fs"] }
tokio = { version = "1.0", features = ["rt-multi-thread", "time", "macros", "fs"] }
tokio-stream = "0.1"
async-stream = "0.3"
tonic = { path = "../tonic", features = ["tls"] }
prost = "0.6"
prost-derive = "0.6"
bytes = "0.5"
prost = "0.7"
prost-derive = "0.7"
bytes = "1.0"
http = "0.2"
futures-core = "0.3"
futures-util = "0.3"
async-stream = "0.2"
tower = "0.3"
http-body = "0.3"
hyper = "0.13"
console = "0.9"
tower = { version = "0.4" }
http-body = "0.4"
hyper = "0.14"
console = "0.14"
structopt = "0.3"
tracing = "0.1"
tracing-subscriber = "0.2.0-alpha"
tracing-log = "0.1.0"
tracing-subscriber = "0.2"
tracing-log = "0.1"
[build-dependencies]
tonic-build = { path = "../tonic-build", features = ["prost"] }
+5 -1
View File
@@ -154,7 +154,11 @@ pub async fn ping_pong(client: &mut TestClient, assertions: &mut Vec<TestAsserti
let (tx, rx) = mpsc::unbounded_channel();
tx.send(make_ping_pong_request(0)).unwrap();
let result = client.full_duplex_call(Request::new(rx)).await;
let result = client
.full_duplex_call(Request::new(
tokio_stream::wrappers::UnboundedReceiverStream::new(rx),
))
.await;
assertions.push(test_assert!(
"call must be successful",
+1 -4
View File
@@ -68,10 +68,7 @@ pub enum TestAssertion {
impl TestAssertion {
pub fn is_failed(&self) -> bool {
match self {
TestAssertion::Failed { .. } => true,
_ => false,
}
matches!(self, TestAssertion::Failed { .. })
}
}
+3 -3
View File
@@ -72,7 +72,7 @@ impl pb::test_service_server::TestService for TestService {
let stream = try_stream! {
for param in response_parameters {
tokio::time::delay_for(Duration::from_micros(param.interval_us as u64)).await;
tokio::time::sleep(Duration::from_micros(param.interval_us as u64)).await;
let payload = crate::server_payload(param.size as usize);
yield StreamingOutputCallResponse { payload: Some(payload) };
@@ -90,7 +90,7 @@ impl pb::test_service_server::TestService for TestService {
) -> Result<StreamingInputCallResponse> {
let mut stream = req.into_inner();
let mut aggregated_payload_size = 0 as i32;
let mut aggregated_payload_size = 0;
while let Some(msg) = stream.try_next().await? {
aggregated_payload_size += msg.payload.unwrap().body.len() as i32;
}
@@ -127,7 +127,7 @@ impl pb::test_service_server::TestService for TestService {
}
for param in msg.response_parameters {
tokio::time::delay_for(Duration::from_micros(param.interval_us as u64)).await;
tokio::time::sleep(Duration::from_micros(param.interval_us as u64)).await;
let payload = crate::server_payload(param.size as usize);
yield StreamingOutputCallResponse { payload: Some(payload) };
+1 -1
View File
@@ -10,7 +10,7 @@ license = "MIT"
[dependencies]
tonic = { path= "../../tonic" }
prost = "0.6"
prost = "0.7"
[build-dependencies]
tonic-build = { path= "../../tonic-build" }
+2 -2
View File
@@ -10,8 +10,8 @@ license = "MIT"
[dependencies]
tonic = { path= "../../../tonic" }
prost = "0.6"
prost-types = "0.6"
prost = "0.7"
prost-types = "0.7"
uuid = { package = "uuid1", path= "../uuid" }
[build-dependencies]
+3 -3
View File
@@ -9,7 +9,7 @@ license = "MIT"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
prost = "0.6"
bytes = "0.5"
prost = "0.7"
bytes = "1.0"
[build-dependencies]
prost-build = "0.6"
prost-build = "0.7"
+1 -1
View File
@@ -10,7 +10,7 @@ license = "MIT"
[dependencies]
tonic = { path = "../../tonic" }
prost = "0.6"
prost = "0.7"
[build-dependencies]
tonic-build = { path = "../../tonic-build" }
+3 -3
View File
@@ -10,12 +10,12 @@ license = "MIT"
[dependencies]
tonic = { path = "../../tonic" }
prost = "0.6"
prost = "0.7"
futures-util = "0.3"
bytes = "0.5"
bytes = "1.0"
[dev-dependencies]
tokio = { version = "0.2", features = ["macros", "rt-core", "tcp"] }
tokio = { version = "1.0", features = ["macros", "rt-multi-thread", "net"] }
[build-dependencies]
tonic-build = { path = "../../tonic-build" }
+4 -4
View File
@@ -41,14 +41,14 @@ async fn connect_returns_err_via_call_after_connected() {
.unwrap();
});
tokio::time::delay_for(Duration::from_millis(100)).await;
tokio::time::sleep(Duration::from_millis(100)).await;
let mut client = TestClient::connect("http://127.0.0.1:1338").await.unwrap();
// First call should pass, then shutdown the server
client.unary_call(Request::new(Input {})).await.unwrap();
tokio::time::delay_for(Duration::from_millis(100)).await;
tokio::time::sleep(Duration::from_millis(100)).await;
let res = client.unary_call(Request::new(Input {})).await;
@@ -81,11 +81,11 @@ async fn connect_lazy_reconnects_after_first_failure() {
.unwrap();
});
tokio::time::delay_for(Duration::from_millis(100)).await;
tokio::time::sleep(Duration::from_millis(100)).await;
client.unary_call(Request::new(Input {})).await.unwrap();
// The server shut down, third call should fail
tokio::time::delay_for(Duration::from_millis(100)).await;
tokio::time::sleep(Duration::from_millis(100)).await;
client.unary_call(Request::new(Input {})).await.unwrap_err();
jh.await.unwrap();
+2 -2
View File
@@ -33,7 +33,7 @@ async fn status_with_details() {
.unwrap();
});
tokio::time::delay_for(Duration::from_millis(100)).await;
tokio::time::sleep(Duration::from_millis(100)).await;
let mut channel = test_client::TestClient::connect("http://127.0.0.1:1337")
.await
@@ -87,7 +87,7 @@ async fn status_with_metadata() {
.unwrap();
});
tokio::time::delay_for(Duration::from_millis(100)).await;
tokio::time::sleep(Duration::from_millis(100)).await;
let mut channel = test_client::TestClient::connect("http://127.0.0.1:1338")
.await
+1 -1
View File
@@ -33,7 +33,7 @@ async fn writes_user_agent_header() {
.unwrap();
});
tokio::time::delay_for(Duration::from_millis(100)).await;
tokio::time::sleep(Duration::from_millis(100)).await;
let channel = Endpoint::from_static("http://127.0.0.1:1322")
.user_agent("my-client")
+1 -1
View File
@@ -10,7 +10,7 @@ license = "MIT"
[dependencies]
tonic = { path = "../../tonic" }
prost = "0.6"
prost = "0.7"
[build-dependencies]
tonic-build = { path = "../../tonic-build" }
+2 -2
View File
@@ -10,8 +10,8 @@ license = "MIT"
[dependencies]
tonic = { path = "../../tonic" }
prost = "0.6"
prost-types = "0.6"
prost = "0.7"
prost-types = "0.7"
[build-dependencies]
tonic-build = { path = "../../tonic-build" }
+1 -1
View File
@@ -16,7 +16,7 @@ keywords = ["rpc", "grpc", "async", "codegen", "protobuf"]
[dependencies]
prost-build = { version = "0.6", optional = true }
prost-build = { version = "0.7", optional = true }
syn = "1.0"
quote = "1.0"
proc-macro2 = "1.0"
+8 -5
View File
@@ -18,12 +18,15 @@ default = ["transport"]
transport = ["tonic/transport"]
[dependencies]
tokio = { version = "0.2", features = ["sync", "stream"] }
tonic = { version = "0.3", path = "../tonic", features = ["codegen", "prost"] }
prost = "0.6"
tokio = { version = "1.0", features = ["sync"] }
tonic = { path = "../tonic", features = ["codegen", "prost"] }
bytes = "1.0"
prost = "0.7"
tokio-stream = "0.1"
async-stream = "0.3"
[dev-dependencies]
tokio = { version = "0.2", features = ["rt-core", "macros"]}
tokio = { version = "1.0", features = ["rt-multi-thread", "macros"]}
[build-dependencies]
tonic-build = { version = "0.3", path = "../tonic-build" }
tonic-build = { path = "../tonic-build" }
+21 -22
View File
@@ -6,8 +6,8 @@ use crate::ServingStatus;
use std::collections::HashMap;
use std::pin::Pin;
use std::sync::Arc;
use tokio::stream::{Stream, StreamExt};
use tokio::sync::{watch, RwLock};
use tokio_stream::Stream;
#[cfg(feature = "transport")]
use tonic::transport::NamedService;
use tonic::{Request, Response, Status};
@@ -80,20 +80,15 @@ impl HealthReporter {
let service_name = service_name.as_ref();
let mut writer = self.statuses.write().await;
match writer.get(service_name) {
None => {
let _ = writer.insert(service_name.to_string(), watch::channel(status));
}
Some((tx, rx)) => {
let mut rx = rx.clone();
if rx.recv().await == Some(status) {
return;
}
Some((tx, _)) => {
// We only ever hand out clones of the receiver, so the originally-created
// receiver should always be present, only being dropped when clearing the
// service status. Consequently, `tx.broadcast` should not fail, making use
// service status. Consequently, `tx.send` should not fail, making use
// of `expect` here safe.
tx.broadcast(status).expect("channel should not be closed");
tx.send(status).expect("channel should not be closed");
}
None => {
writer.insert(service_name.to_string(), watch::channel(status));
}
};
}
@@ -116,10 +111,7 @@ impl HealthService {
async fn service_health(&self, service_name: &str) -> Option<ServingStatus> {
let reader = self.statuses.read().await;
match reader.get(service_name).map(|p| p.1.clone()) {
None => None,
Some(mut receiver) => receiver.recv().await,
}
reader.get(service_name).map(|p| *p.1.borrow())
}
}
@@ -148,15 +140,21 @@ impl Health for HealthService {
request: Request<HealthCheckRequest>,
) -> Result<Response<Self::WatchStream>, Status> {
let service_name = request.get_ref().service.as_str();
let status_rx = match self.statuses.read().await.get(service_name) {
let mut status_rx = match self.statuses.read().await.get(service_name) {
None => return Err(Status::not_found("service not registered")),
Some(pair) => pair.1.clone(),
};
let output = status_rx.map(|status| {
let status = crate::proto::health_check_response::ServingStatus::from(status) as i32;
Ok(HealthCheckResponse { status })
});
let output = async_stream::try_stream! {
// yield the current value
let status = crate::proto::health_check_response::ServingStatus::from(*status_rx.borrow()) as i32;
yield HealthCheckResponse { status };
while let Ok(_) = status_rx.changed().await {
let status = crate::proto::health_check_response::ServingStatus::from(*status_rx.borrow()) as i32;
yield HealthCheckResponse { status };
}
};
Ok(Response::new(Box::pin(output) as Self::WatchStream))
}
@@ -170,8 +168,8 @@ mod tests {
use crate::ServingStatus;
use std::collections::HashMap;
use std::sync::Arc;
use tokio::stream::StreamExt;
use tokio::sync::{watch, RwLock};
use tokio_stream::StreamExt;
use tonic::{Code, Request, Status};
fn assert_serving_status(wire: i32, expected: ServingStatus) {
@@ -269,6 +267,7 @@ mod tests {
reporter
.set_service_status("TestService", ServingStatus::NotServing)
.await;
let item = resp
.next()
.await
+3 -3
View File
@@ -15,8 +15,8 @@ categories = ["web-programming", "network-programming", "asynchronous"]
keywords = ["rpc", "grpc", "protobuf"]
[dependencies]
prost = "0.6"
prost-types = "0.6"
prost = "0.7"
prost-types = "0.7"
[build-dependencies]
prost-build = "0.6"
prost-build = "0.7"
+18 -23
View File
@@ -30,8 +30,6 @@ transport = [
"hyper",
"tokio",
"tower",
"tower-balance",
"tower-load",
"tracing-futures",
]
tls = ["transport", "tokio-rustls"]
@@ -43,45 +41,43 @@ prost = ["prost1", "prost-derive"]
# harness = false
[dependencies]
bytes = "0.5"
bytes = "1.0"
futures-core = { version = "0.3", default-features = false }
futures-util = { version = "0.3", default-features = false }
tracing = "0.1"
http = "0.2"
base64 = "0.12"
base64 = "0.13"
percent-encoding = "2.0"
percent-encoding = "2.1"
tower-service = "0.3"
tokio-util = { version = "0.3", features = ["codec"] }
async-stream = "0.2"
http-body = "0.3"
pin-project = "0.4.17"
tokio-util = { version = "0.6", features = ["codec"] }
async-stream = "0.3"
http-body = "0.4"
pin-project = "1.0"
# prost
prost1 = { package = "prost", version = "0.6", optional = true }
prost-derive = { version = "0.6", optional = true }
prost1 = { package = "prost", version = "0.7", optional = true }
prost-derive = { version = "0.7", optional = true }
# codegen
async-trait = { version = "0.1.13", optional = true }
# transport
h2 = { version = "0.2.2", optional = true }
hyper = { version = "0.13.4", features = ["stream"], optional = true }
tokio = { version = "0.2.13", features = ["tcp"], optional = true }
tower = { version = "0.3", optional = true}
tower-make = { version = "0.3", features = ["connect"] }
tower-balance = { version = "0.3", optional = true }
tower-load = { version = "0.3", optional = true }
h2 = { version = "0.3", optional = true }
hyper = { version = "0.14.2", features = ["full"], optional = true }
tokio = { version = "1.0.1", features = ["net"], optional = true }
tokio-stream = "0.1"
tower = { version = "0.4", features = ["balance", "buffer", "discover", "limit", "load", "make", "timeout", "util"], optional = true}
tracing-futures = { version = "0.2", optional = true }
# rustls
tokio-rustls = { version = "0.14", optional = true }
rustls-native-certs = { version = "0.4", optional = true }
tokio-rustls = { version = "0.22", optional = true }
rustls-native-certs = { version = "0.5", optional = true }
[dev-dependencies]
tokio = { version = "0.2", features = ["rt-core", "macros"] }
tokio = { version = "1.0", features = ["rt", "macros"] }
static_assertions = "1.0"
rand = "0.7"
rand = "0.8"
bencher = "0.1.5"
[package.metadata.docs.rs]
@@ -91,4 +87,3 @@ rustdoc-args = ["--cfg", "docsrs"]
[[bench]]
name = "decode"
harness = false
+2 -3
View File
@@ -11,8 +11,7 @@ use tonic::{codec::DecodeBuf, codec::Decoder, Status, Streaming};
macro_rules! bench {
($name:ident, $message_size:expr, $chunk_size:expr, $message_count:expr) => {
fn $name(b: &mut Bencher) {
let mut rt = tokio::runtime::Builder::new()
.basic_scheduler()
let rt = tokio::runtime::Builder::new_multi_thread()
.build()
.expect("runtime");
@@ -102,7 +101,7 @@ impl Decoder for MockDecoder {
type Error = Status;
fn decode(&mut self, buf: &mut DecodeBuf<'_>) -> Result<Option<Self::Item>, Self::Error> {
let out = Vec::from(buf.bytes());
let out = Vec::from(buf.chunk());
buf.advance(self.message_size);
Ok(Some(out))
}
+1 -1
View File
@@ -160,7 +160,7 @@ where
Pin::new_unchecked(&mut me.0).poll_data(cx)
};
match futures_util::ready!(v) {
Some(Ok(mut i)) => Poll::Ready(Some(Ok(i.to_bytes()))),
Some(Ok(mut i)) => Poll::Ready(Some(Ok(i.copy_to_bytes(i.remaining())))),
Some(Err(e)) => {
let err = Status::map_error(e.into());
Poll::Ready(Some(Err(err)))
+9 -9
View File
@@ -1,5 +1,5 @@
use bytes::buf::UninitSlice;
use bytes::{Buf, BufMut, BytesMut};
use std::mem::MaybeUninit;
/// A specialized buffer to decode gRPC messages from.
#[derive(Debug)]
@@ -27,8 +27,8 @@ impl Buf for DecodeBuf<'_> {
}
#[inline]
fn bytes(&self) -> &[u8] {
let ret = self.buf.bytes();
fn chunk(&self) -> &[u8] {
let ret = self.buf.chunk();
if ret.len() > self.len {
&ret[..self.len]
@@ -63,7 +63,7 @@ impl EncodeBuf<'_> {
}
}
impl BufMut for EncodeBuf<'_> {
unsafe impl BufMut for EncodeBuf<'_> {
#[inline]
fn remaining_mut(&self) -> usize {
self.buf.remaining_mut()
@@ -75,8 +75,8 @@ impl BufMut for EncodeBuf<'_> {
}
#[inline]
fn bytes_mut(&mut self) -> &mut [MaybeUninit<u8>] {
self.buf.bytes_mut()
fn chunk_mut(&mut self) -> &mut UninitSlice {
self.buf.chunk_mut()
}
}
@@ -92,7 +92,7 @@ mod tests {
assert_eq!(buf.len, 20);
assert_eq!(buf.remaining(), 20);
assert_eq!(buf.bytes().len(), 20);
assert_eq!(buf.chunk().len(), 20);
buf.advance(10);
assert_eq!(buf.remaining(), 10);
@@ -100,9 +100,9 @@ mod tests {
let mut out = [0; 5];
buf.copy_to_slice(&mut out);
assert_eq!(buf.remaining(), 5);
assert_eq!(buf.bytes().len(), 5);
assert_eq!(buf.chunk().len(), 5);
assert_eq!(buf.to_bytes().len(), 5);
assert_eq!(buf.copy_to_bytes(5).len(), 5);
assert!(!buf.has_remaining());
}
+1 -1
View File
@@ -15,7 +15,7 @@ use std::{
fmt,
time::Duration,
};
use tower_make::MakeConnection;
use tower::make::MakeConnection;
/// Channel builder.
///
+4 -4
View File
@@ -29,13 +29,13 @@ use tokio::{
sync::mpsc::{channel, Sender},
};
use tower::balance::p2c::Balance;
use tower::{
buffer::{self, Buffer},
discover::{Change, Discover},
util::{BoxService, Either},
Service,
};
use tower_balance::p2c::Balance;
type Svc = Either<Connection, BoxService<Request<BoxBody>, Response<hyper::Body>, crate::Error>>;
@@ -109,7 +109,7 @@ impl Channel {
/// This creates a [`Channel`] that will load balance accross all the
/// provided endpoints.
pub fn balance_list(list: impl Iterator<Item = Endpoint>) -> Self {
let (channel, mut tx) = Self::balance_channel(DEFAULT_BUFFER_SIZE);
let (channel, tx) = Self::balance_channel(DEFAULT_BUFFER_SIZE);
list.for_each(|endpoint| {
tx.try_send(Change::Insert(endpoint.uri.clone(), endpoint))
.unwrap();
@@ -166,9 +166,9 @@ impl Channel {
where
D: Discover<Service = Connection> + Unpin + Send + 'static,
D::Error: Into<crate::Error>,
D::Key: Send + Clone,
D::Key: Hash + Send + Clone,
{
let svc = Balance::from_entropy(discover);
let svc = Balance::new(discover);
let svc = BoxService::new(svc);
let svc = Buffer::new(Either::B(svc), buffer_size);
+2 -2
View File
@@ -105,8 +105,8 @@ where
fn poll_read(
self: Pin<&mut Self>,
cx: &mut Context<'_>,
buf: &mut [u8],
) -> Poll<std::io::Result<usize>> {
buf: &mut tokio::io::ReadBuf<'_>,
) -> Poll<std::io::Result<()>> {
use std::future::Future;
let pin = self.get_mut();
+1 -1
View File
@@ -163,7 +163,7 @@ impl Server {
/// ```
/// # use tonic::transport::Server;
/// # use tower_service::Service;
/// # let mut builder = Server::builder();
/// # let builder = Server::builder();
/// builder.concurrency_limit_per_connection(32);
/// ```
pub fn concurrency_limit_per_connection(self, limit: usize) -> Self {
+1 -1
View File
@@ -10,6 +10,7 @@ use std::{
task::{Context, Poll},
};
use tokio::io::{AsyncRead, AsyncWrite};
use tower::load::Load;
use tower::{
layer::Layer,
limit::{concurrency::ConcurrencyLimitLayer, rate::RateLimitLayer},
@@ -17,7 +18,6 @@ use tower::{
util::BoxService,
ServiceBuilder, ServiceExt,
};
use tower_load::Load;
use tower_service::Service;
pub(crate) type Request = http::Request<BoxBody>;
+1 -1
View File
@@ -4,7 +4,7 @@ use super::io::BoxedIo;
use super::tls::TlsConnector;
use http::Uri;
use std::task::{Context, Poll};
use tower_make::MakeConnection;
use tower::make::MakeConnection;
use tower_service::Service;
#[cfg(not(feature = "tls"))]
+9 -13
View File
@@ -7,9 +7,10 @@ use std::{
pin::Pin,
task::{Context, Poll},
};
use tokio::{stream::Stream, sync::mpsc::Receiver};
use tokio::sync::mpsc::Receiver;
use tower::discover::{Change, Discover};
use tokio_stream::Stream;
use tower::discover::Change;
type DiscoverResult<K, S, E> = Result<Change<K, S>, E>;
@@ -23,17 +24,12 @@ impl<K: Hash + Eq + Clone> DynamicServiceStream<K> {
}
}
impl<K: Hash + Eq + Clone> Discover for DynamicServiceStream<K> {
type Key = K;
type Service = Connection;
type Error = crate::Error;
impl<K: Hash + Eq + Clone> Stream for DynamicServiceStream<K> {
type Item = DiscoverResult<K, Connection, crate::Error>;
fn poll_discover(
mut self: Pin<&mut Self>,
cx: &mut Context<'_>,
) -> Poll<DiscoverResult<Self::Key, Self::Service, Self::Error>> {
fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
let c = &mut self.changes;
match Pin::new(&mut *c).poll_next(cx) {
match Pin::new(&mut *c).poll_recv(cx) {
Poll::Pending | Poll::Ready(None) => Poll::Pending,
Poll::Ready(Some(change)) => match change {
Change::Insert(k, endpoint) => {
@@ -48,9 +44,9 @@ impl<K: Hash + Eq + Clone> Discover for DynamicServiceStream<K> {
let connector = service::connector(http);
let connection = Connection::lazy(connector, endpoint);
let change = Ok(Change::Insert(k, connection));
Poll::Ready(change)
Poll::Ready(Some(change))
}
Change::Remove(k) => Poll::Ready(Ok(Change::Remove(k))),
Change::Remove(k) => Poll::Ready(Some(Ok(Change::Remove(k)))),
},
}
}
+5 -5
View File
@@ -4,7 +4,7 @@ use std::io;
use std::net::SocketAddr;
use std::pin::Pin;
use std::task::{Context, Poll};
use tokio::io::{AsyncRead, AsyncWrite};
use tokio::io::{AsyncRead, AsyncWrite, ReadBuf};
pub(in crate::transport) trait Io:
AsyncRead + AsyncWrite + Send + 'static
@@ -33,8 +33,8 @@ impl AsyncRead for BoxedIo {
fn poll_read(
mut self: Pin<&mut Self>,
cx: &mut Context<'_>,
buf: &mut [u8],
) -> Poll<io::Result<usize>> {
buf: &mut ReadBuf<'_>,
) -> Poll<io::Result<()>> {
Pin::new(&mut self.0).poll_read(cx, buf)
}
}
@@ -83,8 +83,8 @@ impl AsyncRead for ServerIo {
fn poll_read(
mut self: Pin<&mut Self>,
cx: &mut Context<'_>,
buf: &mut [u8],
) -> Poll<io::Result<usize>> {
buf: &mut ReadBuf<'_>,
) -> Poll<io::Result<()>> {
Pin::new(&mut self.0).poll_read(cx, buf)
}
}
+2 -5
View File
@@ -1,8 +1,5 @@
use tower::{
layer::{Layer, Stack},
util::Either,
ServiceBuilder,
};
use tower::layer::util::Stack;
use tower::{layer::Layer, util::Either, ServiceBuilder};
pub(crate) trait ServiceBuilderExt<L> {
fn layer_fn<F: Fn(S) -> Out, S, Out>(self, f: F) -> ServiceBuilder<Stack<LayerFn<F>, L>>;
+1 -1
View File
@@ -6,7 +6,7 @@ use std::{
pin::Pin,
task::{Context, Poll},
};
use tower_make::MakeService;
use tower::make::MakeService;
use tower_service::Service;
use tracing::trace;