google/tarpc

Use tower::Service trait instead of Serve trait?

akiradeveloper opened this issue · 2 comments

This library defines a trait named Serve. Every micro-services will implement this.

pub trait Serve<Req> {
    /// Type of response.
    type Resp;

    /// Type of response future.
    type Fut: Future<Output = Self::Resp>;

    /// Extracts a method name from the request.
    fn method(&self, _request: &Req) -> Option<&'static str> {
        None
    }

    /// Responds to a single request.
    fn serve(self, ctx: context::Context, req: Req) -> Self::Fut;
}

But this trait is almost identical to tower::Service

pub trait Service<Request> {
    type Response;
    type Error;
    type Future: Future;
    fn poll_ready(
        &mut self, 
        cx: &mut Context<'_>
    ) -> Poll<Result<(), Self::Error>>;
    fn call(&mut self, req: Request) -> Self::Future;
}

If tarpc uses tower::Service instead of its own Serve trait, tarpc will be able to exploit every middlewares provided by tower ecosystem which includes timeout, buffering, rate-limiting, etc. Some of them are reinvented in tarpc I believe.

In my opinion, redesigning tarpc to depend on tower will make this library greater than as of now. Do you have a plan to do this? or is my idea wrong?

tikue commented

Thanks for filling this! Tower is indeed very similar. I do hope to converge at some point, because it would be great to leverage all the excellent work done in the tower ecosystem. It's been awhile since I last looked into it; the poll_ready stuff was a point of contention, but I don't think it should be insurmountable.

I've made my own framework that depends on Tower. Since my concern is only for in-process microservices, it was quite a easy task. https://github.com/akiradeveloper/norpc

I still believe using tower::Service instead of Serve is a good direction for tarpc but I am sorry I will not be a user if it is accomplished.