futriix/src/server/mod.rs
2025-09-12 00:40:20 +03:00

233 lines
9.0 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// 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(())
}
}