79209939

Date: 2024-11-21 06:36:51
Score: 1
Natty:
Report link

Took a bunch of experimenting and reading through tonic source code, and I still have some things I don't understand, but the functional answer is to first, implement the NamedService trait for each layer:

use tonic::transport::server::NamedService;

impl<T> NamedService for EndpointTimer_1<T>
where
    T: NamedService,
{
    const NAME: &'static str = T::NAME;
}

Note, that the error type for the layer's service must be Infallible, e.g.

use std::convert::Infallible;

impl<T, RequestBody, ResponseBody> Service<tonic::codegen::http::Request<RequestBody>>
    for EndpointTimer_1<T>
where
    T: Service<
            tonic::codegen::http::Request<RequestBody>,
            Response = tonic::codegen::http::Response<ResponseBody>,
            Error = Infallible,
        > + Send,

instead of the example-provided type Error = Box<dyn Error + Send + Sync>;. AFAICT this works because the protobuf-generated server is Infallible as well? Unsure, would appreciate an explanation of this by anyone in the know.

Finally, services can be registered by wrapping them in layers individually:

let mut server_builder = Server::builder()
    .layer(ConcurrencyGauge::new());

let provider_1 = provider_1_impl::new(&CONFIG)?;
let server_1 = Server_1::new(provider_1);

let provider_2 = provider_2_impl::new(&CONFIG)?;
let server_2 = Server_2::new(provider_2);


let router = server_builder
    .add_service(EndpointTimer_1::new(Server_1))
    .add_service(EndpointTimer_2::new(Server_2));
router.serve(addr).await?;

Note that this is using the Timer itself, which takes a Service as an argument to new(), and not the Layer around it.

Reasons:
  • Blacklisted phrase (1.5): would appreciate
  • Long answer (-1):
  • Has code block (-0.5):
  • Contains question mark (0.5):
  • Self-answer (0.5):
Posted by: gmoss