pub mod service;
pub mod config;
mod auth;
mod error;
#[cfg(test)]
mod tests;
pub use config::ServerConfig;
pub use error::{ServerError, Result};
use std::net::SocketAddr;
use std::sync::Arc;
use anyhow;
use qdrant_client::Qdrant;
use crate::config::AppConfig;
use crate::server::service::VectorDBServiceImpl;
use crate::edit::grpc::EditingServiceImpl;
use tokio::sync::oneshot;
use tonic::transport::Server;
use tracing::{info, error};
#[cfg(feature = "server")]
use {
vectordb_proto::vector_db_service_server::VectorDbServiceServer,
crate::grpc_generated::editing::editing_service_server::EditingServiceServer,
vectordb_proto::FILE_DESCRIPTOR_SET as VECTORDB_FILE_DESCRIPTOR_SET,
crate::grpc_generated::EDITING_FILE_DESCRIPTOR_SET
};
#[cfg(feature = "server")]
pub async fn start_server(
addr: SocketAddr,
config: Arc<AppConfig>,
client: Arc<Qdrant>,
api_key: Option<String>,
require_auth: bool,
tls_config: Option<tonic::transport::server::ServerTlsConfig>,
max_concurrent_requests: Option<usize>,
) -> Result<()> {
info!("Entering start_server function (server feature enabled)");
let api_key_path = config.server_api_key_path.clone();
let vectordb_service = VectorDBServiceImpl::new(client.clone(), config.clone(), api_key_path)?;
info!("Creating EditingServiceImpl instance...");
let editing_service_impl = EditingServiceImpl::default();
info!("Building reflection service...");
let reflection_service = tonic_reflection::server::Builder::configure()
.register_encoded_file_descriptor_set(VECTORDB_FILE_DESCRIPTOR_SET)
.register_encoded_file_descriptor_set(EDITING_FILE_DESCRIPTOR_SET)
.build_v1()?;
info!("Configuring server builder on {}", addr);
info!("Adding services (Reflection, VectorDB, Editing)...");
let server_builder = Server::builder()
.add_service(reflection_service)
.add_service(VectorDbServiceServer::new(vectordb_service))
.add_service(EditingServiceServer::new(editing_service_impl));
info!("Finished adding services.");
if let Some(tls_config) = tls_config {
error!("TLS support is temporarily disabled for compilation reasons");
return Err(anyhow::anyhow!("TLS support is temporarily disabled").into());
} else {
info!("Starting server without TLS...");
let shutdown = shutdown_signal(); tokio::select! {
res = server_builder.serve(addr) => {
if let Err(e) = res {
error!("Server failed to serve: {}", e);
return Err(e.into()); }
info!("Server finished serving normally.");
}
_ = shutdown => {
info!("Shutdown signal received, stopping server.");
}
}
}
Ok(())
}
#[cfg(not(feature = "server"))]
pub async fn start_server(
_addr: SocketAddr,
_config: Arc<AppConfig>,
_client: Arc<Qdrant>,
_shutdown_signal: Option<oneshot::Receiver<()>>,
_use_tls: bool,
_cert_path: Option<String>,
_key_path: Option<String>,
) -> anyhow::Result<()> {
error!("Server feature not enabled. Compile with --features=server to enable server mode.");
Err(anyhow::anyhow!("Server feature not enabled"))
}
pub async fn start_default_server(
port: u16,
config: Arc<AppConfig>,
client: Arc<Qdrant>,
) -> crate::server::Result<()> {
let addr = format!("0.0.0.0:{}", port).parse()?;
start_server(addr, config, client, None, false, None, None).await
}
#[cfg(feature = "server")]
async fn shutdown_signal() {
let ctrl_c = async {
tokio::signal::ctrl_c()
.await
.expect("failed to install Ctrl+C handler");
};
#[cfg(unix)]
let terminate = async {
tokio::signal::unix::signal(tokio::signal::unix::SignalKind::terminate())
.expect("failed to install signal handler")
.recv()
.await;
};
#[cfg(not(unix))]
let terminate = std::future::pending::<()>();
tokio::select! {
_ = ctrl_c => {},
_ = terminate => {},
}
info!("Termination signal received.");
}