diff --git a/internal/config/config.go b/internal/config/config.go deleted file mode 100644 index 64ce127..0000000 --- a/internal/config/config.go +++ /dev/null @@ -1,934 +0,0 @@ -/* - * 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" - "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"` -} - -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"` -} - -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"` -} - -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"` -} - -// 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"` -} - -// ========== Методы для новых конфигураций ========== - -// 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 -} - -// 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 -} - -// ========== Остальные методы без изменений ========== - -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 -} - -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 -} - -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 -} - -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 -} - -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 -} - -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 -} - -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 -} - -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 -} - -func (c *Config) Validate() error { - if c.Cluster.NodePort <= 0 || c.Cluster.NodePort > 65535 { - return fmt.Errorf("invalid node_port: %d", c.Cluster.NodePort) - } - if c.Cluster.RaftPort <= 0 || c.Cluster.RaftPort > 65535 { - return fmt.Errorf("invalid raft_port: %d", c.Cluster.RaftPort) - } - if c.Cluster.PriorityZone < 0 || c.Cluster.PriorityZone > 9 { - return fmt.Errorf("priority_zone must be between 0 and 9, got %d", c.Cluster.PriorityZone) - } - if c.Performance.BatchSize < 1 { - return fmt.Errorf("batch_size must be at least 1, got %d", c.Performance.BatchSize) - } - if c.Performance.MaxConnections < 1 { - return fmt.Errorf("max_connections must be at least 1, got %d", c.Performance.MaxConnections) - } - if c.Monitoring.TraceSampleRate < 0 || c.Monitoring.TraceSampleRate > 1 { - return fmt.Errorf("trace_sample_rate must be between 0 and 1, got %f", c.Monitoring.TraceSampleRate) - } - if c.API.Port == c.Cluster.NodePort { - return fmt.Errorf("API port %d conflicts with cluster node port", c.API.Port) - } - if c.WebUI.Port == c.Cluster.NodePort { - return fmt.Errorf("WebUI port %d conflicts with cluster node port", c.WebUI.Port) - } - if c.Monitoring.MetricsPort == c.Cluster.NodePort { - return fmt.Errorf("metrics port %d conflicts with cluster node port", c.Monitoring.MetricsPort) - } - if c.Security.IsTLSEnabled() { - if c.Security.CertFile == "" { - return fmt.Errorf("cert_file is required when TLS is enabled") - } - if c.Security.KeyFile == "" { - return fmt.Errorf("key_file is required when TLS is enabled") - } - } - if c.Compression.Enabled { - switch c.Compression.Algorithm { - case "snappy", "lz4", "zstd": - default: - return fmt.Errorf("unsupported compression algorithm: %s, supported: snappy, lz4, zstd", c.Compression.Algorithm) - } - } - - // Валидация новых настроек - if c.WAL.RecoveryWorkers < 1 { - return fmt.Errorf("wal.recovery_workers must be at least 1, got %d", c.WAL.RecoveryWorkers) - } - if c.MVCC.MaxVersionsPerDoc < 0 { - return fmt.Errorf("mvcc.max_versions_per_doc cannot be negative, got %d", c.MVCC.MaxVersionsPerDoc) - } - if c.Plugins.MaxCPUTimeMs < 0 { - return fmt.Errorf("plugins.max_cpu_time_ms cannot be negative, got %d", c.Plugins.MaxCPUTimeMs) - } - if c.Plugins.MaxMemoryMB < 0 { - return fmt.Errorf("plugins.max_memory_mb cannot be negative, got %d", c.Plugins.MaxMemoryMB) - } - - return nil -} - -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.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" - } - - // Значения по умолчанию для 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 - } - - // Значения по умолчанию для 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 err := cfg.Validate(); err != nil { - return nil, fmt.Errorf("config validation failed: %v", err) - } - - return &cfg, nil -} - -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, - }, - "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, - }, - } -}