11package main
22
33import (
4- // "evolve/config"
4+ "context"
5+ "errors"
56 "evolve/controller"
7+ "evolve/modules/sse"
8+ "evolve/modules/ws"
69 "evolve/routes"
710 "evolve/util"
811 "fmt"
9- "github.com/rs/cors "
12+ "net "
1013 "net/http"
1114 "os"
15+ "os/signal"
16+ "syscall"
17+ "time"
18+
19+ "github.com/rs/cors"
1220)
1321
1422var (
@@ -17,32 +25,91 @@ var (
1725)
1826
1927func main () {
20-
2128 PORT = fmt .Sprintf (":%s" , os .Getenv ("HTTP_PORT" ))
29+ if PORT == ":" {
30+ PORT = ":5002"
31+ }
2232 FRONTEND_URL = os .Getenv ("FRONTEND_URL" )
33+ if FRONTEND_URL == "" {
34+ FRONTEND_URL = "http://localhost:3000"
35+ }
2336
2437 var logger = util .NewLogger ()
2538
26- // Register routes.
27- http .HandleFunc (routes .TEST , controller .Test )
28- http .HandleFunc (routes .EA , controller .CreateEA )
29- http .HandleFunc (routes .GP , controller .CreateGP )
30- http .HandleFunc (routes .ML , controller .CreateML )
31- http .HandleFunc (routes .PSO , controller .CreatePSO )
32- http .HandleFunc (routes .RUNS , controller .UserRuns )
33- http .HandleFunc (routes .SHARE_RUN , controller .ShareRun )
34- http .HandleFunc (routes .RUN , controller .UserRun )
39+ // Context and Graceful Shutdown Setup.
40+ ctx , stop := signal .NotifyContext (context .Background (), syscall .SIGINT , syscall .SIGTERM )
41+ defer stop ()
42+
43+ // Start WebSocket Server.
44+ wsHub := ws .StartServer (ctx , * logger )
45+ logger .Info ("WebSocket Hub started." )
46+
47+ // Register HTTP Routes.
48+ mux := http .DefaultServeMux
49+
50+ mux .HandleFunc (routes .TEST , controller .Test )
51+ mux .HandleFunc (routes .EA , controller .CreateEA )
52+ mux .HandleFunc (routes .GP , controller .CreateGP )
53+ mux .HandleFunc (routes .ML , controller .CreateML )
54+ mux .HandleFunc (routes .PSO , controller .CreatePSO )
55+ mux .HandleFunc (routes .RUNS , controller .UserRuns )
56+ mux .HandleFunc (routes .SHARE_RUN , controller .ShareRun )
57+ mux .HandleFunc (routes .RUN , controller .UserRun )
58+
59+ // WebSocket Route.
60+ wsHandler := ws .GetHandler (ctx , wsHub , * logger )
61+ mux .HandleFunc (routes .LIVE , wsHandler )
62+ logger .Info ("WebSocket endpoint registered at /live/" )
3563
36- logger .Info (fmt .Sprintf ("Test http server on http://localhost%v/api/test" , PORT ))
64+ // SSE Route.
65+ sseHandler := sse .GetSSEHandler (* logger )
66+ mux .HandleFunc (routes .LOGS , sseHandler )
67+ logger .Info ("SSE endpoint registered at /runs/logs/" )
3768
69+ // Log the test endpoint URL.
70+ logger .Info (fmt .Sprintf ("Test http server on http://localhost%s/api/test" , PORT ))
71+
72+ // CORS Configuration.
3873 corsHandler := cors .New (cors.Options {
3974 AllowedOrigins : []string {FRONTEND_URL },
4075 AllowedMethods : []string {"GET" , "POST" , "PUT" , "DELETE" , "OPTIONS" },
4176 AllowedHeaders : []string {"*" },
4277 AllowCredentials : true ,
43- }).Handler (http .DefaultServeMux )
44- if err := http .ListenAndServe (PORT , corsHandler ); err != nil {
45- logger .Error (fmt .Sprintf ("Failed to start server: %v" , err ))
46- return
78+ }).Handler (mux )
79+
80+ // HTTP Server Setup and Start.
81+ server := & http.Server {
82+ Addr : PORT ,
83+ Handler : corsHandler ,
84+ ReadTimeout : 10 * time .Second ,
85+ WriteTimeout : 0 , // Set WriteTimeout to 0 for long-lived SSE connections.
86+ IdleTimeout : 0 , // Set IdleTimeout to 0 for long-lived SSE connections.
87+ BaseContext : func (_ net.Listener ) context.Context { return ctx },
4788 }
89+
90+ // Start server in a goroutine.
91+ go func () {
92+ logger .Info (fmt .Sprintf ("HTTP server starting on %s (Frontend: %s)" , server .Addr , FRONTEND_URL ))
93+ if err := server .ListenAndServe (); err != nil && ! errors .Is (err , http .ErrServerClosed ) {
94+ logger .Error (fmt .Sprintf ("HTTP server ListenAndServe error: %v" , err ))
95+ stop ()
96+ }
97+ }()
98+
99+ // Wait for Shutdown Signal.
100+ <- ctx .Done ()
101+
102+ // Initiate Graceful Shutdown.
103+ logger .Info ("Shutdown signal received. Starting graceful shutdown..." )
104+
105+ shutdownCtx , cancelShutdown := context .WithTimeout (context .Background (), 10 * time .Second )
106+ defer cancelShutdown ()
107+
108+ if err := server .Shutdown (shutdownCtx ); err != nil {
109+ logger .Error (fmt .Sprintf ("HTTP server graceful shutdown failed: %v" , err ))
110+ } else {
111+ logger .Info ("HTTP server shutdown complete." )
112+ }
113+
114+ logger .Info ("Server exiting." )
48115}
0 commit comments