|
1 | 1 | package main
|
2 | 2 |
|
3 | 3 | import (
|
4 |
| - "log" |
| 4 | + "context" |
| 5 | + "log/slog" |
| 6 | + "os" |
| 7 | + "os/signal" |
| 8 | + "sync" |
| 9 | + "syscall" |
5 | 10 | "time"
|
6 | 11 |
|
| 12 | + "ioaiaaii.net/config" |
7 | 13 | "ioaiaaii.net/internal/controller/httpcontroller"
|
8 | 14 | "ioaiaaii.net/internal/infrastructure/cache"
|
9 | 15 | "ioaiaaii.net/internal/infrastructure/persistence/storage"
|
| 16 | + "ioaiaaii.net/internal/infrastructure/telemetry" |
10 | 17 | "ioaiaaii.net/internal/infrastructure/transport/httpserver"
|
11 | 18 | "ioaiaaii.net/internal/usecase/content"
|
12 | 19 | "ioaiaaii.net/website/data"
|
13 | 20 | )
|
14 | 21 |
|
15 | 22 | func main() {
|
| 23 | + slog.Info("Application starting...") |
| 24 | + // Load configuration |
| 25 | + cfg := config.LoadConfig() |
16 | 26 |
|
17 |
| - var dataConf data.Config |
| 27 | + // Create a signal-aware context for graceful shutdown |
| 28 | + ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM) |
| 29 | + defer cancel() |
18 | 30 |
|
19 |
| - err := dataConf.LoadData() |
| 31 | + // Initialize OpenTelemetry SDK for metrics |
| 32 | + slog.Info("Initializing OpenTelemetry...") |
| 33 | + shutdownTelemetry, err := telemetry.SetupOTelSDK(ctx, cfg.OtelConfig) |
20 | 34 | if err != nil {
|
21 |
| - log.Fatalf("Error loading data: %v", err) |
| 35 | + slog.ErrorContext(ctx, "Failed to initialize OpenTelemetry", "error", err.Error()) |
| 36 | + os.Exit(1) // Exit immediately on critical error |
22 | 37 | }
|
| 38 | + defer func() { |
| 39 | + shutdownCtx, cancelShutdown := context.WithTimeout(context.Background(), 10*time.Second) |
| 40 | + defer cancelShutdown() |
23 | 41 |
|
24 |
| - // 2. Initialize the repository (file-based repository in this case) |
| 42 | + if err := shutdownTelemetry(shutdownCtx); err != nil { |
| 43 | + slog.ErrorContext(ctx, "Error during OpenTelemetry shutdown", "error", err.Error()) |
| 44 | + } else { |
| 45 | + slog.Info("OpenTelemetry shut down gracefully.") |
| 46 | + } |
| 47 | + }() |
| 48 | + |
| 49 | + // Step 5: Initialize data configuration |
| 50 | + slog.Info("Loading data configuration...") |
| 51 | + var dataConf data.Files |
| 52 | + if err := dataConf.LoadFiles(); err != nil { |
| 53 | + slog.ErrorContext(ctx, "Error loading data", "error", err.Error()) |
| 54 | + os.Exit(1) // Exit immediately on critical error |
| 55 | + } |
| 56 | + |
| 57 | + // Step 6: Initialize repository (file-based repository in this case) |
| 58 | + slog.Info("Initializing storage repository...") |
25 | 59 | fetchedData := storage.NewFileContent(dataConf)
|
26 | 60 |
|
27 |
| - // Add in-memory caching layer with a 10-minute TTL |
| 61 | + // Step 7: Add in-memory caching layer with a 30-minute TTL |
| 62 | + slog.Info("Initializing in-memory cache...") |
28 | 63 | cachedRepo := cache.NewInMemoryCacheRepository(fetchedData, 30*time.Minute)
|
29 | 64 |
|
30 |
| - // 3. Initialize the use case by injecting the repository |
| 65 | + // Step 8: Initialize use case by injecting repository |
| 66 | + slog.Info("Initializing content use case...") |
31 | 67 | contentUsecase := content.NewContentUsecase(cachedRepo)
|
32 | 68 |
|
33 |
| - // 4. Initialize the HTTP handler (controller) by injecting the use case |
| 69 | + // Step 9: Initialize HTTP handler (controller) by injecting use case |
| 70 | + slog.Info("Initializing HTTP handler...") |
34 | 71 | contentHandler := httpcontroller.NewContentHandler(contentUsecase)
|
35 | 72 |
|
36 |
| - // 5. Setup and start the HTTP server |
37 |
| - app := httpserver.SetupHTTPServer(contentHandler) |
38 |
| - // 6. Start the HTTP server |
39 |
| - log.Fatal(app.Listen(":8080")) |
| 73 | + // Step 10: Initialize WaitGroup for managing goroutines |
| 74 | + var wg sync.WaitGroup |
| 75 | + |
| 76 | + // Step 11: Start the HTTP server with the context |
| 77 | + slog.Info("Starting HTTP server...") |
| 78 | + httpserver.StartHTTPServer(ctx, contentHandler, &wg, cfg.APIConfig) |
| 79 | + |
| 80 | + // Step 12: Wait for all goroutines to finish |
| 81 | + slog.Info("Waiting for goroutines to finish...") |
| 82 | + wg.Wait() |
| 83 | + |
| 84 | + // Step 13: Log application shutdown |
| 85 | + slog.Info("Application shut down gracefully.") |
40 | 86 | }
|
0 commit comments