Delete src/utils/config.rs
This commit is contained in:
parent
542c8a69e0
commit
ec97bbde89
@ -1,750 +0,0 @@
|
||||
//! Конфигурационный модуль для flusql
|
||||
//!
|
||||
//! Этот модуль отвечает за загрузку и управление конфигурацией
|
||||
//! сервера flusql из файла config.toml и переменных окружения.
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::fs;
|
||||
use std::path::Path;
|
||||
use thiserror::Error;
|
||||
|
||||
/// Основная конфигурация flusql
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct Config {
|
||||
/// Общие настройки сервера
|
||||
#[serde(default = "default_server_config")]
|
||||
pub server: ServerConfig,
|
||||
|
||||
/// Настройки базы данных
|
||||
#[serde(default = "default_database_config")]
|
||||
pub database: DatabaseConfig,
|
||||
|
||||
/// Настройки логгера
|
||||
#[serde(default = "default_logging_config")]
|
||||
pub logging: LoggingConfig,
|
||||
|
||||
/// Настройки Lua интерпретатора
|
||||
#[serde(default = "default_lua_config")]
|
||||
pub lua: LuaConfig,
|
||||
|
||||
/// Настройки кластера
|
||||
#[serde(default = "default_cluster_config")]
|
||||
pub cluster: ClusterConfig,
|
||||
|
||||
/// Настройки плагинов
|
||||
#[serde(default = "default_plugins_config")]
|
||||
pub plugins: PluginsConfig,
|
||||
|
||||
/// Настройки HTTP сервера (если включен)
|
||||
#[serde(default = "default_http_config")]
|
||||
pub http: HttpConfig,
|
||||
|
||||
/// Настройки репликации
|
||||
#[serde(default = "default_replication_config")]
|
||||
pub replication: ReplicationConfig,
|
||||
|
||||
/// Настройки сети
|
||||
#[serde(default = "default_network_config")]
|
||||
pub network: NetworkConfig,
|
||||
}
|
||||
|
||||
/// Конфигурация сети
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct NetworkConfig {
|
||||
/// IP-адрес для прослушивания
|
||||
#[serde(default = "default_network_host")]
|
||||
pub host: String,
|
||||
|
||||
/// Порт для прослушивания
|
||||
#[serde(default = "default_network_port")]
|
||||
pub port: u16,
|
||||
|
||||
/// Разрешить удаленные подключения
|
||||
#[serde(default = "default_allow_remote")]
|
||||
pub allow_remote: bool,
|
||||
|
||||
/// Таймаут соединения в секундах
|
||||
#[serde(default = "default_connection_timeout")]
|
||||
pub connection_timeout: u64,
|
||||
|
||||
/// Максимальное количество соединений
|
||||
#[serde(default = "default_max_connections")]
|
||||
pub max_connections: u32,
|
||||
|
||||
/// Размер буфера для сетевых операций в байтах
|
||||
#[serde(default = "default_buffer_size")]
|
||||
pub buffer_size: usize,
|
||||
}
|
||||
|
||||
/// Значения по умолчанию для NetworkConfig
|
||||
fn default_network_config() -> NetworkConfig {
|
||||
NetworkConfig {
|
||||
host: default_network_host(),
|
||||
port: default_network_port(),
|
||||
allow_remote: default_allow_remote(),
|
||||
connection_timeout: default_connection_timeout(),
|
||||
max_connections: default_max_connections(),
|
||||
buffer_size: default_buffer_size(),
|
||||
}
|
||||
}
|
||||
|
||||
fn default_network_host() -> String { "127.0.0.1".to_string() }
|
||||
fn default_network_port() -> u16 { 8080 }
|
||||
fn default_allow_remote() -> bool { false }
|
||||
fn default_connection_timeout() -> u64 { 30 }
|
||||
fn default_max_connections() -> u32 { 100 }
|
||||
fn default_buffer_size() -> usize { 8192 }
|
||||
|
||||
/// Конфигурация плагинов
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct PluginsConfig {
|
||||
/// Включена ли система плагинов
|
||||
#[serde(default = "default_plugins_enabled")]
|
||||
pub enabled: bool,
|
||||
|
||||
/// Директория для плагинов
|
||||
#[serde(default = "default_plugins_dir")]
|
||||
pub plugins_dir: String,
|
||||
|
||||
/// Включить изоляцию плагинов (sandbox)
|
||||
#[serde(default = "default_sandbox_enabled")]
|
||||
pub sandbox_enabled: bool,
|
||||
|
||||
/// Максимальное количество плагинов
|
||||
#[serde(default = "default_max_plugins")]
|
||||
pub max_plugins: usize,
|
||||
|
||||
/// Автозагрузка плагинов при старте
|
||||
#[serde(default = "default_auto_load")]
|
||||
pub auto_load: bool,
|
||||
|
||||
/// Включить горячую перезагрузку плагинов
|
||||
#[serde(default = "default_hot_reload")]
|
||||
pub hot_reload: bool,
|
||||
|
||||
/// Таймаут выполнения плагина в секундах
|
||||
#[serde(default = "default_plugin_timeout")]
|
||||
pub plugin_timeout_sec: u64,
|
||||
|
||||
/// Максимальный размер памяти плагина в МБ
|
||||
#[serde(default = "default_max_memory_mb")]
|
||||
pub max_memory_mb: u64,
|
||||
|
||||
/// Разрешенные API для плагинов
|
||||
#[serde(default = "default_allowed_apis")]
|
||||
pub allowed_apis: Vec<String>,
|
||||
|
||||
/// Запрещенные функции Lua
|
||||
#[serde(default = "default_blocked_functions")]
|
||||
pub blocked_functions: Vec<String>,
|
||||
}
|
||||
|
||||
/// Значения по умолчанию для PluginsConfig
|
||||
fn default_plugins_config() -> PluginsConfig {
|
||||
PluginsConfig {
|
||||
enabled: default_plugins_enabled(),
|
||||
plugins_dir: default_plugins_dir(),
|
||||
sandbox_enabled: default_sandbox_enabled(),
|
||||
max_plugins: default_max_plugins(),
|
||||
auto_load: default_auto_load(),
|
||||
hot_reload: default_hot_reload(),
|
||||
plugin_timeout_sec: default_plugin_timeout(),
|
||||
max_memory_mb: default_max_memory_mb(),
|
||||
allowed_apis: default_allowed_apis(),
|
||||
blocked_functions: default_blocked_functions(),
|
||||
}
|
||||
}
|
||||
|
||||
fn default_plugins_enabled() -> bool { true }
|
||||
fn default_plugins_dir() -> String { "./plugins".to_string() }
|
||||
fn default_sandbox_enabled() -> bool { true }
|
||||
fn default_max_plugins() -> usize { 50 }
|
||||
fn default_auto_load() -> bool { true }
|
||||
fn default_hot_reload() -> bool { false }
|
||||
fn default_plugin_timeout() -> u64 { 30 }
|
||||
fn default_max_memory_mb() -> u64 { 100 }
|
||||
fn default_allowed_apis() -> Vec<String> {
|
||||
vec![
|
||||
"database".to_string(),
|
||||
"table".to_string(),
|
||||
"query".to_string(),
|
||||
"index".to_string(),
|
||||
"event".to_string(),
|
||||
"log".to_string(),
|
||||
]
|
||||
}
|
||||
fn default_blocked_functions() -> Vec<String> {
|
||||
vec![
|
||||
"io.popen".to_string(),
|
||||
"os.execute".to_string(),
|
||||
"os.exit".to_string(),
|
||||
"debug.debug".to_string(),
|
||||
"debug.getregistry".to_string(),
|
||||
"debug.setmetatable".to_string(),
|
||||
]
|
||||
}
|
||||
|
||||
/// Конфигурация HTTP сервера
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct HttpConfig {
|
||||
/// Включен ли HTTP сервер
|
||||
pub enabled: bool,
|
||||
|
||||
/// Хост для HTTP сервера
|
||||
#[serde(default = "default_http_host")]
|
||||
pub host: String,
|
||||
|
||||
/// Порт HTTP сервера
|
||||
#[serde(default = "default_http_port")]
|
||||
pub port: u16,
|
||||
|
||||
/// Порт HTTPS сервера
|
||||
#[serde(default = "default_https_port")]
|
||||
pub https_port: u16,
|
||||
|
||||
/// Включена ли поддержка HTTP/2
|
||||
#[serde(default)]
|
||||
pub http2_enabled: bool,
|
||||
|
||||
/// Включена ли поддержка TLS
|
||||
#[serde(default)]
|
||||
pub tls_enabled: bool,
|
||||
|
||||
/// Путь к сертификату TLS
|
||||
#[serde(default)]
|
||||
pub tls_cert_path: Option<String>,
|
||||
|
||||
/// Путь к приватному ключу TLS
|
||||
#[serde(default)]
|
||||
pub tls_key_path: Option<String>,
|
||||
}
|
||||
|
||||
/// Значения по умолчанию для HttpConfig
|
||||
fn default_http_config() -> HttpConfig {
|
||||
HttpConfig {
|
||||
enabled: false,
|
||||
host: default_http_host(),
|
||||
port: default_http_port(),
|
||||
https_port: default_https_port(),
|
||||
http2_enabled: false,
|
||||
tls_enabled: false,
|
||||
tls_cert_path: None,
|
||||
tls_key_path: None,
|
||||
}
|
||||
}
|
||||
|
||||
fn default_http_host() -> String { "127.0.0.1".to_string() }
|
||||
fn default_http_port() -> u16 { 8080 }
|
||||
fn default_https_port() -> u16 { 8443 }
|
||||
|
||||
/// Конфигурация репликации
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct ReplicationConfig {
|
||||
/// Включена ли репликация
|
||||
pub enabled: bool,
|
||||
|
||||
/// Режим репликации
|
||||
#[serde(default = "default_replication_mode")]
|
||||
pub mode: String,
|
||||
|
||||
/// Мастер-сервер для репликации
|
||||
#[serde(default)]
|
||||
pub master: Option<String>,
|
||||
|
||||
/// Список слейв-серверов
|
||||
#[serde(default)]
|
||||
pub slaves: Vec<String>,
|
||||
}
|
||||
|
||||
/// Значения по умолчанию для ReplicationConfig
|
||||
fn default_replication_config() -> ReplicationConfig {
|
||||
ReplicationConfig {
|
||||
enabled: false,
|
||||
mode: default_replication_mode(),
|
||||
master: None,
|
||||
slaves: vec![],
|
||||
}
|
||||
}
|
||||
|
||||
fn default_replication_mode() -> String { "async".to_string() }
|
||||
|
||||
/// Конфигурация сервера
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct ServerConfig {
|
||||
/// Порт сервера
|
||||
#[serde(default = "default_server_port")]
|
||||
pub port: u16,
|
||||
|
||||
/// Хост сервера
|
||||
#[serde(default = "default_server_host")]
|
||||
pub host: String,
|
||||
|
||||
/// Максимальное количество одновременных соединений
|
||||
#[serde(default = "default_server_max_connections")]
|
||||
pub max_connections: u32,
|
||||
|
||||
/// Таймаут соединения в секундах
|
||||
#[serde(default = "default_server_timeout")]
|
||||
pub timeout: u64,
|
||||
|
||||
/// Размер пула потоков
|
||||
#[serde(default = "default_thread_pool_size")]
|
||||
pub thread_pool_size: usize,
|
||||
|
||||
/// Включить отладку
|
||||
#[serde(default = "default_debug_enabled")]
|
||||
pub debug: bool,
|
||||
|
||||
/// Путь к PID файлу
|
||||
#[serde(default)]
|
||||
pub pid_file: Option<String>,
|
||||
}
|
||||
|
||||
/// Значения по умолчанию для ServerConfig
|
||||
fn default_server_config() -> ServerConfig {
|
||||
ServerConfig {
|
||||
port: default_server_port(),
|
||||
host: default_server_host(),
|
||||
max_connections: default_server_max_connections(),
|
||||
timeout: default_server_timeout(),
|
||||
thread_pool_size: default_thread_pool_size(),
|
||||
debug: default_debug_enabled(),
|
||||
pid_file: None,
|
||||
}
|
||||
}
|
||||
|
||||
fn default_server_port() -> u16 { 5432 }
|
||||
fn default_server_host() -> String { "127.0.0.1".to_string() }
|
||||
fn default_server_max_connections() -> u32 { 100 }
|
||||
fn default_server_timeout() -> u64 { 30 }
|
||||
fn default_thread_pool_size() -> usize { 4 }
|
||||
fn default_debug_enabled() -> bool { false }
|
||||
|
||||
/// Конфигурация базы данных
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct DatabaseConfig {
|
||||
/// Директория для хранения данных
|
||||
#[serde(default = "default_data_dir")]
|
||||
pub data_dir: String,
|
||||
|
||||
/// Автоматически создавать базу данных при первом подключении
|
||||
#[serde(default = "default_auto_create")]
|
||||
pub auto_create: bool,
|
||||
|
||||
/// Режим транзакций
|
||||
#[serde(default = "default_transaction_mode")]
|
||||
pub transaction_mode: String,
|
||||
|
||||
/// Размер кэша в МБ
|
||||
#[serde(default = "default_cache_size")]
|
||||
pub cache_size_mb: u64,
|
||||
|
||||
/// Размер страницы в байтах
|
||||
#[serde(default = "default_page_size")]
|
||||
pub page_size: u32,
|
||||
|
||||
/// Включить MVCC (Multi-Version Concurrency Control)
|
||||
#[serde(default = "default_mvcc_enabled")]
|
||||
pub mvcc_enabled: bool,
|
||||
|
||||
/// Включить WAL (Write-Ahead Logging)
|
||||
#[serde(default = "default_wal_enabled")]
|
||||
pub wal_enabled: bool,
|
||||
|
||||
/// Максимальный размер WAL в МБ
|
||||
#[serde(default = "default_max_wal_size")]
|
||||
pub max_wal_size_mb: u64,
|
||||
|
||||
/// Автоматическая проверка целостности при запуске
|
||||
#[serde(default = "default_integrity_check")]
|
||||
pub integrity_check: bool,
|
||||
|
||||
/// Частота автоматического сохранения в секундах
|
||||
#[serde(default = "default_auto_save_interval")]
|
||||
pub auto_save_interval: u64,
|
||||
|
||||
/// Максимальное количество открытых файлов БД
|
||||
#[serde(default = "default_max_open_files")]
|
||||
pub max_open_files: u32,
|
||||
}
|
||||
|
||||
/// Значения по умолчанию для DatabaseConfig
|
||||
fn default_database_config() -> DatabaseConfig {
|
||||
DatabaseConfig {
|
||||
data_dir: default_data_dir(),
|
||||
auto_create: default_auto_create(),
|
||||
transaction_mode: default_transaction_mode(),
|
||||
cache_size_mb: default_cache_size(),
|
||||
page_size: default_page_size(),
|
||||
mvcc_enabled: default_mvcc_enabled(),
|
||||
wal_enabled: default_wal_enabled(),
|
||||
max_wal_size_mb: default_max_wal_size(),
|
||||
integrity_check: default_integrity_check(),
|
||||
auto_save_interval: default_auto_save_interval(),
|
||||
max_open_files: default_max_open_files(),
|
||||
}
|
||||
}
|
||||
|
||||
fn default_data_dir() -> String { "./data".to_string() }
|
||||
fn default_auto_create() -> bool { true }
|
||||
fn default_transaction_mode() -> String { "write_ahead_log".to_string() }
|
||||
fn default_cache_size() -> u64 { 100 }
|
||||
fn default_page_size() -> u32 { 8192 } // 8KB страницы по умолчанию
|
||||
fn default_mvcc_enabled() -> bool { true }
|
||||
fn default_wal_enabled() -> bool { true }
|
||||
fn default_max_wal_size() -> u64 { 100 }
|
||||
fn default_integrity_check() -> bool { true }
|
||||
fn default_auto_save_interval() -> u64 { 60 } // 60 секунд
|
||||
fn default_max_open_files() -> u32 { 1000 }
|
||||
|
||||
/// Конфигурация логгера
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct LoggingConfig {
|
||||
/// Уровень логирования
|
||||
#[serde(default = "default_log_level")]
|
||||
pub level: String,
|
||||
|
||||
/// Путь к файлу логов
|
||||
#[serde(default = "default_log_path")]
|
||||
pub log_file: String,
|
||||
|
||||
/// Максимальный размер файла логов в МБ
|
||||
#[serde(default = "default_max_log_size")]
|
||||
pub max_size_mb: u64,
|
||||
|
||||
/// Количество ротируемых файлов
|
||||
#[serde(default = "default_backup_count")]
|
||||
pub backup_count: u32,
|
||||
|
||||
/// Формат логов
|
||||
#[serde(default = "default_log_format")]
|
||||
pub format: String,
|
||||
|
||||
/// Включить логирование в stdout
|
||||
#[serde(default = "default_stdout_enabled")]
|
||||
pub stdout_enabled: bool,
|
||||
|
||||
/// Включить логирование в stderr
|
||||
#[serde(default = "default_stderr_enabled")]
|
||||
pub stderr_enabled: bool,
|
||||
|
||||
/// Включить логирование SQL запросов
|
||||
#[serde(default = "default_sql_logging")]
|
||||
pub sql_logging: bool,
|
||||
|
||||
/// Включить медленный лог (запросы дольше N секунд)
|
||||
#[serde(default)]
|
||||
pub slow_query_threshold_sec: Option<u64>,
|
||||
}
|
||||
|
||||
/// Значения по умолчанию для LoggingConfig
|
||||
fn default_logging_config() -> LoggingConfig {
|
||||
LoggingConfig {
|
||||
level: default_log_level(),
|
||||
log_file: default_log_path(),
|
||||
max_size_mb: default_max_log_size(),
|
||||
backup_count: default_backup_count(),
|
||||
format: default_log_format(),
|
||||
stdout_enabled: default_stdout_enabled(),
|
||||
stderr_enabled: default_stderr_enabled(),
|
||||
sql_logging: default_sql_logging(),
|
||||
slow_query_threshold_sec: None,
|
||||
}
|
||||
}
|
||||
|
||||
fn default_log_level() -> String { "info".to_string() }
|
||||
fn default_log_path() -> String { "flusql.log".to_string() }
|
||||
fn default_max_log_size() -> u64 { 10 }
|
||||
fn default_backup_count() -> u32 { 5 }
|
||||
fn default_log_format() -> String { "json".to_string() }
|
||||
fn default_stdout_enabled() -> bool { true }
|
||||
fn default_stderr_enabled() -> bool { false }
|
||||
fn default_sql_logging() -> bool { true }
|
||||
|
||||
/// Конфигурация Lua интерпретатора
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct LuaConfig {
|
||||
/// Включен ли Lua интерпретатор
|
||||
#[serde(default = "default_lua_enabled")]
|
||||
pub enabled: bool,
|
||||
|
||||
/// Путь к директории со скриптами
|
||||
#[serde(default = "default_lua_scripts_dir")]
|
||||
pub scripts_dir: String,
|
||||
|
||||
/// Максимальное время выполнения скрипта в секундах
|
||||
#[serde(default = "default_lua_timeout")]
|
||||
pub timeout_seconds: u64,
|
||||
|
||||
/// Максимальная память для Lua VM в МБ
|
||||
#[serde(default = "default_lua_memory_limit")]
|
||||
pub memory_limit_mb: u64,
|
||||
|
||||
/// Разрешить доступ к файловой системе
|
||||
#[serde(default = "default_lua_filesystem_access")]
|
||||
pub filesystem_access: bool,
|
||||
|
||||
/// Разрешить сетевые операции
|
||||
#[serde(default = "default_lua_network_access")]
|
||||
pub network_access: bool,
|
||||
|
||||
/// Список разрешенных модулей
|
||||
#[serde(default = "default_lua_allowed_modules")]
|
||||
pub allowed_modules: Vec<String>,
|
||||
}
|
||||
|
||||
/// Значения по умолчанию для LuaConfig
|
||||
fn default_lua_config() -> LuaConfig {
|
||||
LuaConfig {
|
||||
enabled: default_lua_enabled(),
|
||||
scripts_dir: default_lua_scripts_dir(),
|
||||
timeout_seconds: default_lua_timeout(),
|
||||
memory_limit_mb: default_lua_memory_limit(),
|
||||
filesystem_access: default_lua_filesystem_access(),
|
||||
network_access: default_lua_network_access(),
|
||||
allowed_modules: default_lua_allowed_modules(),
|
||||
}
|
||||
}
|
||||
|
||||
fn default_lua_enabled() -> bool { true }
|
||||
fn default_lua_scripts_dir() -> String { "./lua-scripts".to_string() }
|
||||
fn default_lua_timeout() -> u64 { 30 }
|
||||
fn default_lua_memory_limit() -> u64 { 100 }
|
||||
fn default_lua_filesystem_access() -> bool { false }
|
||||
fn default_lua_network_access() -> bool { false }
|
||||
fn default_lua_allowed_modules() -> Vec<String> {
|
||||
vec![
|
||||
"string".to_string(),
|
||||
"table".to_string(),
|
||||
"math".to_string(),
|
||||
"os".to_string(),
|
||||
]
|
||||
}
|
||||
|
||||
/// Конфигурация кластера
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct ClusterConfig {
|
||||
/// Включен ли режим кластера
|
||||
#[serde(default = "default_cluster_enabled")]
|
||||
pub enabled: bool,
|
||||
|
||||
/// Идентификатор узла
|
||||
#[serde(default = "default_node_id")]
|
||||
pub node_id: String,
|
||||
|
||||
/// Адрес узла
|
||||
#[serde(default = "default_node_address")]
|
||||
pub node_address: String,
|
||||
|
||||
/// Режим кластера
|
||||
#[serde(default = "default_cluster_mode")]
|
||||
pub mode: String,
|
||||
|
||||
/// Список узлов кластера
|
||||
#[serde(default)]
|
||||
pub nodes: Vec<String>,
|
||||
|
||||
/// Интервал heartbeat в секундах
|
||||
#[serde(default = "default_heartbeat_interval")]
|
||||
pub heartbeat_interval: u64,
|
||||
|
||||
/// Таймаут heartbeat в секундах
|
||||
#[serde(default = "default_heartbeat_timeout")]
|
||||
pub heartbeat_timeout: u64,
|
||||
|
||||
/// Включить автоматическое восстановление
|
||||
#[serde(default = "default_auto_recovery")]
|
||||
pub auto_recovery: bool,
|
||||
|
||||
/// Максимальное количество реплик
|
||||
#[serde(default = "default_max_replicas")]
|
||||
pub max_replicas: u32,
|
||||
}
|
||||
|
||||
/// Значения по умолчанию для ClusterConfig
|
||||
fn default_cluster_config() -> ClusterConfig {
|
||||
ClusterConfig {
|
||||
enabled: default_cluster_enabled(),
|
||||
node_id: default_node_id(),
|
||||
node_address: default_node_address(),
|
||||
mode: default_cluster_mode(),
|
||||
nodes: vec![],
|
||||
heartbeat_interval: default_heartbeat_interval(),
|
||||
heartbeat_timeout: default_heartbeat_timeout(),
|
||||
auto_recovery: default_auto_recovery(),
|
||||
max_replicas: default_max_replicas(),
|
||||
}
|
||||
}
|
||||
|
||||
fn default_cluster_enabled() -> bool { false }
|
||||
fn default_node_id() -> String { "node_1".to_string() }
|
||||
fn default_node_address() -> String { "127.0.0.1:8080".to_string() }
|
||||
fn default_cluster_mode() -> String { "single".to_string() }
|
||||
fn default_heartbeat_interval() -> u64 { 5 }
|
||||
fn default_heartbeat_timeout() -> u64 { 30 }
|
||||
fn default_auto_recovery() -> bool { true }
|
||||
fn default_max_replicas() -> u32 { 3 }
|
||||
|
||||
impl Default for Config {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
server: default_server_config(),
|
||||
database: default_database_config(),
|
||||
logging: default_logging_config(),
|
||||
lua: default_lua_config(),
|
||||
cluster: default_cluster_config(),
|
||||
plugins: default_plugins_config(),
|
||||
http: default_http_config(),
|
||||
replication: default_replication_config(),
|
||||
network: default_network_config(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Config {
|
||||
/// Загрузка конфигурации из файла
|
||||
pub fn load(path: &str) -> Result<Self, ConfigError> {
|
||||
let config_content = fs::read_to_string(path)
|
||||
.map_err(|e| ConfigError::IoError(e))?;
|
||||
|
||||
let config: Config = toml::from_str(&config_content)
|
||||
.map_err(|e| ConfigError::ParseError(e))?;
|
||||
|
||||
Ok(config)
|
||||
}
|
||||
|
||||
/// Создание конфигурации по умолчанию
|
||||
pub fn default_with_path(data_dir: &str) -> Self {
|
||||
let mut config = Self::default();
|
||||
config.database.data_dir = data_dir.to_string();
|
||||
config
|
||||
}
|
||||
|
||||
/// Получение пути к директории данных для базы данных
|
||||
pub fn get_data_path(&self, db_name: &str) -> String {
|
||||
format!("{}/{}", self.database.data_dir, db_name)
|
||||
}
|
||||
|
||||
/// Сохранение конфигурации в файл
|
||||
pub fn save(&self, path: &str) -> Result<(), ConfigError> {
|
||||
let config_content = toml::to_string_pretty(self)
|
||||
.map_err(|e| ConfigError::SerializeError(e))?;
|
||||
|
||||
// Создаем директорию если она не существует
|
||||
if let Some(parent) = Path::new(path).parent() {
|
||||
fs::create_dir_all(parent)
|
||||
.map_err(|e| ConfigError::IoError(e))?;
|
||||
}
|
||||
|
||||
fs::write(path, config_content)
|
||||
.map_err(|e| ConfigError::IoError(e))
|
||||
}
|
||||
|
||||
/// Создание файла конфигурации по умолчанию
|
||||
pub fn create_default_config(path: &str) -> Result<(), ConfigError> {
|
||||
let default_config = Self::default();
|
||||
default_config.save(path)
|
||||
}
|
||||
|
||||
/// Получение конфигурации из переменных окружения или файла
|
||||
pub fn from_env_or_file(default_path: &str) -> Result<Self, ConfigError> {
|
||||
// Сначала пробуем загрузить из переменной окружения
|
||||
if let Ok(config_path) = std::env::var("FLUSQL_CONFIG") {
|
||||
return Self::load(&config_path);
|
||||
}
|
||||
|
||||
// Пробуем загрузить из текущей директории
|
||||
if Path::new(default_path).exists() {
|
||||
return Self::load(default_path);
|
||||
}
|
||||
|
||||
// Пробуем загрузить из домашней директории
|
||||
if let Ok(home_dir) = std::env::var("HOME") {
|
||||
let home_config = format!("{}/.config/flusql/config.toml", home_dir);
|
||||
if Path::new(&home_config).exists() {
|
||||
return Self::load(&home_config);
|
||||
}
|
||||
}
|
||||
|
||||
// Пробуем загрузить из /etc
|
||||
let etc_config = "/etc/flusql/config.toml";
|
||||
if Path::new(etc_config).exists() {
|
||||
return Self::load(etc_config);
|
||||
}
|
||||
|
||||
// Создаем конфигурацию по умолчанию
|
||||
Ok(Self::default())
|
||||
}
|
||||
|
||||
/// Проверка валидности конфигурации
|
||||
pub fn validate(&self) -> Result<(), ConfigError> {
|
||||
// Проверяем размер страницы (должен быть степенью двойки и в разумных пределах)
|
||||
if self.database.page_size < 512 || self.database.page_size > 65536 {
|
||||
return Err(ConfigError::Invalid(format!(
|
||||
"Page size must be between 512 and 65536 bytes, got {}",
|
||||
self.database.page_size
|
||||
)));
|
||||
}
|
||||
|
||||
// Проверяем что page_size является степенью двойки
|
||||
if self.database.page_size & (self.database.page_size - 1) != 0 {
|
||||
return Err(ConfigError::Invalid(format!(
|
||||
"Page size must be a power of two, got {}",
|
||||
self.database.page_size
|
||||
)));
|
||||
}
|
||||
|
||||
// Проверяем порты
|
||||
// Исправление: убраны все проверки на > 65535, так как тип u16 гарантирует этот предел
|
||||
// Оставляем только проверку на 0 (порт 0 недопустим для сервера)
|
||||
if self.server.port == 0 {
|
||||
return Err(ConfigError::Invalid(
|
||||
"Server port cannot be 0".to_string()
|
||||
));
|
||||
}
|
||||
|
||||
if self.http.enabled {
|
||||
// Исправление: убраны все проверки на > 65535, так как тип u16 гарантирует этот предел
|
||||
// Оставляем только проверку на 0 (порт 0 недопустим для HTTP сервера)
|
||||
if self.http.port == 0 {
|
||||
return Err(ConfigError::Invalid(
|
||||
"HTTP port cannot be 0".to_string()
|
||||
));
|
||||
}
|
||||
|
||||
if self.http.tls_enabled {
|
||||
if self.http.tls_cert_path.is_none() || self.http.tls_key_path.is_none() {
|
||||
return Err(ConfigError::Invalid(
|
||||
"TLS requires both certificate and key paths".to_string()
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Проверяем директорию данных
|
||||
if self.database.data_dir.trim().is_empty() {
|
||||
return Err(ConfigError::Invalid("Data directory cannot be empty".to_string()));
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// Ошибки конфигурации
|
||||
#[derive(Debug, Error)]
|
||||
pub enum ConfigError {
|
||||
#[error("IO error: {0}")]
|
||||
IoError(std::io::Error),
|
||||
|
||||
#[error("Parse error: {0}")]
|
||||
ParseError(toml::de::Error),
|
||||
|
||||
#[error("Serialize error: {0}")]
|
||||
SerializeError(toml::ser::Error),
|
||||
|
||||
#[error("Configuration not found")]
|
||||
NotFound,
|
||||
|
||||
#[error("Invalid configuration: {0}")]
|
||||
Invalid(String),
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user