-
Notifications
You must be signed in to change notification settings - Fork 285
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
A struct to combine two service #813
Comments
Maybe i'm missing something here, but isn't this basically what layers is all about? |
Yes! That's why I need this. I have many module that offer a layer interface, but I have to repeat time and time to write a lot of layer_fn service_fn in every modules. So I made this to DRY. After implementing this, I could write my layer in only one line (call Btw I also made a (above is just a example, real code are more much longer because I have to repeat |
I see. There's already Stack. It's generic. Currently implemented for Layers. Maybe can also be implemented for 2 Services? Maybe not. I do see where you come from. Makes me think that in theory any service could be turned into a layer, with some kind of building block like this |
FYI below is the the It's indeed possible to implementing the combine of two service with And I have to make other utils for tower:
below is the implement of use std::{future::Future, task::ready};
use tower::Service;
pub trait ServiceExt<T>: Service<T> {
fn ready_call(&mut self, req: T) -> ReadyCall<Self, T>
where
Self: Sized,
{
ReadyCall::new(self, req)
}
}
pin_project_lite::pin_project! {
pub struct ReadyCall<'a, S, T>
where
S: Service<T>,
{
service: &'a mut S,
req: Option<T>,
#[pin]
fut: Option<S::Future>,
}
}
impl<'a, S, T> ReadyCall<'a, S, T>
where
S: Service<T>,
{
pub fn new(service: &'a mut S, req: T) -> Self {
Self {
service,
req: Some(req),
fut: None,
}
}
}
impl<'a, S, T> Future for ReadyCall<'a, S, T>
where
S: Service<T>,
{
type Output = Result<S::Response, S::Error>;
fn poll(
mut self: std::pin::Pin<&mut Self>,
cx: &mut std::task::Context<'_>,
) -> std::task::Poll<Self::Output> {
loop {
let mut proj = self.as_mut().project();
if let Some(fut) = proj.fut.as_mut().as_pin_mut() {
return ready!(fut.poll(cx)).into();
}
if let Err(e) = ready!(proj.service.poll_ready(cx)) {
return Err(e).into();
}
let req = proj.req.take().expect("req is none");
let fut = proj.service.call(req);
proj.fut.set(Some(fut));
}
}
} |
Hi,
I'm new to use tower. And I find it common for me to write such a Service: e.g. I have a
Service<A, Response = B>
, and aService<B>
, I want make up a new service that calls the first, and then pipe the response from A to B.I have searched the tower docs for this but I get nothing, so I make one that working for me and share it here.
It's worth to merge into tower? Or is there any better way to do that?
The text was updated successfully, but these errors were encountered: