main.go
1 package main 2 3 import ( 4 "context" 5 "fmt" 6 "os" 7 "os/signal" 8 "syscall" 9 "time" 10 11 "go.uber.org/zap" 12 ) 13 14 func main() { 15 // Initialize composition root with all dependencies 16 root, err := NewCompositionRoot() 17 if err != nil { 18 fmt.Printf("Failed to initialize application: %v\n", err) 19 os.Exit(1) 20 } 21 22 // Ensure cleanup on exit 23 defer func() { 24 if err := root.Cleanup(); err != nil { 25 root.Logger.Error("Failed to cleanup resources", zap.Error(err)) 26 } 27 }() 28 29 // Get socket path 30 socketPath := root.GetSocketPath() 31 32 // Start server on Unix socket 33 root.Logger.Info("Starting cache server on Unix socket", zap.String("socket_path", socketPath)) 34 go func() { 35 if err := root.HTTPServer.StartUnixSocket(socketPath); err != nil { 36 root.Logger.Error("Server failed to start on Unix socket", zap.Error(err)) 37 } 38 }() 39 40 // Start metrics server on HTTP port 41 metricsPort := root.GetMetricsPort() 42 root.Logger.Info("Starting metrics server", zap.String("port", metricsPort)) 43 go func() { 44 if err := root.MetricsServer.Start(metricsPort); err != nil { 45 root.Logger.Error("Metrics server failed to start", zap.Error(err)) 46 } 47 }() 48 49 // Wait for interrupt signal to gracefully shutdown 50 quit := make(chan os.Signal, 1) 51 signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM) 52 <-quit 53 54 root.Logger.Info("Shutting down server...") 55 56 // Create a deadline for shutdown 57 ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) 58 defer cancel() 59 60 // Shutdown servers 61 if err := root.HTTPServer.Stop(ctx); err != nil { 62 root.Logger.Error("HTTP server forced to shutdown", zap.Error(err)) 63 } 64 if err := root.MetricsServer.Stop(ctx); err != nil { 65 root.Logger.Error("Metrics server forced to shutdown", zap.Error(err)) 66 } 67 68 root.Logger.Info("Server exited") 69 }