// Path: Backend/internal/process/process.go package process import ( "context" "errors" "fmt" "log/slog" "net/http" "os" "os/signal" "syscall" "time" ) func RunHTTPServer(serviceName, address string, handler http.Handler, logger *slog.Logger, shutdownTimeout time.Duration) error { server := &http.Server{ Addr: address, Handler: handler, ReadHeaderTimeout: 5 * time.Second, } serverErr := make(chan error, 1) go func() { logger.Info("http server starting", "service", serviceName, "address", address) serverErr <- server.ListenAndServe() }() signalCtx, stop := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM) defer stop() select { case err := <-serverErr: if err != nil && !errors.Is(err, http.ErrServerClosed) { return err } return nil case <-signalCtx.Done(): logger.Info("shutdown requested", "service", serviceName) } shutdownCtx, cancel := context.WithTimeout(context.Background(), shutdownTimeout) defer cancel() if err := server.Shutdown(shutdownCtx); err != nil { return fmt.Errorf("shutdown %s server: %w", serviceName, err) } logger.Info("http server stopped", "service", serviceName) return nil } func WaitForShutdown(serviceName string, logger *slog.Logger) error { signalCtx, stop := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM) defer stop() logger.Info("process running", "service", serviceName) <-signalCtx.Done() logger.Info("shutdown requested", "service", serviceName) return nil }