tarantula-s2 0.1.0

Search polygons at lngitude/latitude with s2geometry

use tonic::{transport::Server, Response, Status};
use grpc::service_server::{Service, ServiceServer};
use grpc::{TarantulaReq, TarantulaReply};
use std::net::ToSocketAddrs;
use tower_http::trace::{TraceLayer, DefaultMakeSpan, DefaultOnResponse};
use tracing::Level;
use crate::search::GLOBAL_SEARCH;

pub mod grpc {
    tonic::include_proto!("grpc"); 
}

#[derive(Debug, Default)]
pub struct GrpcService {}

#[tonic::async_trait]
impl Service for GrpcService {
    async fn tarantula(&self, request: tonic::Request<TarantulaReq>) 
        -> Result<Response<TarantulaReply>, Status> { 
        let search = unsafe { &GLOBAL_SEARCH.as_ref() }
            .ok_or_else(|| Status::internal("search not initialized"))?;
        let results 
            = search.search(request.get_ref().lon, request.get_ref().lat);
        match results {
            Ok(res) => {
                let reply = TarantulaReply {
                    infos: res
                        .into_iter()
                        .map(|info| grpc::Info {
                            district: info.district,
                            level: info.level,
                            name: info.name,
                        })
                        .collect(), 
                };
                return Ok(Response::new(reply));
            }
            Err(e) => {
                return Err(Status::internal(format!("search error: {}", e)));
            }
        }
    }
}

pub async fn start_server() {
    let config = crate::GLOBAL_CONFIG.grpc.clone();
    let addr = (config.host, config.port)
        .to_socket_addrs()
        .expect("invalid host or port")
        .next()
        .expect("unable to resolve address");

    let service = GrpcService::default();

    println!("grpc server listening on {}", addr);

    let trace_layer = TraceLayer::new_for_grpc()
        .make_span_with(DefaultMakeSpan::new().level(Level::INFO))
        .on_response(DefaultOnResponse::new().level(Level::INFO));

    Server::builder()
        .layer(trace_layer)
        .add_service(ServiceServer::new(service))
        .serve(addr)
        .await
        .unwrap()
}