gocommon/webserver/webserver.go
2023-01-10 21:12:50 +00:00

76 lines
1.7 KiB
Go

package webserver
import (
"context"
"errors"
"fmt"
"net/http"
"os"
"os/signal"
"syscall"
"time"
"git.dev.m-and-m.ovh/mderasse/gocommon/commonctx"
)
const defaultTimeout = 90 * time.Second
const defaultShutdownTimeout = 10 * time.Second
type cleanupFunc func() error
// ExecuteServerParams are the parameters expected in the ExecuteServer function.
type ExecuteServerParams struct {
Cleanup cleanupFunc
ShutdownTimeout *time.Duration
}
// ExecuteServer will launche a http.Server and handle the "exit" signals and gracefully stop the server
// and call the cleanup function.
func ExecuteServer(ctx context.Context, srv *http.Server, params *ExecuteServerParams) error {
log := commonctx.GetLogger(ctx)
if srv == nil {
return fmt.Errorf("missing http.server params")
}
if srv.ReadTimeout == 0 {
srv.ReadTimeout = defaultTimeout
}
if srv.WriteTimeout == 0 {
srv.WriteTimeout = defaultTimeout
}
log.Infof("launching webserver on %s", srv.Addr)
go func() {
if err := srv.ListenAndServe(); !errors.Is(err, http.ErrServerClosed) {
log.WithError(err).Fatalf("HTTP server error: %v", err)
}
log.Info("Stopped serving new connections.")
}()
sigChan := make(chan os.Signal, 1)
signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM)
<-sigChan
shutdownCtx, shutdownRelease := context.WithTimeout(ctx, defaultShutdownTimeout)
defer shutdownRelease()
if err := srv.Shutdown(shutdownCtx); err != nil {
log.WithError(err).Warnf("HTTP shutdown error: %v", err)
}
if params.Cleanup != nil {
if err := params.Cleanup(); err != nil {
log.WithError(err).Warnf("Impossible to cleanup correctly after shutdown. error : %v", err)
return nil
}
}
log.Info("Graceful shutdown complete.")
return nil
}