package main import ( "context" "flag" "fmt" "log" "os" "os/signal" "syscall" "time" ) const defaultConfigPath = "config.yaml" func main() { configPath := flag.String("config", defaultConfigPath, "Path to config file") flag.Parse() log.Println("NaviWatcher starting...") cfg, err := 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.") } // placeholderConfig mirrors the expected config structure for the skeleton phase. // Will be replaced by internal/config.Config in Task 2. type placeholderConfig struct { Server struct { Host string Port int } } func loadConfig(path string) (*placeholderConfig, error) { data, err := os.ReadFile(path) if err != nil { return nil, fmt.Errorf("read config file: %w", err) } var cfg placeholderConfig if err := parseYAML(data, &cfg); err != nil { return nil, fmt.Errorf("parse config: %w", err) } if cfg.Server.Host == "" { cfg.Server.Host = "0.0.0.0" } if cfg.Server.Port == 0 { cfg.Server.Port = 8080 } return &cfg, nil } // parseYAML is a temporary placeholder. Will be replaced by gopkg.in/yaml.v3 in Task 2. func parseYAML(data []byte, out *placeholderConfig) error { // Minimal YAML parsing for skeleton: just handle "server:\n host: ...\n port: ..." // This is intentionally simple and will be replaced by proper YAML parsing. return nil } func run(ctx context.Context, cfg *placeholderConfig) 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 }