net-component 0.1.0

This crate defines core traits and types for the components in net-timescale. The component in the context is a separate microservice which handles each own type of requests from net-gateway - rest server. Because of the amount of such services we decided to create a trait which defines the skeleton of each one to reduce the code duplicate.
Documentation
use std::error::Error;
use std::net::SocketAddr;
use std::sync::Arc;

use net_core_api::api::envelope::envelope::Envelope;
use net_core_api::api::result::result::ResultDTO;
use net_core_api::core::decoder_api::Decoder;
use net_core_api::core::encoder_api::Encoder;
use net_core_api::core::typed_api::Typed;
use net_transport::quinn::connection::QuicConnection;
use sqlx::Pool;
use sqlx::Postgres;

use net_transport::quinn::server::builder::ServerQuicEndpointBuilder;

use crate::handler::network_service_handler_manager::NetworkServiceHandlerManager;

use super::component_core::Component;

#[async_trait::async_trait]
pub trait NetworkServiceComponent: Component {
    fn get_connection_pool(&self) -> Arc<Pool<Postgres>>;
    fn get_server_addr(&self) -> SocketAddr;
    fn get_handling_manager(&self) -> Arc<NetworkServiceHandlerManager>;


    async fn handle_client_request(
        mut client_connection: QuicConnection,
        handling_update_manager: Arc<NetworkServiceHandlerManager>,
        handling_connection_pool: Arc<Pool<Postgres>>,
    ) {
        tokio::spawn(async move {
            let receive_result = client_connection.receive_reliable().await;
            if receive_result.is_err() {
                todo!()
            }
            let recieve_result = receive_result.unwrap();

            let enveloped_request = Envelope::decode(&recieve_result);

            let tenant_id: String = enveloped_request.get_tenant_id().to_owned();

            log::debug!("Recieved request from client: {:?}", enveloped_request);

            let handle_request_result = handling_update_manager.handle(handling_connection_pool, enveloped_request).await;
            log::debug!("Got response on request: {:?}", handle_request_result);

            let request_result_dto: ResultDTO = match handle_request_result {
                Ok(envelope) => ResultDTO::new(
                    true,
                    None,
                    Some(envelope)
                ),
                Err(e) => ResultDTO::new(
                    false,
                    Some(&e.to_string()),
                    None
                )
            };
            
            let envelope_to_send = Envelope::new(
                &tenant_id,
                ResultDTO::get_data_type(),
                &request_result_dto.encode()
            );

            let send_result = client_connection.send_all_reliable(&envelope_to_send.encode()).await;
            if send_result.is_err() {
                todo!()
            }
        });
    }
}

#[async_trait::async_trait]
impl<T: NetworkServiceComponent> Component for T {
    async fn run (&self) -> Result<(), Box<dyn Error + Send + Sync>> {
        log::debug!("Run component");

        //TODO: Think of running some preambula here (some kind of setup fn), where we can run meigrations for example

        log::debug!("Creating server endpoint for net-reporter..."); 
        let mut service_server_endpoint = ServerQuicEndpointBuilder::default()
            .with_addr(self.get_server_addr())
            .build()?;
        log::debug!("Successfully created server endpoint for net-reporter");

        loop {
            log::debug!("Waiting on client connection...");
            let client_connection_result = service_server_endpoint.accept_client_connection().await;
            match client_connection_result {
                Ok(client_connection) => {
                    log::debug!("Client is successfully connected");
                    let handling_update_manager = self.get_handling_manager();
                    let handling_connection_pool = self.get_connection_pool();
                    
                        Self::handle_client_request(
                            client_connection,
                            handling_update_manager,
                            handling_connection_pool,
                        ).await
                },
                Err(e) => {
                    log::error!("Client was trying to connect, but here is some error: {e}");
                },
            }
        }
    }
}