Files
futriix/internal/config/config.go

1734 lines
54 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/*
* 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,
},
},
}
}