Use async fn in generated traits!!

The major breaking change is that Channel::execute no longer internally
spawns RPC handlers, because it is no longer possible to place a Send
bound on the return type of Serve::serve. Instead, Channel::execute
returns a stream of RPC handler futures.

Service authors can reproduce the old behavior by spawning each response
handler (the compiler knows whether or not the futures can be spawned;
it's just that the bounds can't be expressed generically):

    channel.execute(server.serve())
           .for_each(|rpc| { tokio::spawn(rpc); })
This commit is contained in:
Tim Kuehn
2022-11-23 01:36:51 -08:00
committed by Tim
parent 7c5afa97bb
commit 8dc3711a80
31 changed files with 421 additions and 838 deletions

View File

@@ -4,6 +4,9 @@
// license that can be found in the LICENSE file or at
// https://opensource.org/licenses/MIT.
#![allow(incomplete_features)]
#![feature(async_fn_in_trait)]
use std::env;
use tracing_subscriber::{fmt::format::FmtSpan, prelude::*};

View File

@@ -4,6 +4,9 @@
// license that can be found in the LICENSE file or at
// https://opensource.org/licenses/MIT.
#![allow(incomplete_features)]
#![feature(async_fn_in_trait)]
use clap::Parser;
use futures::{future, prelude::*};
use rand::{
@@ -34,7 +37,6 @@ struct Flags {
#[derive(Clone)]
struct HelloServer(SocketAddr);
#[tarpc::server]
impl World for HelloServer {
async fn hello(self, _: context::Context, name: String) -> String {
let sleep_time =
@@ -44,6 +46,10 @@ impl World for HelloServer {
}
}
async fn spawn(fut: impl Future<Output = ()> + Send + 'static) {
tokio::spawn(fut);
}
#[tokio::main]
async fn main() -> anyhow::Result<()> {
let flags = Flags::parse();
@@ -66,7 +72,7 @@ async fn main() -> anyhow::Result<()> {
// the generated World trait.
.map(|channel| {
let server = HelloServer(channel.transport().peer_addr().unwrap());
channel.execute(server.serve())
channel.execute(server.serve()).for_each(spawn)
})
// Max 10 channels.
.buffer_unordered(10)