use std::future::Future;
use std::pin::Pin;
use std::sync::Arc;
use bytes::Bytes;
use http::{Request, Response};
use http_body::Body as HttpBody;
use tonic::body::Body;
use tonic::service::Routes;
use tonic::transport::Server;
use tower::{Layer, Service};
use super::GrpcConfig;
use crate::tracing::info;
pub(crate) struct GrpcServer<T> {
server: Server<T>,
routes: Routes,
config: Arc<GrpcConfig>,
}
impl<T> GrpcServer<T> {
pub fn new(server: Server<T>, routes: Routes, config: Arc<GrpcConfig>) -> Self {
Self {
server,
routes,
config,
}
}
}
impl<L, ResBody> crate::server::Server for GrpcServer<L>
where
L: Layer<Routes> + Clone + Send + 'static,
L::Service: Service<Request<Body>, Response = Response<ResBody>> + Clone + Send + 'static,
<<L as Layer<Routes>>::Service as Service<Request<Body>>>::Future: Send,
<<L as Layer<Routes>>::Service as Service<Request<Body>>>::Error:
Into<Box<dyn std::error::Error + Send + Sync>> + Send,
ResBody: HttpBody<Data = Bytes> + Send + 'static,
ResBody::Error: Into<Box<dyn std::error::Error + Send + Sync>>,
{
type Future = Pin<Box<dyn Future<Output = ()> + Send>>;
fn start(&self) -> Self::Future {
let mut server = self.server.clone();
let routes = self.routes.clone();
let config = self.config.clone();
Box::pin(async move {
let addr = format!("{}:{}", config.host, config.port)
.parse()
.expect("Invalid gRPC server address");
info!("gRPC server listening on {}", addr);
server
.add_routes(routes)
.serve(addr)
.await
.expect("gRPC server error");
})
}
}