You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
This repository has been archived by the owner on Mar 13, 2021. It is now read-only.
I was looking into tower recently and wanted to play with it a little. However, it was a bit tough getting started. A small and self contained example would have helped a lot. Everything I could find is built on top of hyper.
I ended up building the small example project below, based on tokio-tower. Ordinarily I would file a PR, but a) tower is in a bit of flux right now and b) I don't think it's good enough. There are three things that need improvement, I think.
Demonstrate how to properly use ServiceBuilder and the various layers it can add.
Use MakeService on the server side. That's what the documentation says it's for, but I couldn't figure out how.
A general clean up. My Rust game isn't at a level yet where I should write examples for other people.
use std::future::Future;use std::pin::Pin;use futures::future::{self,BoxFuture,FutureExt};use serde::{Deserialize,Serialize};use tokio::net::TcpListener;use tokio_tower::multiplex;use tower::Service;#[tokio::main]asyncfnmain() -> Result<(),ClientError>{let addr = "127.0.0.1:4444".parse().unwrap();
tokio::spawn(run_server(addr).map(|_| ()));// give the server a chance to start up
tokio::task::yield_now().await;letmut client = setup_client(addr);let exprs = [Expr::add(187.0,578.0),Expr::div(Expr::add(123.0,321.0),2.0),Expr::sub(Expr::mul(2.0,25.0),8.0),];for expr in exprs.iter(){
futures::future::poll_fn(|cx| client.poll_ready(cx)).await?;let res = client.call(Tagged::blank(expr.clone())).await?;println!("{} = {}", expr, res.content);}Ok(())}//// Client//fnsetup_client(addr: std::net::SocketAddrV4,) -> implService<Tagged<Expr>,Response = Tagged<f64>,Error = ClientError,Future = implFuture<Output = Result<Tagged<f64>,ClientError>>,>{
tower::reconnect::Reconnect::new::<
<ConnectToServerasService<std::net::SocketAddrV4>>::Response,Tagged<Expr>,>(ConnectToServer, addr)}typeClientError = Box<dyn std::error::Error + Send + Sync>;structConnectToServer;implService<std::net::SocketAddrV4>forConnectToServer{typeResponse = CalcClient;typeError = ClientError;typeFuture = BoxFuture<'static,Result<Self::Response,Self::Error>>;fnpoll_ready(&mutself,_cx:&mut std::task::Context,) -> std::task::Poll<Result<(),Self::Error>>{Ok(()).into()}fncall(&mutself,req: std::net::SocketAddrV4) -> Self::Future{Box::pin(asyncmove{let tcp_stream = tokio::net::TcpStream::connect(req).await?;let transport = multiplex::MultiplexTransport::new(
async_bincode::AsyncBincodeStream::from(tcp_stream).for_async(),Tagger::new(),);let client = multiplex::Client::new(transport);Ok(CalcClient{delegate:Box::new(client),})})}}structCalcClient{delegate:Box<dynService<Tagged<Expr>,Response = Tagged<f64>,Error = ClientError,Future = Pin<Box<dynFuture<Output = Result<Tagged<f64>,ClientError>> + Send>>,>,>,}implService<Tagged<Expr>>forCalcClient{typeResponse = Tagged<f64>;typeError = ClientError;typeFuture = Pin<Box<dynFuture<Output = Result<Tagged<f64>,ClientError>> + Send>>;fnpoll_ready(&mutself,cx:&mut std::task::Context,) -> std::task::Poll<Result<(),Self::Error>>{self.delegate.poll_ready(cx)}fncall(&mutself,req:Tagged<Expr>) -> Self::Future{self.delegate.call(req)}}impl tokio_tower::multiplex::TagStore<Tagged<Expr>,Tagged<f64>>forTagger{typeTag = u32;fnassign_tag(mutself: std::pin::Pin<&mutSelf>,req:&mutTagged<Expr>) -> Self::Tag{
req.tag = self.slab.insert(())asu32;
req.tag}fnfinish_tag(mutself: std::pin::Pin<&mutSelf>,resp:&Tagged<f64>) -> Self::Tag{self.slab.remove(resp.tagasusize);
resp.tag}}//// Server//asyncfnrun_server(addr: std::net::SocketAddrV4) -> Result<(),Box<dyn std::error::Error>>{letmut listener = TcpListener::bind(addr).await?;loop{let(tcp_stream, _) = listener.accept().await?;let server = multiplex::Server::new(
async_bincode::AsyncBincodeStream::from(tcp_stream).for_async(),CalcServer,);let server = tower::ServiceBuilder::new().service(server);
tokio::spawn(server);}}#[derive(Clone)]structCalcServer;implService<Tagged<Expr>>forCalcServer{typeResponse = Tagged<f64>;typeError = ();typeFuture = futures::future::Ready<Result<Self::Response,Self::Error>>;fnpoll_ready(&mutself,_cx:&mut std::task::Context,) -> std::task::Poll<Result<(),Self::Error>>{Ok(()).into()}fncall(&mutself,req:Tagged<Expr>) -> Self::Future{
future::ready(Ok(Tagged{tag: req.tag,content:eval(req.content),}))}}fneval(expr:Expr) -> f64{match expr {Expr::Add(a, b) => eval(*a) + eval(*b),Expr::Div(a, b) => eval(*a) / eval(*b),Expr::Mul(a, b) => eval(*a)*eval(*b),Expr::Sub(a, b) => eval(*a) - eval(*b),Expr::Val(x) => x,}}//// Shared//#[derive(Clone,Deserialize,Serialize)]enumExpr{Add(Box<Expr>,Box<Expr>),Div(Box<Expr>,Box<Expr>),Mul(Box<Expr>,Box<Expr>),Sub(Box<Expr>,Box<Expr>),Val(f64),}implFrom<f64>forExpr{fnfrom(x:f64) -> Expr{Expr::Val(x)}}implExpr{fnadd<A:Into<Expr>,B:Into<Expr>>(a:A,b:B) -> Expr{Expr::Add(Box::new(a.into()),Box::new(b.into()))}fndiv<A:Into<Expr>,B:Into<Expr>>(a:A,b:B) -> Expr{Expr::Div(Box::new(a.into()),Box::new(b.into()))}fnmul<A:Into<Expr>,B:Into<Expr>>(a:A,b:B) -> Expr{Expr::Mul(Box::new(a.into()),Box::new(b.into()))}fnsub<A:Into<Expr>,B:Into<Expr>>(a:A,b:B) -> Expr{Expr::Sub(Box::new(a.into()),Box::new(b.into()))}}impl std::fmt::DisplayforExpr{fnfmt(&self,f:&mut std::fmt::Formatter<'_>) -> std::fmt::Result{matchself{Expr::Add(a, b) => write!(f, "({} + {})", a, b),Expr::Div(a, b) => write!(f, "({} ÷ {})", a, b),Expr::Mul(a, b) => write!(f, "({} * {})", a, b),Expr::Sub(a, b) => write!(f, "({} - {})", a, b),Expr::Val(x) => write!(f, "{}", x),}}}structTagger{slab: slab::Slab<()>,}implTagger{pubfnnew() -> Self{Self{slab: slab::Slab::new(),}}}#[derive(Debug,Deserialize,Serialize)]structTagged<T>{tag:u32,content:T,}impl<T>Tagged<T>{fnblank(content:T) -> Self{Self{tag:0, content }}}
The text was updated successfully, but these errors were encountered:
From a quick glance this example looks nice! We do need more examples etc. Hopefully we can find the time once our spring cleaning work is done and we ship 0.4.
I was looking into tower recently and wanted to play with it a little. However, it was a bit tough getting started. A small and self contained example would have helped a lot. Everything I could find is built on top of hyper.
I ended up building the small example project below, based on tokio-tower. Ordinarily I would file a PR, but a) tower is in a bit of flux right now and b) I don't think it's good enough. There are three things that need improvement, I think.
ServiceBuilder
and the various layers it can add.MakeService
on the server side. That's what the documentation says it's for, but I couldn't figure out how.The text was updated successfully, but these errors were encountered: