/* * Copyright 2026 Safronov Grigorii * * Licensed under the CDDL, Version 1.0 (the "License"); * you may not use this file except in compliance with the License. * * You may obtain a copy of the License at * https://opensource.org/licenses/CDDL-1.0 */ // Файл: internal/config/config.go // Назначение: Загрузка и парсинг TOML-конфигурации, валидация параметров, // предоставление доступа к настройкам кластера, хранилища и REPL. package config import ( "fmt" "strings" "time" "github.com/BurntSushi/toml" ) type Config struct { Cluster ClusterConfig `toml:"cluster"` Storage StorageConfig `toml:"storage"` Repl ReplConfig `toml:"repl"` Log LogConfig `toml:"log"` API APIConfig `toml:"api"` Replication ReplicationConfig `toml:"replication"` Plugins PluginsConfig `toml:"plugins"` Compression CompressionConfig `toml:"compression"` WebUI WebUIConfig `toml:"webui"` Performance PerformanceConfig `toml:"performance"` Security SecurityConfig `toml:"security"` Monitoring MonitoringConfig `toml:"monitoring"` Recovery RecoveryConfig `toml:"recovery"` WAL WALConfig `toml:"wal"` MVCC MVCCConfig `toml:"mvcc"` Transactions TransactionsConfig `toml:"transactions"` ACL ACLConfig `toml:"acl"` ClusterTLS TLSConfig `toml:"cluster_tls"` Backpressure BackpressureConfig `toml:"backpressure"` RuntimeLimits RuntimeLimitsConfig `toml:"runtime_limits"` Autoscaling AutoscalingConfig `toml:"autoscaling"` SchemaMigration SchemaMigrationConfig `toml:"schema_migration"` Backup BackupConfig `toml:"backup"` Engines EnginesConfig `toml:"engines"` } type ClusterConfig struct { Name string `toml:"name"` NodeIP string `toml:"node_ip"` NodePort int `toml:"node_port"` RaftPort int `toml:"raft_port"` RaftDataDir string `toml:"raft_data_dir"` Bootstrap bool `toml:"bootstrap"` Nodes []string `toml:"nodes"` HeartbeatTimeoutMs int `toml:"heartbeat_timeout_ms"` ElectionTimeoutMs int `toml:"election_timeout_ms"` CommitTimeoutMs int `toml:"commit_timeout_ms"` SnapshotIntervalMin int `toml:"snapshot_interval_min"` SnapshotThreshold int `toml:"snapshot_threshold"` SplitBrainPrevention bool `toml:"split_brain_prevention"` RecoveryTimeoutSec int `toml:"recovery_timeout_sec"` Region string `toml:"region"` PriorityZone int `toml:"priority_zone"` } type StorageConfig struct { PageSizeMB int `toml:"page_size_mb"` MaxCollections int `toml:"max_collections"` MaxDocumentsPerCollection int `toml:"max_documents_per_collection"` DefaultEngine string `toml:"default_engine"` EnableCustomEngines bool `toml:"enable_custom_engines"` } type ReplConfig struct { PromptColor string `toml:"prompt_color"` HistorySize int `toml:"history_size"` } type LogConfig struct { LogFile string `toml:"log_file"` LogLevel string `toml:"log_level"` } type APIConfig struct { Port int `toml:"port"` } type ReplicationConfig struct { Enabled bool `toml:"enabled"` MasterMaster bool `toml:"master_master"` SyncReplication bool `toml:"sync_replication"` ReplicationTimeoutMs int `toml:"replication_timeout_ms"` } type PluginsConfig struct { Enabled bool `toml:"enabled"` ScriptDir string `toml:"script_dir"` AllowList []string `toml:"allow_list"` MaxCPUTimeMs int `toml:"max_cpu_time_ms"` MaxMemoryMB int `toml:"max_memory_mb"` MaxExecutionTimeSec int `toml:"max_execution_time_sec"` MaxInstructions int64 `toml:"max_instructions"` HotReloadIntervalSec int `toml:"hot_reload_interval_sec"` MaxEventLogSize int `toml:"max_event_log_size"` LoadTimeoutSec int `toml:"load_timeout_sec"` MaxLuaStates int `toml:"max_lua_states"` LuaStateTTLSec int `toml:"lua_state_ttl_sec"` EnginePluginDir string `toml:"engine_plugin_dir"` } type CompressionConfig struct { Enabled bool `toml:"enabled"` Algorithm string `toml:"algorithm"` Level int `toml:"level"` MinSize int `toml:"min_size"` } type WebUIConfig struct { Enabled bool `toml:"enabled"` Port int `toml:"port"` Theme string `toml:"theme"` } type PerformanceConfig struct { EnablePipeline bool `toml:"enable_pipeline"` BatchSize int `toml:"batch_size"` ReadFromFollower bool `toml:"read_from_follower"` MaxConnections int `toml:"max_connections"` } type SecurityConfig struct { EnableTLS bool `toml:"enable_tls"` CertFile string `toml:"cert_file"` KeyFile string `toml:"key_file"` CAFile string `toml:"ca_file"` MinVersion string `toml:"min_version"` } type MonitoringConfig struct { EnableMetrics bool `toml:"enable_metrics"` MetricsPort int `toml:"metrics_port"` EnableTracing bool `toml:"enable_tracing"` TraceSampleRate float64 `toml:"trace_sample_rate"` } type RecoveryConfig struct { AutoRejoin bool `toml:"auto_rejoin"` MaxRetrySec int `toml:"max_retry_sec"` DataReplicationTimeoutSec int `toml:"data_replication_timeout_sec"` StaleReadTimeoutSec int `toml:"stale_read_timeout_sec"` } // ========== НОВЫЕ КОНФИГУРАЦИОННЫЕ СТРУКТУРЫ ========== // WALConfig настройки Write-Ahead Log type WALConfig struct { SegmentSizeMB int `toml:"segment_size_mb"` SyncIntervalSec int `toml:"sync_interval_sec"` BatchSize int `toml:"batch_size"` RecoveryWorkers int `toml:"recovery_workers"` Enabled bool `toml:"enabled"` AsyncRecovery bool `toml:"async_recovery"` AsyncRecoveryWorkers int `toml:"async_recovery_workers"` AsyncRecoveryBuffer int `toml:"async_recovery_buffer"` } // MVCCConfig настройки Multi-Version Concurrency Control type MVCCConfig struct { MaxVersionsPerDoc int `toml:"max_versions_per_doc"` VisibilityMapSize int `toml:"visibility_map_size"` PruneIntervalMin int `toml:"prune_interval_min"` RetentionDays int `toml:"retention_days"` ReadCacheSize int `toml:"read_cache_size"` ReadCacheTTLSec int `toml:"read_cache_ttl_sec"` } // TransactionsConfig настройки транзакций type TransactionsConfig struct { DefaultTimeoutSec int `toml:"default_timeout_sec"` DeadlockCheckIntervalSec int `toml:"deadlock_check_interval_sec"` MaxSavepointsPerTx int `toml:"max_savepoints_per_tx"` TwoPhaseCommitTimeoutSec int `toml:"two_phase_commit_timeout_sec"` Enabled bool `toml:"enabled"` CheckpointIntervalSec int `toml:"checkpoint_interval_sec"` } // ACLConfig настройки Access Control List type ACLConfig struct { MaxDeniedLogSize int `toml:"max_denied_log_size"` TemporaryGrantTTLHours int `toml:"temporary_grant_ttl_hours"` EnableRoleHierarchy bool `toml:"enable_role_hierarchy"` CacheTTLSec int `toml:"cache_ttl_sec"` } // ========== НОВЫЕ СЕКЦИИ КОНФИГУРАЦИИ ========== // TLSConfig настройки TLS для межузлового общения type TLSConfig struct { Enabled bool `toml:"enabled"` CertFile string `toml:"cert_file"` KeyFile string `toml:"key_file"` CAFile string `toml:"ca_file"` MinVersion string `toml:"min_version"` MutualAuth bool `toml:"mutual_auth"` KeyRotationDays int `toml:"key_rotation_days"` AutoGenerate bool `toml:"auto_generate"` } // BackpressureConfig настройки backpressure type BackpressureConfig struct { Enabled bool `toml:"enabled"` CPUThreshold float64 `toml:"cpu_threshold"` MemoryThreshold float64 `toml:"memory_threshold"` QueueSizeThreshold int `toml:"queue_size_threshold"` ConnectionThreshold int `toml:"connection_threshold"` CheckIntervalMs int `toml:"check_interval_ms"` LowDelayMs int64 `toml:"low_delay_ms"` MediumRejectProb uint32 `toml:"medium_reject_prob"` HighRejectProb uint32 `toml:"high_reject_prob"` } // RuntimeLimitsConfig настройки runtime-ограничений type RuntimeLimitsConfig struct { Enabled bool `toml:"enabled"` GlobalMaxDocSizeMB int `toml:"global_max_doc_size_mb"` GlobalMaxCollSizeMB int64 `toml:"global_max_coll_size_mb"` GlobalMaxDocsPerColl int64 `toml:"global_max_docs_per_coll"` } // AutoscalingConfig настройки автомасштабирования type AutoscalingConfig struct { Enabled bool `toml:"enabled"` MinNodes int `toml:"min_nodes"` MaxNodes int `toml:"max_nodes"` ScaleUpThreshold float64 `toml:"scale_up_threshold"` ScaleDownThreshold float64 `toml:"scale_down_threshold"` ScaleUpCooldownSec int `toml:"scale_up_cooldown_sec"` ScaleDownCooldownSec int `toml:"scale_down_cooldown_sec"` EvaluationIntervalSec int `toml:"evaluation_interval_sec"` PredictiveEnabled bool `toml:"predictive_enabled"` MaxScaleUpNodes int `toml:"max_scale_up_nodes"` MaxScaleDownNodes int `toml:"max_scale_down_nodes"` } // SchemaMigrationConfig настройки миграции схемы type SchemaMigrationConfig struct { Enabled bool `toml:"enabled"` MigrationDir string `toml:"migration_dir"` AutoMigrate bool `toml:"auto_migrate"` TargetVersion string `toml:"target_version"` } // BackupConfig настройки бэкапов type BackupConfig struct { Enabled bool `toml:"enabled"` BackupDir string `toml:"backup_dir"` MaxConcurrent int `toml:"max_concurrent"` CompressEnabled bool `toml:"compress_enabled"` RetentionDays int `toml:"retention_days"` } // EnginesConfig настройки кастомных движков хранения type EnginesConfig struct { Row EngineConfig `toml:"row"` Columnar EngineConfig `toml:"columnar"` Document EngineConfig `toml:"document"` KV EngineConfig `toml:"kv"` TS EngineConfig `toml:"ts"` Graph EngineConfig `toml:"graph"` } // EngineConfig конфигурация конкретного движка type EngineConfig struct { Enabled bool `toml:"enabled"` Description string `toml:"description"` Config map[string]interface{} `toml:"config"` } // ValidationResult представляет результат валидации конфигурации type ValidationResult struct { Valid bool Errors []error Warnings []error } // ========== Методы для существующих конфигураций ========== // GetSegmentSize возвращает размер сегмента WAL в байтах func (w *WALConfig) GetSegmentSize() int64 { if w.SegmentSizeMB <= 0 { return 64 * 1024 * 1024 } return int64(w.SegmentSizeMB) * 1024 * 1024 } // GetSyncInterval возвращает интервал синхронизации WAL func (w *WALConfig) GetSyncInterval() time.Duration { if w.SyncIntervalSec <= 0 { return 5 * time.Second } return time.Duration(w.SyncIntervalSec) * time.Second } // GetBatchSize возвращает размер пакета WAL func (w *WALConfig) GetBatchSize() int { if w.BatchSize <= 0 { return 100 } return w.BatchSize } // GetRecoveryWorkers возвращает количество воркеров для parallel recovery func (w *WALConfig) GetRecoveryWorkers() int { if w.RecoveryWorkers <= 0 { return 4 } return w.RecoveryWorkers } // IsWALEnabled возвращает статус WAL func (w *WALConfig) IsWALEnabled() bool { return w.Enabled } // IsAsyncRecoveryEnabled возвращает статус асинхронного восстановления func (w *WALConfig) IsAsyncRecoveryEnabled() bool { return w.AsyncRecovery } // GetAsyncRecoveryWorkers возвращает количество воркеров для асинхронного восстановления func (w *WALConfig) GetAsyncRecoveryWorkers() int { if w.AsyncRecoveryWorkers <= 0 { return 4 } return w.AsyncRecoveryWorkers } // GetAsyncRecoveryBuffer возвращает размер буфера для асинхронного восстановления func (w *WALConfig) GetAsyncRecoveryBuffer() int { if w.AsyncRecoveryBuffer <= 0 { return 10000 } return w.AsyncRecoveryBuffer } // GetMaxVersionsPerDoc возвращает максимальное количество версий на документ func (m *MVCCConfig) GetMaxVersionsPerDoc() int { if m.MaxVersionsPerDoc <= 0 { return 10 } return m.MaxVersionsPerDoc } // GetVisibilityMapSize возвращает размер карты видимости func (m *MVCCConfig) GetVisibilityMapSize() int { if m.VisibilityMapSize <= 0 { return 1024 * 1024 } return m.VisibilityMapSize } // GetPruneInterval возвращает интервал очистки версий func (m *MVCCConfig) GetPruneInterval() time.Duration { if m.PruneIntervalMin <= 0 { return 5 * time.Minute } return time.Duration(m.PruneIntervalMin) * time.Minute } // GetRetentionDays возвращает дни хранения версий func (m *MVCCConfig) GetRetentionDays() int { if m.RetentionDays <= 0 { return 7 } return m.RetentionDays } // GetReadCacheSize возвращает размер кэша чтения func (m *MVCCConfig) GetReadCacheSize() int { if m.ReadCacheSize <= 0 { return 10000 } return m.ReadCacheSize } // GetReadCacheTTL возвращает TTL кэша чтения func (m *MVCCConfig) GetReadCacheTTL() time.Duration { if m.ReadCacheTTLSec <= 0 { return 300 * time.Second } return time.Duration(m.ReadCacheTTLSec) * time.Second } // GetDefaultTimeout возвращает таймаут транзакции по умолчанию func (t *TransactionsConfig) GetDefaultTimeout() time.Duration { if t.DefaultTimeoutSec <= 0 { return 30 * time.Second } return time.Duration(t.DefaultTimeoutSec) * time.Second } // GetDeadlockCheckInterval возвращает интервал проверки дедлоков func (t *TransactionsConfig) GetDeadlockCheckInterval() time.Duration { if t.DeadlockCheckIntervalSec <= 0 { return 1 * time.Second } return time.Duration(t.DeadlockCheckIntervalSec) * time.Second } // GetMaxSavepointsPerTx возвращает максимальное количество точек сохранения func (t *TransactionsConfig) GetMaxSavepointsPerTx() int { if t.MaxSavepointsPerTx <= 0 { return 100 } return t.MaxSavepointsPerTx } // GetTwoPhaseCommitTimeout возвращает таймаут двухфазного коммита func (t *TransactionsConfig) GetTwoPhaseCommitTimeout() time.Duration { if t.TwoPhaseCommitTimeoutSec <= 0 { return 10 * time.Second } return time.Duration(t.TwoPhaseCommitTimeoutSec) * time.Second } // IsTransactionsEnabled возвращает статус поддержки транзакций func (t *TransactionsConfig) IsTransactionsEnabled() bool { return t.Enabled } // GetCheckpointInterval возвращает интервал чекпоинтов func (t *TransactionsConfig) GetCheckpointInterval() int64 { if t.CheckpointIntervalSec <= 0 { return 300 } return int64(t.CheckpointIntervalSec) } // GetMaxDeniedLogSize возвращает максимальный размер лога отказов func (a *ACLConfig) GetMaxDeniedLogSize() int { if a.MaxDeniedLogSize <= 0 { return 10000 } return a.MaxDeniedLogSize } // GetTemporaryGrantTTL возвращает TTL временных разрешений func (a *ACLConfig) GetTemporaryGrantTTL() time.Duration { if a.TemporaryGrantTTLHours <= 0 { return 24 * time.Hour } return time.Duration(a.TemporaryGrantTTLHours) * time.Hour } // IsRoleHierarchyEnabled возвращает статус иерархии ролей func (a *ACLConfig) IsRoleHierarchyEnabled() bool { return a.EnableRoleHierarchy } // GetCacheTTL возвращает TTL кэша ACL func (a *ACLConfig) GetCacheTTL() time.Duration { if a.CacheTTLSec <= 0 { return 60 * time.Second } return time.Duration(a.CacheTTLSec) * time.Second } // ========== Методы PluginsConfig (расширенные) ========== // GetMaxCPUTime возвращает лимит CPU для плагина func (p *PluginsConfig) GetMaxCPUTime() time.Duration { if p.MaxCPUTimeMs <= 0 { return 100 * time.Millisecond } return time.Duration(p.MaxCPUTimeMs) * time.Millisecond } // GetMaxMemory возвращает лимит памяти для плагина в байтах func (p *PluginsConfig) GetMaxMemory() int64 { if p.MaxMemoryMB <= 0 { return 50 * 1024 * 1024 } return int64(p.MaxMemoryMB) * 1024 * 1024 } // GetMaxExecutionTime возвращает лимит времени выполнения плагина func (p *PluginsConfig) GetMaxExecutionTime() time.Duration { if p.MaxExecutionTimeSec <= 0 { return 5 * time.Second } return time.Duration(p.MaxExecutionTimeSec) * time.Second } // GetMaxInstructions возвращает лимит инструкций Lua func (p *PluginsConfig) GetMaxInstructions() int64 { if p.MaxInstructions <= 0 { return 1000000 } return p.MaxInstructions } // GetHotReloadInterval возвращает интервал проверки изменений плагинов func (p *PluginsConfig) GetHotReloadInterval() time.Duration { if p.HotReloadIntervalSec <= 0 { return 30 * time.Second } return time.Duration(p.HotReloadIntervalSec) * time.Second } // GetMaxEventLogSize возвращает максимальный размер лога событий плагина func (p *PluginsConfig) GetMaxEventLogSize() int { if p.MaxEventLogSize <= 0 { return 1000 } return p.MaxEventLogSize } // GetLoadTimeout возвращает таймаут загрузки плагина func (p *PluginsConfig) GetLoadTimeout() time.Duration { if p.LoadTimeoutSec <= 0 { return 10 * time.Second } return time.Duration(p.LoadTimeoutSec) * time.Second } // GetMaxLuaStates возвращает максимальное количество Lua-состояний func (p *PluginsConfig) GetMaxLuaStates() int { if p.MaxLuaStates <= 0 { return 100 } return p.MaxLuaStates } // GetLuaStateTTL возвращает TTL Lua-состояния func (p *PluginsConfig) GetLuaStateTTL() time.Duration { if p.LuaStateTTLSec <= 0 { return 10 * time.Minute } return time.Duration(p.LuaStateTTLSec) * time.Second } // GetEnginePluginDir возвращает директорию с движками-плагинами func (p *PluginsConfig) GetEnginePluginDir() string { if p.EnginePluginDir == "" { return "engines" } return p.EnginePluginDir } // ========== Методы для новых конфигураций ========== // GetTLSMinVersion возвращает минимальную версию TLS func (t *TLSConfig) GetTLSMinVersion() string { if t.MinVersion == "" { return "1.2" } return t.MinVersion } // IsTLSEnabled возвращает статус TLS func (t *TLSConfig) IsTLSEnabled() bool { return t.Enabled } // IsMutualAuthEnabled возвращает статус взаимной аутентификации func (t *TLSConfig) IsMutualAuthEnabled() bool { return t.MutualAuth } // GetKeyRotationDays возвращает дни ротации ключей func (t *TLSConfig) GetKeyRotationDays() int { if t.KeyRotationDays <= 0 { return 30 } return t.KeyRotationDays } // IsAutoGenerateEnabled возвращает статус автогенерации сертификатов func (t *TLSConfig) IsAutoGenerateEnabled() bool { return t.AutoGenerate } // IsBackpressureEnabled возвращает статус backpressure func (b *BackpressureConfig) IsBackpressureEnabled() bool { return b.Enabled } // GetCPUThreshold возвращает порог CPU func (b *BackpressureConfig) GetCPUThreshold() float64 { if b.CPUThreshold <= 0 { return 0.8 } if b.CPUThreshold > 1.0 { return 1.0 } return b.CPUThreshold } // GetMemoryThreshold возвращает порог памяти func (b *BackpressureConfig) GetMemoryThreshold() float64 { if b.MemoryThreshold <= 0 { return 0.85 } if b.MemoryThreshold > 1.0 { return 1.0 } return b.MemoryThreshold } // GetQueueSizeThreshold возвращает порог размера очереди func (b *BackpressureConfig) GetQueueSizeThreshold() int { if b.QueueSizeThreshold <= 0 { return 10000 } return b.QueueSizeThreshold } // GetConnectionThreshold возвращает порог количества соединений func (b *BackpressureConfig) GetConnectionThreshold() int { if b.ConnectionThreshold <= 0 { return 5000 } return b.ConnectionThreshold } // GetCheckInterval возвращает интервал проверки func (b *BackpressureConfig) GetCheckInterval() time.Duration { if b.CheckIntervalMs <= 0 { return 1 * time.Second } return time.Duration(b.CheckIntervalMs) * time.Millisecond } // GetLowDelay возвращает задержку при низкой нагрузке func (b *BackpressureConfig) GetLowDelay() time.Duration { if b.LowDelayMs <= 0 { return 100 * time.Millisecond } return time.Duration(b.LowDelayMs) * time.Millisecond } // GetMediumRejectProb возвращает вероятность отклонения при средней нагрузке func (b *BackpressureConfig) GetMediumRejectProb() uint32 { if b.MediumRejectProb > 100 { return 100 } return b.MediumRejectProb } // GetHighRejectProb возвращает вероятность отклонения при высокой нагрузке func (b *BackpressureConfig) GetHighRejectProb() uint32 { if b.HighRejectProb > 100 { return 100 } return b.HighRejectProb } // IsRuntimeLimitsEnabled возвращает статус runtime-ограничений func (r *RuntimeLimitsConfig) IsRuntimeLimitsEnabled() bool { return r.Enabled } // GetGlobalMaxDocSizeMB возвращает максимальный размер документа func (r *RuntimeLimitsConfig) GetGlobalMaxDocSizeMB() int { if r.GlobalMaxDocSizeMB <= 0 { return 16 } return r.GlobalMaxDocSizeMB } // GetGlobalMaxCollSizeMB возвращает максимальный размер коллекции func (r *RuntimeLimitsConfig) GetGlobalMaxCollSizeMB() int64 { if r.GlobalMaxCollSizeMB <= 0 { return 10240 } return r.GlobalMaxCollSizeMB } // GetGlobalMaxDocsPerColl возвращает максимальное количество документов в коллекции func (r *RuntimeLimitsConfig) GetGlobalMaxDocsPerColl() int64 { if r.GlobalMaxDocsPerColl <= 0 { return 10000000 } return r.GlobalMaxDocsPerColl } // IsAutoscalingEnabled возвращает статус автомасштабирования func (a *AutoscalingConfig) IsAutoscalingEnabled() bool { return a.Enabled } // GetMinNodes возвращает минимальное количество узлов func (a *AutoscalingConfig) GetMinNodes() int { if a.MinNodes <= 0 { return 1 } return a.MinNodes } // GetMaxNodes возвращает максимальное количество узлов func (a *AutoscalingConfig) GetMaxNodes() int { if a.MaxNodes <= 0 { return 10 } return a.MaxNodes } // GetScaleUpThreshold возвращает порог для увеличения func (a *AutoscalingConfig) GetScaleUpThreshold() float64 { if a.ScaleUpThreshold <= 0 { return 0.75 } if a.ScaleUpThreshold > 1.0 { return 1.0 } return a.ScaleUpThreshold } // GetScaleDownThreshold возвращает порог для уменьшения func (a *AutoscalingConfig) GetScaleDownThreshold() float64 { if a.ScaleDownThreshold <= 0 { return 0.30 } return a.ScaleDownThreshold } // GetScaleUpCooldown возвращает cooldown после увеличения func (a *AutoscalingConfig) GetScaleUpCooldown() time.Duration { if a.ScaleUpCooldownSec <= 0 { return 5 * time.Minute } return time.Duration(a.ScaleUpCooldownSec) * time.Second } // GetScaleDownCooldown возвращает cooldown после уменьшения func (a *AutoscalingConfig) GetScaleDownCooldown() time.Duration { if a.ScaleDownCooldownSec <= 0 { return 10 * time.Minute } return time.Duration(a.ScaleDownCooldownSec) * time.Second } // GetEvaluationInterval возвращает интервал оценки func (a *AutoscalingConfig) GetEvaluationInterval() time.Duration { if a.EvaluationIntervalSec <= 0 { return 30 * time.Second } return time.Duration(a.EvaluationIntervalSec) * time.Second } // IsPredictiveEnabled возвращает статус прогнозирования нагрузки func (a *AutoscalingConfig) IsPredictiveEnabled() bool { return a.PredictiveEnabled } // GetMaxScaleUpNodes возвращает максимальное количество узлов за одно увеличение func (a *AutoscalingConfig) GetMaxScaleUpNodes() int { if a.MaxScaleUpNodes <= 0 { return 3 } return a.MaxScaleUpNodes } // GetMaxScaleDownNodes возвращает максимальное количество узлов за одно уменьшение func (a *AutoscalingConfig) GetMaxScaleDownNodes() int { if a.MaxScaleDownNodes <= 0 { return 2 } return a.MaxScaleDownNodes } // IsSchemaMigrationEnabled возвращает статус миграции схемы func (s *SchemaMigrationConfig) IsSchemaMigrationEnabled() bool { return s.Enabled } // GetMigrationDir возвращает директорию миграций func (s *SchemaMigrationConfig) GetMigrationDir() string { if s.MigrationDir == "" { return "migrations" } return s.MigrationDir } // IsAutoMigrateEnabled возвращает статус автоматической миграции func (s *SchemaMigrationConfig) IsAutoMigrateEnabled() bool { return s.AutoMigrate } // GetTargetVersion возвращает целевую версию схемы func (s *SchemaMigrationConfig) GetTargetVersion() string { if s.TargetVersion == "" { return "latest" } return s.TargetVersion } // IsBackupEnabled возвращает статус бэкапов func (b *BackupConfig) IsBackupEnabled() bool { return b.Enabled } // GetBackupDir возвращает директорию бэкапов func (b *BackupConfig) GetBackupDir() string { if b.BackupDir == "" { return "backups" } return b.BackupDir } // GetMaxConcurrentBackups возвращает максимальное количество одновременных бэкапов func (b *BackupConfig) GetMaxConcurrentBackups() int { if b.MaxConcurrent <= 0 { return 1 } return b.MaxConcurrent } // IsCompressEnabled возвращает статус сжатия бэкапов func (b *BackupConfig) IsCompressEnabled() bool { return b.CompressEnabled } // GetBackupRetentionDays возвращает дни хранения бэкапов func (b *BackupConfig) GetBackupRetentionDays() int { if b.RetentionDays <= 0 { return 7 } return b.RetentionDays } // ========== Методы для конфигурации движков ========== // GetDefaultEngine возвращает движок хранения по умолчанию func (s *StorageConfig) GetDefaultEngine() string { if s.DefaultEngine == "" { return "row" } return s.DefaultEngine } // IsCustomEnginesEnabled возвращает статус поддержки кастомных движков func (s *StorageConfig) IsCustomEnginesEnabled() bool { return s.EnableCustomEngines } // IsEngineEnabled проверяет, включён ли конкретный движок func (e *EnginesConfig) IsEngineEnabled(name string) bool { switch name { case "row": return e.Row.Enabled case "columnar": return e.Columnar.Enabled case "document": return e.Document.Enabled case "kv": return e.KV.Enabled case "ts": return e.TS.Enabled case "graph": return e.Graph.Enabled default: return false } } // GetEngineConfig возвращает конфигурацию конкретного движка func (e *EnginesConfig) GetEngineConfig(name string) map[string]interface{} { switch name { case "row": return e.Row.Config case "columnar": return e.Columnar.Config case "document": return e.Document.Config case "kv": return e.KV.Config case "ts": return e.TS.Config case "graph": return e.Graph.Config default: return make(map[string]interface{}) } } // GetEngineDescription возвращает описание движка func (e *EnginesConfig) GetEngineDescription(name string) string { switch name { case "row": return e.Row.Description case "columnar": return e.Columnar.Description case "document": return e.Document.Description case "kv": return e.KV.Description case "ts": return e.TS.Description case "graph": return e.Graph.Description default: return "" } } // ========== Методы ClusterConfig ========== func (c *ClusterConfig) GetHeartbeatTimeout() time.Duration { if c.HeartbeatTimeoutMs <= 0 { return 1000 * time.Millisecond } return time.Duration(c.HeartbeatTimeoutMs) * time.Millisecond } func (c *ClusterConfig) GetElectionTimeout() time.Duration { if c.ElectionTimeoutMs <= 0 { return 1000 * time.Millisecond } return time.Duration(c.ElectionTimeoutMs) * time.Millisecond } func (c *ClusterConfig) GetCommitTimeout() time.Duration { if c.CommitTimeoutMs <= 0 { return 500 * time.Millisecond } return time.Duration(c.CommitTimeoutMs) * time.Millisecond } func (c *ClusterConfig) GetSnapshotInterval() time.Duration { if c.SnapshotIntervalMin <= 0 { return 30 * time.Minute } return time.Duration(c.SnapshotIntervalMin) * time.Minute } func (c *ClusterConfig) GetSnapshotThreshold() uint64 { if c.SnapshotThreshold <= 0 { return 1000 } return uint64(c.SnapshotThreshold) } func (c *ClusterConfig) IsSplitBrainPreventionEnabled() bool { return c.SplitBrainPrevention } func (c *ClusterConfig) GetRecoveryTimeout() time.Duration { if c.RecoveryTimeoutSec <= 0 { return 30 * time.Second } return time.Duration(c.RecoveryTimeoutSec) * time.Second } func (c *ClusterConfig) GetRegion() string { if c.Region == "" { return "default" } return c.Region } func (c *ClusterConfig) GetPriorityZone() int { if c.PriorityZone < 0 { return 0 } if c.PriorityZone > 9 { return 9 } return c.PriorityZone } // ========== Методы ReplicationConfig ========== func (r *ReplicationConfig) GetReplicationTimeout() time.Duration { if r.ReplicationTimeoutMs <= 0 { return 5 * time.Second } return time.Duration(r.ReplicationTimeoutMs) * time.Millisecond } func (r *ReplicationConfig) IsReplicationEnabled() bool { return r.Enabled } func (r *ReplicationConfig) IsMasterMasterEnabled() bool { return r.MasterMaster } func (r *ReplicationConfig) IsSyncReplicationEnabled() bool { return r.SyncReplication } // ========== Методы RecoveryConfig ========== func (r *RecoveryConfig) GetMaxRetryDuration() time.Duration { if r.MaxRetrySec <= 0 { return 300 * time.Second } return time.Duration(r.MaxRetrySec) * time.Second } func (r *RecoveryConfig) GetDataReplicationTimeout() time.Duration { if r.DataReplicationTimeoutSec <= 0 { return 60 * time.Second } return time.Duration(r.DataReplicationTimeoutSec) * time.Second } func (r *RecoveryConfig) GetStaleReadTimeout() time.Duration { if r.StaleReadTimeoutSec <= 0 { return 30 * time.Second } return time.Duration(r.StaleReadTimeoutSec) * time.Second } func (r *RecoveryConfig) IsAutoRejoinEnabled() bool { return r.AutoRejoin } // ========== Методы PerformanceConfig ========== func (p *PerformanceConfig) GetBatchSize() int { if p.BatchSize <= 0 { return 100 } return p.BatchSize } func (p *PerformanceConfig) GetMaxConnections() int { if p.MaxConnections <= 0 { return 1000 } return p.MaxConnections } func (p *PerformanceConfig) IsReadFromFollowerEnabled() bool { return p.ReadFromFollower } func (p *PerformanceConfig) IsPipelineEnabled() bool { return p.EnablePipeline } // ========== Методы MonitoringConfig ========== func (m *MonitoringConfig) GetMetricsPort() int { if m.MetricsPort <= 0 { return 9090 } return m.MetricsPort } func (m *MonitoringConfig) GetTraceSampleRate() float64 { if m.TraceSampleRate <= 0 || m.TraceSampleRate > 1 { return 0.01 } return m.TraceSampleRate } func (m *MonitoringConfig) IsMetricsEnabled() bool { return m.EnableMetrics } func (m *MonitoringConfig) IsTracingEnabled() bool { return m.EnableTracing } // ========== Методы SecurityConfig ========== func (s *SecurityConfig) GetTLSMinVersion() uint16 { switch s.MinVersion { case "1.0": return 0x0301 case "1.1": return 0x0302 case "1.2": return 0x0303 case "1.3": return 0x0304 default: return 0x0303 } } func (s *SecurityConfig) IsTLSEnabled() bool { return s.EnableTLS && s.CertFile != "" && s.KeyFile != "" } func (s *SecurityConfig) GetCertFile() string { return s.CertFile } func (s *SecurityConfig) GetKeyFile() string { return s.KeyFile } func (s *SecurityConfig) GetCAFile() string { return s.CAFile } // ========== Методы CompressionConfig ========== func (c *CompressionConfig) IsCompressionEnabled() bool { return c.Enabled } func (c *CompressionConfig) GetAlgorithm() string { if c.Algorithm == "" { return "snappy" } return c.Algorithm } func (c *CompressionConfig) GetLevel() int { if c.Level < 1 { return 3 } if c.Level > 9 { return 9 } return c.Level } func (c *CompressionConfig) GetMinSize() int { if c.MinSize <= 0 { return 1024 } return c.MinSize } // ========== Методы WebUIConfig ========== func (w *WebUIConfig) IsWebUIEnabled() bool { return w.Enabled } func (w *WebUIConfig) GetWebUIPort() int { if w.Port <= 0 { return 8080 } return w.Port } func (w *WebUIConfig) GetTheme() string { if w.Theme == "" { return "dark" } return w.Theme } // ========== Валидация конфигурации ========== // ValidateConfig выполняет полную валидацию конфигурации func ValidateConfig(cfg *Config) *ValidationResult { result := &ValidationResult{ Valid: true, Errors: make([]error, 0), Warnings: make([]error, 0), } // Валидация кластерной конфигурации if cfg.Cluster.NodePort <= 0 || cfg.Cluster.NodePort > 65535 { result.Errors = append(result.Errors, fmt.Errorf("invalid node_port: %d", cfg.Cluster.NodePort)) } if cfg.Cluster.RaftPort <= 0 || cfg.Cluster.RaftPort > 65535 { result.Errors = append(result.Errors, fmt.Errorf("invalid raft_port: %d", cfg.Cluster.RaftPort)) } if cfg.Cluster.PriorityZone < 0 || cfg.Cluster.PriorityZone > 9 { result.Errors = append(result.Errors, fmt.Errorf("priority_zone must be between 0 and 9, got %d", cfg.Cluster.PriorityZone)) } // Валидация производительности if cfg.Performance.BatchSize < 1 { result.Errors = append(result.Errors, fmt.Errorf("batch_size must be at least 1, got %d", cfg.Performance.BatchSize)) } if cfg.Performance.MaxConnections < 1 { result.Errors = append(result.Errors, fmt.Errorf("max_connections must be at least 1, got %d", cfg.Performance.MaxConnections)) } // Валидация мониторинга if cfg.Monitoring.TraceSampleRate < 0 || cfg.Monitoring.TraceSampleRate > 1 { result.Errors = append(result.Errors, fmt.Errorf("trace_sample_rate must be between 0 and 1, got %f", cfg.Monitoring.TraceSampleRate)) } // Проверка конфликтов портов if cfg.API.Port == cfg.Cluster.NodePort { result.Errors = append(result.Errors, fmt.Errorf("API port %d conflicts with cluster node port", cfg.API.Port)) } if cfg.WebUI.Port == cfg.Cluster.NodePort { result.Errors = append(result.Errors, fmt.Errorf("WebUI port %d conflicts with cluster node port", cfg.WebUI.Port)) } if cfg.Monitoring.MetricsPort == cfg.Cluster.NodePort { result.Errors = append(result.Errors, fmt.Errorf("metrics port %d conflicts with cluster node port", cfg.Monitoring.MetricsPort)) } // Валидация TLS if cfg.Security.IsTLSEnabled() { if cfg.Security.CertFile == "" { result.Errors = append(result.Errors, fmt.Errorf("cert_file is required when TLS is enabled")) } if cfg.Security.KeyFile == "" { result.Errors = append(result.Errors, fmt.Errorf("key_file is required when TLS is enabled")) } } // Валидация сжатия if cfg.Compression.Enabled { switch cfg.Compression.Algorithm { case "snappy", "lz4", "zstd": default: result.Errors = append(result.Errors, fmt.Errorf("unsupported compression algorithm: %s, supported: snappy, lz4, zstd", cfg.Compression.Algorithm)) } } // Валидация WAL if cfg.WAL.RecoveryWorkers < 1 { result.Errors = append(result.Errors, fmt.Errorf("wal.recovery_workers must be at least 1, got %d", cfg.WAL.RecoveryWorkers)) } if cfg.WAL.AsyncRecoveryWorkers < 1 && cfg.WAL.AsyncRecovery { result.Warnings = append(result.Warnings, fmt.Errorf("wal.async_recovery_workers is less than 1, will use default 4")) } if cfg.WAL.AsyncRecoveryBuffer < 0 { result.Errors = append(result.Errors, fmt.Errorf("wal.async_recovery_buffer cannot be negative, got %d", cfg.WAL.AsyncRecoveryBuffer)) } // Валидация MVCC if cfg.MVCC.MaxVersionsPerDoc < 0 { result.Errors = append(result.Errors, fmt.Errorf("mvcc.max_versions_per_doc cannot be negative, got %d", cfg.MVCC.MaxVersionsPerDoc)) } // Валидация плагинов if cfg.Plugins.MaxCPUTimeMs < 0 { result.Errors = append(result.Errors, fmt.Errorf("plugins.max_cpu_time_ms cannot be negative, got %d", cfg.Plugins.MaxCPUTimeMs)) } if cfg.Plugins.MaxMemoryMB < 0 { result.Errors = append(result.Errors, fmt.Errorf("plugins.max_memory_mb cannot be negative, got %d", cfg.Plugins.MaxMemoryMB)) } if cfg.Plugins.MaxLuaStates < 1 { result.Warnings = append(result.Warnings, fmt.Errorf("plugins.max_lua_states is less than 1, will use default 100")) } // Валидация backpressure if cfg.Backpressure.Enabled { if cfg.Backpressure.CPUThreshold < 0 || cfg.Backpressure.CPUThreshold > 1 { result.Errors = append(result.Errors, fmt.Errorf("backpressure.cpu_threshold must be between 0 and 1, got %f", cfg.Backpressure.CPUThreshold)) } if cfg.Backpressure.MemoryThreshold < 0 || cfg.Backpressure.MemoryThreshold > 1 { result.Errors = append(result.Errors, fmt.Errorf("backpressure.memory_threshold must be between 0 and 1, got %f", cfg.Backpressure.MemoryThreshold)) } if cfg.Backpressure.MediumRejectProb > 100 { result.Warnings = append(result.Warnings, fmt.Errorf("backpressure.medium_reject_prob is > 100, will be capped to 100")) } if cfg.Backpressure.HighRejectProb > 100 { result.Warnings = append(result.Warnings, fmt.Errorf("backpressure.high_reject_prob is > 100, will be capped to 100")) } } // Валидация runtime limits if cfg.RuntimeLimits.Enabled { if cfg.RuntimeLimits.GlobalMaxDocSizeMB < 0 { result.Errors = append(result.Errors, fmt.Errorf("runtime_limits.global_max_doc_size_mb cannot be negative, got %d", cfg.RuntimeLimits.GlobalMaxDocSizeMB)) } if cfg.RuntimeLimits.GlobalMaxCollSizeMB < 0 { result.Errors = append(result.Errors, fmt.Errorf("runtime_limits.global_max_coll_size_mb cannot be negative, got %d", cfg.RuntimeLimits.GlobalMaxCollSizeMB)) } if cfg.RuntimeLimits.GlobalMaxDocsPerColl < 0 { result.Errors = append(result.Errors, fmt.Errorf("runtime_limits.global_max_docs_per_coll cannot be negative, got %d", cfg.RuntimeLimits.GlobalMaxDocsPerColl)) } } // Валидация автомасштабирования if cfg.Autoscaling.Enabled { if cfg.Autoscaling.MinNodes < 1 { result.Errors = append(result.Errors, fmt.Errorf("autoscaling.min_nodes must be at least 1, got %d", cfg.Autoscaling.MinNodes)) } if cfg.Autoscaling.MaxNodes < cfg.Autoscaling.MinNodes { result.Errors = append(result.Errors, fmt.Errorf("autoscaling.max_nodes (%d) must be >= min_nodes (%d)", cfg.Autoscaling.MaxNodes, cfg.Autoscaling.MinNodes)) } if cfg.Autoscaling.ScaleUpThreshold <= 0 || cfg.Autoscaling.ScaleUpThreshold > 1 { result.Warnings = append(result.Warnings, fmt.Errorf("autoscaling.scale_up_threshold is invalid, will use default 0.75")) } if cfg.Autoscaling.ScaleDownThreshold <= 0 || cfg.Autoscaling.ScaleDownThreshold >= cfg.Autoscaling.ScaleUpThreshold { result.Warnings = append(result.Warnings, fmt.Errorf("autoscaling.scale_down_threshold should be less than scale_up_threshold")) } } // Валидация движков if cfg.Storage.EnableCustomEngines { // Проверяем, что движок по умолчанию существует defaultEngine := cfg.Storage.GetDefaultEngine() switch defaultEngine { case "row", "columnar", "document", "kv", "ts", "graph": // Встроенные движки всегда доступны default: // Кастомный движок может быть загружен через плагин result.Warnings = append(result.Warnings, fmt.Errorf("default_engine '%s' is not a built-in engine, ensure plugin is loaded", defaultEngine)) } } result.Valid = len(result.Errors) == 0 return result } // LoadConfig загружает и валидирует конфигурацию из TOML файла func LoadConfig(path string) (*Config, error) { var cfg Config if _, err := toml.DecodeFile(path, &cfg); err != nil { return nil, fmt.Errorf("failed to decode config file: %v", err) } // Значения по умолчанию для существующих настроек if cfg.Cluster.RaftPort == 0 { cfg.Cluster.RaftPort = 9878 } if cfg.Cluster.RaftDataDir == "" { cfg.Cluster.RaftDataDir = "raft_data" } if cfg.Replication.ReplicationTimeoutMs == 0 { cfg.Replication.ReplicationTimeoutMs = 5000 } if cfg.Plugins.ScriptDir == "" { cfg.Plugins.ScriptDir = "plugins" } if cfg.Plugins.EnginePluginDir == "" { cfg.Plugins.EnginePluginDir = "engines" } if cfg.API.Port == 0 { cfg.API.Port = 8080 } if cfg.Compression.Algorithm == "" { cfg.Compression.Algorithm = "snappy" } if cfg.Compression.MinSize == 0 { cfg.Compression.MinSize = 1024 } if cfg.Compression.Level == 0 { cfg.Compression.Level = 3 } if cfg.WebUI.Port == 0 { cfg.WebUI.Port = 9080 } if cfg.WebUI.Theme == "" { cfg.WebUI.Theme = "dark" } if cfg.Cluster.HeartbeatTimeoutMs == 0 { cfg.Cluster.HeartbeatTimeoutMs = 1000 } if cfg.Cluster.ElectionTimeoutMs == 0 { cfg.Cluster.ElectionTimeoutMs = 1000 } if cfg.Cluster.CommitTimeoutMs == 0 { cfg.Cluster.CommitTimeoutMs = 500 } if cfg.Cluster.SnapshotIntervalMin == 0 { cfg.Cluster.SnapshotIntervalMin = 30 } if cfg.Cluster.SnapshotThreshold == 0 { cfg.Cluster.SnapshotThreshold = 1000 } if cfg.Cluster.RecoveryTimeoutSec == 0 { cfg.Cluster.RecoveryTimeoutSec = 30 } if cfg.Cluster.Region == "" { cfg.Cluster.Region = "default" } if cfg.Performance.BatchSize == 0 { cfg.Performance.BatchSize = 100 } if cfg.Performance.MaxConnections == 0 { cfg.Performance.MaxConnections = 1000 } if cfg.Monitoring.MetricsPort == 0 { cfg.Monitoring.MetricsPort = 9090 } if cfg.Monitoring.TraceSampleRate == 0 { cfg.Monitoring.TraceSampleRate = 0.01 } if cfg.Recovery.MaxRetrySec == 0 { cfg.Recovery.MaxRetrySec = 300 } if cfg.Recovery.DataReplicationTimeoutSec == 0 { cfg.Recovery.DataReplicationTimeoutSec = 60 } if cfg.Recovery.StaleReadTimeoutSec == 0 { cfg.Recovery.StaleReadTimeoutSec = 30 } if cfg.Security.MinVersion == "" { cfg.Security.MinVersion = "1.2" } if cfg.Storage.DefaultEngine == "" { cfg.Storage.DefaultEngine = "row" } // Значения по умолчанию для WAL if cfg.WAL.SegmentSizeMB == 0 { cfg.WAL.SegmentSizeMB = 64 } if cfg.WAL.SyncIntervalSec == 0 { cfg.WAL.SyncIntervalSec = 5 } if cfg.WAL.BatchSize == 0 { cfg.WAL.BatchSize = 100 } if cfg.WAL.RecoveryWorkers == 0 { cfg.WAL.RecoveryWorkers = 4 } if cfg.WAL.AsyncRecoveryWorkers == 0 { cfg.WAL.AsyncRecoveryWorkers = 4 } if cfg.WAL.AsyncRecoveryBuffer == 0 { cfg.WAL.AsyncRecoveryBuffer = 10000 } // Значения по умолчанию для MVCC if cfg.MVCC.MaxVersionsPerDoc == 0 { cfg.MVCC.MaxVersionsPerDoc = 10 } if cfg.MVCC.VisibilityMapSize == 0 { cfg.MVCC.VisibilityMapSize = 1024 * 1024 } if cfg.MVCC.PruneIntervalMin == 0 { cfg.MVCC.PruneIntervalMin = 5 } if cfg.MVCC.RetentionDays == 0 { cfg.MVCC.RetentionDays = 7 } if cfg.MVCC.ReadCacheSize == 0 { cfg.MVCC.ReadCacheSize = 10000 } if cfg.MVCC.ReadCacheTTLSec == 0 { cfg.MVCC.ReadCacheTTLSec = 300 } // Значения по умолчанию для транзакций if cfg.Transactions.DefaultTimeoutSec == 0 { cfg.Transactions.DefaultTimeoutSec = 30 } if cfg.Transactions.DeadlockCheckIntervalSec == 0 { cfg.Transactions.DeadlockCheckIntervalSec = 1 } if cfg.Transactions.MaxSavepointsPerTx == 0 { cfg.Transactions.MaxSavepointsPerTx = 100 } if cfg.Transactions.TwoPhaseCommitTimeoutSec == 0 { cfg.Transactions.TwoPhaseCommitTimeoutSec = 10 } if cfg.Transactions.CheckpointIntervalSec == 0 { cfg.Transactions.CheckpointIntervalSec = 300 } // Значения по умолчанию для ACL if cfg.ACL.MaxDeniedLogSize == 0 { cfg.ACL.MaxDeniedLogSize = 10000 } if cfg.ACL.TemporaryGrantTTLHours == 0 { cfg.ACL.TemporaryGrantTTLHours = 24 } if cfg.ACL.CacheTTLSec == 0 { cfg.ACL.CacheTTLSec = 60 } // Значения по умолчанию для расширенных настроек плагинов if cfg.Plugins.MaxCPUTimeMs == 0 { cfg.Plugins.MaxCPUTimeMs = 100 } if cfg.Plugins.MaxMemoryMB == 0 { cfg.Plugins.MaxMemoryMB = 50 } if cfg.Plugins.MaxExecutionTimeSec == 0 { cfg.Plugins.MaxExecutionTimeSec = 5 } if cfg.Plugins.MaxInstructions == 0 { cfg.Plugins.MaxInstructions = 1000000 } if cfg.Plugins.HotReloadIntervalSec == 0 { cfg.Plugins.HotReloadIntervalSec = 30 } if cfg.Plugins.MaxEventLogSize == 0 { cfg.Plugins.MaxEventLogSize = 1000 } if cfg.Plugins.LoadTimeoutSec == 0 { cfg.Plugins.LoadTimeoutSec = 10 } if cfg.Plugins.MaxLuaStates == 0 { cfg.Plugins.MaxLuaStates = 100 } if cfg.Plugins.LuaStateTTLSec == 0 { cfg.Plugins.LuaStateTTLSec = 600 } // Значения по умолчанию для новых конфигураций if cfg.ClusterTLS.MinVersion == "" { cfg.ClusterTLS.MinVersion = "1.2" } if cfg.ClusterTLS.KeyRotationDays == 0 { cfg.ClusterTLS.KeyRotationDays = 30 } if cfg.Backpressure.CheckIntervalMs == 0 { cfg.Backpressure.CheckIntervalMs = 1000 } if cfg.Backpressure.LowDelayMs == 0 { cfg.Backpressure.LowDelayMs = 100 } if cfg.RuntimeLimits.GlobalMaxDocSizeMB == 0 { cfg.RuntimeLimits.GlobalMaxDocSizeMB = 16 } if cfg.RuntimeLimits.GlobalMaxCollSizeMB == 0 { cfg.RuntimeLimits.GlobalMaxCollSizeMB = 10240 } if cfg.RuntimeLimits.GlobalMaxDocsPerColl == 0 { cfg.RuntimeLimits.GlobalMaxDocsPerColl = 10000000 } if cfg.Autoscaling.MinNodes == 0 { cfg.Autoscaling.MinNodes = 1 } if cfg.Autoscaling.MaxNodes == 0 { cfg.Autoscaling.MaxNodes = 10 } if cfg.Autoscaling.ScaleUpCooldownSec == 0 { cfg.Autoscaling.ScaleUpCooldownSec = 300 } if cfg.Autoscaling.ScaleDownCooldownSec == 0 { cfg.Autoscaling.ScaleDownCooldownSec = 600 } if cfg.Autoscaling.EvaluationIntervalSec == 0 { cfg.Autoscaling.EvaluationIntervalSec = 30 } if cfg.SchemaMigration.MigrationDir == "" { cfg.SchemaMigration.MigrationDir = "migrations" } if cfg.Backup.BackupDir == "" { cfg.Backup.BackupDir = "backups" } if cfg.Backup.RetentionDays == 0 { cfg.Backup.RetentionDays = 7 } // Значения по умолчанию для движков if !cfg.Engines.Row.Enabled { cfg.Engines.Row.Enabled = true cfg.Engines.Row.Description = "Row-based storage engine (default)" } if cfg.Engines.Row.Config == nil { cfg.Engines.Row.Config = make(map[string]interface{}) } if cfg.Engines.Columnar.Config == nil { cfg.Engines.Columnar.Config = make(map[string]interface{}) } if cfg.Engines.Document.Config == nil { cfg.Engines.Document.Config = make(map[string]interface{}) } if cfg.Engines.KV.Config == nil { cfg.Engines.KV.Config = make(map[string]interface{}) } if cfg.Engines.TS.Config == nil { cfg.Engines.TS.Config = make(map[string]interface{}) } if cfg.Engines.Graph.Config == nil { cfg.Engines.Graph.Config = make(map[string]interface{}) } // Полная валидация конфигурации validationResult := ValidateConfigFull(&cfg) if !validationResult.Valid { var errMsg strings.Builder errMsg.WriteString("config validation failed:\n") for _, err := range validationResult.Errors { errMsg.WriteString(fmt.Sprintf(" - %s\n", err.Error())) } if len(validationResult.Warnings) > 0 { errMsg.WriteString("Warnings:\n") for _, warn := range validationResult.Warnings { errMsg.WriteString(fmt.Sprintf(" - %s\n", warn.Error())) } } return nil, fmt.Errorf("%s", errMsg.String()) } // Выводим предупреждения, если есть (логгер ещё не инициализирован, используем fmt) if len(validationResult.Warnings) > 0 { fmt.Println("Configuration warnings:") for _, warn := range validationResult.Warnings { fmt.Printf(" - %s\n", warn.Error()) } } return &cfg, nil } // GetConfigSummary возвращает сводку по конфигурации func (c *Config) GetConfigSummary() map[string]interface{} { return map[string]interface{}{ "cluster": map[string]interface{}{ "name": c.Cluster.Name, "node_ip": c.Cluster.NodeIP, "node_port": c.Cluster.NodePort, "raft_port": c.Cluster.RaftPort, "bootstrap": c.Cluster.Bootstrap, "nodes_count": len(c.Cluster.Nodes), "region": c.Cluster.GetRegion(), "priority_zone": c.Cluster.GetPriorityZone(), "split_brain_prevention": c.Cluster.IsSplitBrainPreventionEnabled(), }, "replication": map[string]interface{}{ "enabled": c.Replication.IsReplicationEnabled(), "master_master": c.Replication.IsMasterMasterEnabled(), "sync": c.Replication.IsSyncReplicationEnabled(), "timeout_ms": c.Replication.ReplicationTimeoutMs, }, "performance": map[string]interface{}{ "pipeline": c.Performance.IsPipelineEnabled(), "batch_size": c.Performance.GetBatchSize(), "read_from_follower": c.Performance.IsReadFromFollowerEnabled(), "max_connections": c.Performance.GetMaxConnections(), }, "security": map[string]interface{}{ "tls_enabled": c.Security.IsTLSEnabled(), "tls_version": c.Security.MinVersion, }, "monitoring": map[string]interface{}{ "metrics_enabled": c.Monitoring.IsMetricsEnabled(), "metrics_port": c.Monitoring.GetMetricsPort(), "tracing_enabled": c.Monitoring.IsTracingEnabled(), "trace_sample_rate": c.Monitoring.GetTraceSampleRate(), }, "compression": map[string]interface{}{ "enabled": c.Compression.IsCompressionEnabled(), "algorithm": c.Compression.GetAlgorithm(), "level": c.Compression.GetLevel(), "min_size": c.Compression.GetMinSize(), }, "wal": map[string]interface{}{ "segment_size_mb": c.WAL.SegmentSizeMB, "sync_interval_sec": c.WAL.SyncIntervalSec, "batch_size": c.WAL.BatchSize, "recovery_workers": c.WAL.RecoveryWorkers, "enabled": c.WAL.Enabled, "async_recovery": c.WAL.AsyncRecovery, "async_recovery_workers": c.WAL.AsyncRecoveryWorkers, }, "mvcc": map[string]interface{}{ "max_versions_per_doc": c.MVCC.MaxVersionsPerDoc, "prune_interval_min": c.MVCC.PruneIntervalMin, "retention_days": c.MVCC.RetentionDays, }, "transactions": map[string]interface{}{ "default_timeout_sec": c.Transactions.DefaultTimeoutSec, "enabled": c.Transactions.Enabled, }, "acl": map[string]interface{}{ "enable_role_hierarchy": c.ACL.EnableRoleHierarchy, }, "plugins": map[string]interface{}{ "enabled": c.Plugins.Enabled, "script_dir": c.Plugins.ScriptDir, "max_lua_states": c.Plugins.MaxLuaStates, "hot_reload_interval_sec": c.Plugins.HotReloadIntervalSec, }, "cluster_tls": map[string]interface{}{ "enabled": c.ClusterTLS.Enabled, "mutual_auth": c.ClusterTLS.MutualAuth, "key_rotation_days": c.ClusterTLS.KeyRotationDays, }, "backpressure": map[string]interface{}{ "enabled": c.Backpressure.Enabled, "cpu_threshold": c.Backpressure.CPUThreshold, "memory_threshold": c.Backpressure.MemoryThreshold, }, "runtime_limits": map[string]interface{}{ "enabled": c.RuntimeLimits.Enabled, "global_max_doc_size_mb": c.RuntimeLimits.GlobalMaxDocSizeMB, "global_max_coll_size_mb": c.RuntimeLimits.GlobalMaxCollSizeMB, "global_max_docs_per_coll": c.RuntimeLimits.GlobalMaxDocsPerColl, }, "autoscaling": map[string]interface{}{ "enabled": c.Autoscaling.Enabled, "min_nodes": c.Autoscaling.MinNodes, "max_nodes": c.Autoscaling.MaxNodes, "predictive": c.Autoscaling.PredictiveEnabled, }, "schema_migration": map[string]interface{}{ "enabled": c.SchemaMigration.Enabled, "auto_migrate": c.SchemaMigration.AutoMigrate, }, "backup": map[string]interface{}{ "enabled": c.Backup.Enabled, "retention_days": c.Backup.RetentionDays, "compress_enabled": c.Backup.CompressEnabled, }, "storage": map[string]interface{}{ "page_size_mb": c.Storage.PageSizeMB, "max_collections": c.Storage.MaxCollections, "max_documents_per_collection": c.Storage.MaxDocumentsPerCollection, "default_engine": c.Storage.GetDefaultEngine(), "enable_custom_engines": c.Storage.EnableCustomEngines, }, "engines": map[string]interface{}{ "row": map[string]interface{}{ "enabled": c.Engines.Row.Enabled, "description": c.Engines.Row.Description, }, "columnar": map[string]interface{}{ "enabled": c.Engines.Columnar.Enabled, "description": c.Engines.Columnar.Description, }, "document": map[string]interface{}{ "enabled": c.Engines.Document.Enabled, "description": c.Engines.Document.Description, }, "kv": map[string]interface{}{ "enabled": c.Engines.KV.Enabled, "description": c.Engines.KV.Description, }, "ts": map[string]interface{}{ "enabled": c.Engines.TS.Enabled, "description": c.Engines.TS.Description, }, "graph": map[string]interface{}{ "enabled": c.Engines.Graph.Enabled, "description": c.Engines.Graph.Description, }, }, } }