package main import ( "fmt" "log" "os" "github.com/goccy/go-yaml" ) // Estructuras para mapear el YAML type RetryConfig struct { Attempts int `yaml:"attempts"` } type DBInfo struct { Schema string `yaml:"schema"` Table string `yaml:"table"` PrimaryKey string `yaml:"primary_key,omitempty"` // omitempty si no siempre existe } // JobSettings contiene los campos que se comparten entre 'defaults' y cada 'job' type JobSettings struct { MaxExtractors *int `yaml:"max_extractors"` MaxLoaders *int `yaml:"max_loaders"` QueueSize *int `yaml:"queue_size"` ChunkSize *int `yaml:"chunk_size"` ChunksPerBatch *int `yaml:"chunks_per_batch"` TruncateTarget *bool `yaml:"truncate_target"` TruncateMethod *string `yaml:"truncate_method"` Retry *RetryConfig `yaml:"retry"` } type Job struct { Name string `yaml:"name"` Enabled bool `yaml:"enabled"` Source DBInfo `yaml:"source"` Target DBInfo `yaml:"target"` PreSQL []string `yaml:"pre_sql"` PostSQL []string `yaml:"post_sql"` // Incrustamos los settings para permitir los overrides JobSettings `yaml:",inline"` } type Config struct { MaxParallelWorkers int `yaml:"max_parallel_workers"` Defaults JobSettings `yaml:"defaults"` Jobs []Job `yaml:"jobs"` } func main() { yamlFile, err := os.ReadFile("config.yaml") if err != nil { log.Fatalf("Error leyendo archivo: %v", err) } var config Config err = yaml.Unmarshal(yamlFile, &config) if err != nil { log.Fatalf("Error parseando YAML: %v", err) } fmt.Printf("Configuración cargada. Trabajos: %d\n", len(config.Jobs)) for i, job := range config.Jobs { jobPtr := &config.Jobs[i] if job.MaxExtractors == nil { jobPtr.MaxExtractors = config.Defaults.MaxExtractors } if job.MaxLoaders == nil { jobPtr.MaxLoaders = config.Defaults.MaxLoaders } if job.QueueSize == nil { jobPtr.QueueSize = config.Defaults.QueueSize } if job.ChunkSize == nil { jobPtr.ChunkSize = config.Defaults.ChunkSize } if job.ChunksPerBatch == nil { jobPtr.ChunksPerBatch = config.Defaults.ChunksPerBatch } if job.TruncateTarget == nil { jobPtr.TruncateTarget = config.Defaults.TruncateTarget } if job.TruncateMethod == nil { jobPtr.TruncateMethod = config.Defaults.TruncateMethod } if job.Retry == nil { jobPtr.Retry = config.Defaults.Retry } } printConfig(config) } func printConfig(config Config) { fmt.Println("Max parallel workers: ", config.MaxParallelWorkers) fmt.Println("Defaults:") fmt.Printf("\tMaxExtractors: %v\n", *config.Defaults.MaxExtractors) fmt.Printf("\tMaxLoaders: %v\n", *config.Defaults.MaxLoaders) fmt.Printf("\tQueueSize: %v\n", *config.Defaults.QueueSize) fmt.Printf("\tChunkSize: %v\n", *config.Defaults.ChunkSize) fmt.Printf("\tChunksPerBatch: %v\n", *config.Defaults.ChunksPerBatch) fmt.Printf("\tTruncateTarget: %v\n", *config.Defaults.TruncateTarget) fmt.Printf("\tTruncateMethod: %v\n", *config.Defaults.TruncateMethod) fmt.Printf("\tRetry: %v\n", *config.Defaults.Retry) fmt.Println("Jobs:") for i, job := range config.Jobs { fmt.Printf("Job Name: %v\n", job.Name) fmt.Printf("\tEnabled: %v\n", job.Enabled) fmt.Printf("\tSource: %v\n", job.Source) fmt.Printf("\tTarget: %v\n", job.Target) fmt.Printf("\tMaxExtractors: %v\n", *job.MaxExtractors) fmt.Printf("\tMaxLoaders: %v\n", *job.MaxLoaders) fmt.Printf("\tQueueSize: %v\n", *job.QueueSize) fmt.Printf("\tChunkSize: %v\n", *job.ChunkSize) fmt.Printf("\tChunksPerBatch: %v\n", *job.ChunksPerBatch) fmt.Printf("\tTruncateTarget: %v\n", *job.TruncateTarget) fmt.Printf("\tTruncateMethod: %v\n", *job.TruncateMethod) fmt.Printf("\tRetry: %v\n", *job.Retry) fmt.Printf("\tPreSQL: %v\n", job.PreSQL) fmt.Printf("\tPostSQL: %v\n", job.PostSQL) if i >= 2 { fmt.Println("Skipping remaining jobs...") } } }