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  }