diff --git a/src/server/mod.rs b/src/server/mod.rs deleted file mode 100644 index 41c05f5..0000000 --- a/src/server/mod.rs +++ /dev/null @@ -1,331 +0,0 @@ -// src/server/mod.rs -//! Сервер Futriix - документо-ориентированная БД с wait-free архитектурой -//! -//! Основной модуль сервера, реализующий wait-free доступ к данным, -//! синхронную master-master репликацию и поддержку HTTP/HTTPS. - -#![allow(dead_code)] - -use std::sync::Arc; -use std::fs::OpenOptions; -use std::io::Write; - -use crate::common::Result; -use crate::common::config::Config; -use crate::lua_shell::LuaShell; - -// Импортируем подмодули -pub mod database; -pub mod lua_engine; -pub mod http; -pub mod sharding; // Объединенный модуль шардинга и репликации -pub mod csv_import_export; // Модуль для CSV импорта/экспорта - -/// Функция для логирования в файл -fn log_to_file(message: &str) { - if let Ok(mut file) = OpenOptions::new() - .create(true) - .append(true) - .open("futriix.log") - { - let timestamp = chrono::Local::now().format("%Y-%m-%d %H:%M:%S%.3f").to_string(); - let log_message = format!("[{}] {}\n", timestamp, message); - let _ = file.write_all(log_message.as_bytes()); - } -} - -/// Функция для вывода текста с ANSI цветом -#[allow(dead_code)] -fn print_colored(text: &str, ansi_color: &str) { - println!("{}{}\x1b[0m", ansi_color, text); -} - -/// Конвертация HEX цвета в ANSI escape code -fn hex_to_ansi(hex_color: &str) -> String { - let hex = hex_color.trim_start_matches('#'); - - if hex.len() == 6 { - if let (Ok(r), Ok(g), Ok(b)) = ( - u8::from_str_radix(&hex[0..2], 16), - u8::from_str_radix(&hex[2..4], 16), - u8::from_str_radix(&hex[4..6], 16), - ) { - return format!("\x1b[38;2;{};{};{}m", r, g, b); - } - } - - "\x1b[38;2;255;255;255m".to_string() -} - -/// Основный сервер Futriix с wait-free архитектураой -pub struct FutriixServer { - config: Config, - database: Arc, - lua_engine: lua_engine::LuaEngine, - sharding_manager: Arc, // Объединенный менеджер - http_enabled: bool, - csv_manager: Arc, -} - -impl FutriixServer { - /// Создание нового сервера с wait-free архитектурой - pub async fn new(config_path: &str) -> Result { - // Загрузка конфигурации - let config = Config::load(config_path)?; - - // Инициализация компонентов с wait-free подходами - let database = Arc::new(database::Database::new()); - let lua_engine = lua_engine::LuaEngine::new()?; - - // Инициализация объединенного менеджера шардинга и репликации - let sharding_manager = Arc::new(sharding::ShardingManager::new( - 160, // virtual_nodes_per_node - config.replication.enabled, - )); - - // Инициализация менеджера CSV - let csv_manager = Arc::new(csv_import_export::CsvManager::new( - database.clone(), - config.csv.clone(), - )); - - // Регистрация функций БД в Lua - lua_engine.register_db_functions(database.clone(), sharding_manager.clone())?; - - // Инициализация базы данных - FutriixServer::initialize_database(database.clone())?; - - // Проверяем, включен ли HTTP режим (теперь учитываем новые директивы) - let http_enabled = (config.server.http_port.is_some() && config.server.http) || - (config.server.https_port.is_some() && config.server.https); - - Ok(Self { - config, - database, - lua_engine, - sharding_manager, - http_enabled, - csv_manager, - }) - } - - /// Инициализация базы данных с wait-free структурами - fn initialize_database(db: Arc) -> Result<()> { - // Создаем системные коллекции с wait-free доступом - let _system_collection = db.get_collection("_system"); - let _users_collection = db.get_collection("_users"); - let _logs_collection = db.get_collection("_logs"); - let _procedures_collection = db.get_collection("_procedures"); - let _triggers_collection = db.get_collection("_triggers"); - let _csv_imports_collection = db.get_collection("_csv_imports"); - - // Создаем директорию для бэкапов - let backup_dir = "/futriix/backups"; - if let Err(e) = std::fs::create_dir_all(backup_dir) { - // Используем текущую директорию как запасной вариант - let current_backup_dir = "./futriix_backups"; - if let Err(e2) = std::fs::create_dir_all(current_backup_dir) { - eprintln!("Warning: Failed to create backup directory '{}': {}", backup_dir, e); - eprintln!("Warning: Also failed to create fallback directory '{}': {}", current_backup_dir, e2); - } else { - println!("Backup directory created at: {}", current_backup_dir); - } - } else { - println!("Backup directory created at: {}", backup_dir); - } - - // Создаем директорию для CSV файлов - let csv_dir = "/futriix/csv"; - if let Err(e) = std::fs::create_dir_all(csv_dir) { - // Используем текущую директорию как запасной вариант - let current_csv_dir = "./futriix_csv"; - if let Err(e2) = std::fs::create_dir_all(current_csv_dir) { - eprintln!("Warning: Failed to create CSV directory '{}': {}", csv_dir, e); - eprintln!("Warning: Also failed to create fallback directory '{}': {}", current_csv_dir, e2); - } else { - println!("CSV directory created at: {}", current_csv_dir); - } - } else { - println!("CSV directory created at: {}", csv_dir); - } - - // Создаем директорию для статических файлов - let static_dir = "static"; - if let Err(e) = std::fs::create_dir_all(static_dir) { - eprintln!("Warning: Failed to create static files directory '{}': {}", static_dir, e); - } else { - println!("Static files directory created at: {}", static_dir); - } - - // СОЗДАЕМ ПРОСТОЙ INDEX.HTML ДЛЯ ТЕСТИРОВАНИЯ - let index_html_content = r#" - - - Futriix Database Server - - - -

Futriix Database Server

-
-

Server is running successfully!

-

This is a test page to verify HTTP server functionality.

-

Current time:

-
- - -"#; - - if let Err(e) = std::fs::write("static/index.html", index_html_content) { - eprintln!("Warning: Failed to create index.html: {}", e); - } else { - println!("Created test index.html in static directory"); - } - - let message = "Database initialized with system collections"; - println!("{}", message); - log_to_file(message); - - Ok(()) - } - - /// Запуск сервера с wait-free архитектурой - pub async fn run(&self) -> Result<()> { - // Определяем режим работы и имя кластера - let cluster_name = &self.config.cluster.name; - - // ИЗМЕНЕНИЕ: Заменено "Mode" на "Run" - println!("Run: cluster (cluster: '{}')", cluster_name); - - log_to_file("Futriix Database Server started"); - log_to_file(&format!("Run: cluster (cluster: '{}')", cluster_name)); - - // Запуск HTTP/HTTPS серверов в отдельных задачах, если настроены - if self.http_enabled { - // ЗАПУСКАЕМ СЕРВЕРЫ В ФОНОВЫХ ЗАДАЧАХ, НЕ БЛОКИРУЯ ОСНОВНОЙ ПОТОК - self.start_http_servers_in_background().await?; - } else { - println!("HTTP/HTTPS servers disabled in configuration"); - } - - // Добавляем пустую строку после информации о серверах - println!(); - - let mut lua_shell = LuaShell::new( - self.lua_engine.clone(), - self.database.clone(), - self.sharding_manager.clone(), - self.csv_manager.clone(), - ); - - // Запуск интерактивной оболочки - ЭТО ОСНОВНОЙ ПОТОК ВЫПОЛНЕНИЯ - lua_shell.run().await?; - - Ok(()) - } - - /// Запуск HTTP/HTTPS серверов в фоновых задачах (не блокирующий) - async fn start_http_servers_in_background(&self) -> Result<()> { - let static_config = self::http::StaticFilesConfig::default(); - let acl_config = self::http::AclConfig { - enabled: self.config.acl.enabled, - allowed_ips: self.config.acl.allowed_ips.clone(), - denied_ips: self.config.acl.denied_ips.clone(), - }; - - // Запуск HTTP сервера, если настроен и включен - if let Some(http_port) = self.config.server.http_port { - if self.config.server.http { - let http_addr = format!("{}:{}", self.config.server.host, http_port); - let http_config = self::http::HttpConfig { - enabled: true, - port: http_port, - http2_enabled: self.config.server.http2_enabled.unwrap_or(false), - }; - - let db_clone = self.database.clone(); - let static_config_clone = static_config.clone(); - let acl_config_clone = acl_config.clone(); - - // ЗАПУСКАЕМ В ФОНОВОЙ ЗАДАЧЕ БЕЗ ОЖИДАНИЯ - tokio::spawn(async move { - // ИЗМЕНЕНИЕ: Убрано многоточие - println!("Starting HTTP server on {}", http_addr); - match self::http::start_http_server(&http_addr, db_clone, static_config_clone, http_config, acl_config_clone).await { - Ok(_) => { - let message = format!("HTTP server started on {}", http_addr); - println!("{}", message); - log_to_file(&message); - } - Err(e) => { - let message = format!("Failed to start HTTP server: {}", e); - eprintln!("{}", message); - log_to_file(&message); - } - } - }); - } else { - println!("HTTP server disabled in configuration"); - } - } - - // Запуск HTTPS сервера, если настроен и включен - if let Some(https_port) = self.config.server.https_port { - if self.config.server.https && self.config.tls.enabled { - let https_addr = format!("{}:{}", self.config.server.host, https_port); - let tls_config = self::http::TlsConfig { - enabled: self.config.tls.enabled, - cert_path: self.config.tls.cert_path.clone(), - key_path: self.config.tls.key_path.clone(), - }; - - let db_clone = self.database.clone(); - let static_config_clone = static_config.clone(); - let acl_config_clone = acl_config.clone(); - - // ЗАПУСКАЕМ В ФОНОВОЙ ЗАДАЧЕ БЕЗ ОЖИДАНИЯ - tokio::spawn(async move { - // ИЗМЕНЕНИЕ: Убрано многоточие - println!("Starting HTTPS server on {}", https_addr); - match self::http::start_https_server(&https_addr, db_clone, static_config_clone, tls_config, acl_config_clone).await { - Ok(_) => { - let message = format!("HTTPS server started on {}", https_addr); - println!("{}", message); - log_to_file(&message); - } - Err(e) => { - let message = format!("Failed to start HTTPS server: {}", e); - eprintln!("{}", message); - log_to_file(&message); - } - } - }); - } else { - if !self.config.tls.enabled { - println!("HTTPS disabled: TLS not enabled in configuration"); - } else { - println!("HTTPS server disabled in configuration"); - } - } - } - - Ok(()) - } - - /// Получение менеджера шардинга (для тестов и расширений) - #[allow(dead_code)] - pub fn get_sharding_manager(&self) -> Arc { - self.sharding_manager.clone() - } - - /// Получение менеджера CSV (для тестов и расширений) - #[allow(dead_code)] - pub fn get_csv_manager(&self) -> Arc { - self.csv_manager.clone() - } -}