futriix/src/server/mod.rs

233 lines
9.0 KiB
Rust
Raw Normal View History

2025-09-12 00:40:20 +03:00
// src/server/mod.rs
//! Сервер Falcot - документо-ориентированная БД с 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::error::Result;
use crate::lua_shell::LuaShell;
// Импортируем подмодули
pub mod database;
pub mod replication;
pub mod lua_engine;
pub mod messagepack;
pub mod config;
pub mod http;
pub mod sharding; // Добавляем модуль шардинга
/// Функция для логирования в файл
fn log_to_file(message: &str) {
if let Ok(mut file) = OpenOptions::new()
.create(true)
.append(true)
.open("falcot.log")
{
let timestamp = chrono::Local::now().format("%Y-%m-%d %H:%M:%S");
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()
}
/// Основный сервер Falcot с wait-free архитектурой
pub struct FalcotServer {
config: config::Config,
database: Arc<database::Database>,
lua_engine: lua_engine::LuaEngine,
replication: Arc<replication::ReplicationManager>,
http_enabled: bool,
}
impl FalcotServer {
/// Создание нового сервера с wait-free архитектурой
pub async fn new(config_path: &str) -> Result<Self> {
// Загрузка конфигурации
let config = config::Config::load(config_path)?;
// Инициализация компонентов с wait-free подходами
let database = Arc::new(database::Database::new());
let lua_engine = lua_engine::LuaEngine::new()?;
let replication = Arc::new(replication::ReplicationManager::new(
config.replication.master_nodes.iter()
.map(|addr| addr.to_string())
.collect(),
config.replication.sync_interval,
config.replication.enabled,
));
// Регистрация функций БД в Lua
lua_engine.register_db_functions(database.clone())?;
// Инициализация базы данных
FalcotServer::initialize_database(database.clone())?;
// Проверяем, включен ли HTTP режим
let http_enabled = config.server.http_port.is_some() || config.server.https_port.is_some();
Ok(Self {
config,
database,
lua_engine,
replication,
http_enabled,
})
}
/// Инициализация базы данных с wait-free структурами
fn initialize_database(db: Arc<database::Database>) -> 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 backup_dir = "/falcot/backups";
if let Err(e) = std::fs::create_dir_all(backup_dir) {
eprintln!("Warning: Failed to create backup directory: {}", e);
}
let message = "Database initialized with system collections";
println!("{}", message);
log_to_file(message);
Ok(())
}
/// Запуск сервера с wait-free архитектурой
pub async fn run(&self) -> Result<()> {
// Вывод приветственного сообщения с цветом #00bfff
println!();
let color_code = hex_to_ansi("#00bfff");
print_colored("Falcot Database Server", &color_code);
println!();
println!("Version: 1.0.0");
println!("Features: Wait-Free Architecture, Master-Master Replication, Lua Scripting, HTTP/HTTPS Support");
log_to_file("Falcot Database Server started");
log_to_file("Version: 1.0.0");
// Запуск HTTP/HTTPS серверов в отдельных задачах, если настроены
if self.http_enabled {
self.start_http_servers().await?;
}
// Запуск Lua интерпретатора
println!("Starting Lua interpreter...");
log_to_file("Starting Lua interpreter...");
let mut lua_shell = LuaShell::new(
self.lua_engine.clone(),
self.database.clone(),
self.replication.clone()
);
// Запуск интерактивной оболочки
lua_shell.run().await?;
Ok(())
}
/// Запуск HTTP/HTTPS серверов в отдельных задачах
async fn start_http_servers(&self) -> Result<()> {
let static_config = http::StaticFilesConfig::default();
let acl_config = 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 {
let http_addr = format!("{}:{}", self.config.server.host, http_port);
let http_config = 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();
// Запускаем HTTP сервер в отдельной задаче (не блокирующей основной поток)
tokio::spawn(async move {
match 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);
}
}
});
}
// Запуск HTTPS сервера, если настроен
if let Some(https_port) = self.config.server.https_port {
let https_addr = format!("{}:{}", self.config.server.host, https_port);
let tls_config = 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();
// Запускаем HTTPS сервер в отдельной задаче
tokio::spawn(async move {
match 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);
}
}
});
}
Ok(())
}
}