use std::sync::Arc;
use crate::errors::execute_error::ExecuteError;
use crate::errors::RRDBError;
use crate::executor::config::global::GlobalConfig;
use crate::executor::predule::Executor;
use crate::logger::predule::Logger;
use crate::pgwire::predule::Connection;
use crate::server::channel::ChannelResponse;
use crate::server::predule::{ChannelRequest, SharedState};
use futures::future::join_all;
use tokio::net::TcpListener;
use tokio::sync::mpsc;
use super::client::ClientInfo;
pub struct Server {
pub config: Arc<GlobalConfig>,
}
impl Server {
pub fn new(config: GlobalConfig) -> Self {
Self {
config: Arc::new(config),
}
}
pub async fn run(&self) -> Result<(), RRDBError> {
let (request_sender, mut request_receiver) = mpsc::channel::<ChannelRequest>(1000);
let config = self.config.clone();
let background_task = tokio::spawn(async move {
while let Some(request) = request_receiver.recv().await {
let config = config.clone();
tokio::spawn(async move {
let executor = Executor::new(config);
let result = executor
.process_query(request.statement, request.connection_id)
.await;
match result {
Ok(result) => {
if let Err(_response) = request
.response_sender
.send(ChannelResponse { result: Ok(result) })
{
Logger::error("channel send failed");
}
}
Err(error) => {
let error = error.to_string();
if let Err(_response) = request.response_sender.send(ChannelResponse {
result: Err(ExecuteError::wrap(error)),
}) {
Logger::error("channel send failed");
}
}
}
});
}
});
let listener = TcpListener::bind((self.config.host.to_owned(), self.config.port as u16))
.await
.map_err(|error| ExecuteError::wrap(error.to_string()))?;
let config = self.config.clone();
let connection_task = tokio::spawn(async move {
loop {
let accepted = listener.accept().await;
let (stream, address) = match accepted {
Ok((stream, address)) => (stream, address),
Err(error) => {
Logger::error(format!("socket error {:?}", error));
continue;
}
};
let client_info = ClientInfo {
ip: address.ip(),
connection_id: uuid::Uuid::new_v4().to_string(),
database: "None".into(),
};
let shared_state = SharedState {
sender: request_sender.clone(),
client_info,
};
let config = config.clone();
tokio::spawn(async move {
let mut conn = Connection::new(shared_state, config);
if let Err(error) = conn.run(stream).await {
Logger::error(format!("connection error {:?}", error));
}
});
}
});
Logger::info(format!(
"Server is running on {}:{}",
self.config.host, self.config.port
));
join_all(vec![connection_task, background_task]).await;
Ok(())
}
}