Add internal/config package with Config struct (Server, Navidrome, MusicBrainz, Telegram, Scanner sections), LoadConfig function for YAML parsing, config validation (required fields, port range, threshold range), and defaults. Include config.yaml.example matching spec. Update main.go to use real config package instead of placeholders. Add comprehensive tests covering valid configs, defaults, missing files, malformed YAML, and validation boundaries. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
58 lines
1.2 KiB
Go
58 lines
1.2 KiB
Go
package main
|
|
|
|
import (
|
|
"context"
|
|
"flag"
|
|
"log"
|
|
"os"
|
|
"os/signal"
|
|
"syscall"
|
|
"time"
|
|
|
|
"naviwatcher/internal/config"
|
|
)
|
|
|
|
const defaultConfigPath = "config.yaml"
|
|
|
|
func main() {
|
|
configPath := flag.String("config", defaultConfigPath, "Path to config file")
|
|
flag.Parse()
|
|
|
|
log.Println("NaviWatcher starting...")
|
|
|
|
cfg, err := config.LoadConfig(*configPath)
|
|
if err != nil {
|
|
log.Fatalf("Failed to load config: %v", err)
|
|
}
|
|
|
|
log.Printf("Config loaded from %s (server: %s:%d)", *configPath, cfg.Server.Host, cfg.Server.Port)
|
|
|
|
ctx, cancel := context.WithCancel(context.Background())
|
|
defer cancel()
|
|
|
|
sigCh := make(chan os.Signal, 1)
|
|
signal.Notify(sigCh, syscall.SIGINT, syscall.SIGTERM)
|
|
|
|
go func() {
|
|
sig := <-sigCh
|
|
log.Printf("Received signal %v, shutting down...", sig)
|
|
cancel()
|
|
}()
|
|
|
|
if err := run(ctx, cfg); err != nil {
|
|
log.Fatalf("Application error: %v", err)
|
|
}
|
|
|
|
log.Println("NaviWatcher stopped.")
|
|
}
|
|
|
|
func run(ctx context.Context, cfg *config.Config) error {
|
|
// Main application loop — blocks until context is cancelled.
|
|
// Business logic will be added in future tasks.
|
|
<-ctx.Done()
|
|
|
|
// Graceful shutdown delay to let goroutines finish.
|
|
time.Sleep(100 * time.Millisecond)
|
|
return nil
|
|
}
|