diff --git a/app.go b/app.go index a9a01d5..ebbec68 100644 --- a/app.go +++ b/app.go @@ -7,6 +7,7 @@ import ( "fmt" "net/http" "net/http/pprof" // Sadly, this also changes the DefaultMux to have the pprof URLs + "os" "os/signal" "sync" "sync/atomic" @@ -183,16 +184,22 @@ func (app *App) RunAndWait(mainLoop MainLoopFunc) { // Run main loop on a go-routine errs := make(chan error, 1) go app.runMainLoop(mainLoop, errs) - app.waitMainLoopOrSignal(errs) + err := app.waitMainLoopOrSignal(errs) // App is shutting down... app.readinessProbe.SetNotOk() app.waitGracePeriod() - _ = app.Shutdown(context.Background()) + shutdownErr := app.Shutdown(context.Background()) app.waitMainLoopFinish(10 * time.Second) // This forces kubernetes kills the pod if some other code is holding the main func. app.healthinessProbe.SetNotOk() + + // Ensure that the app finishes with an error code if the main loop finished by itself + // with an error or if the shutdown procedure failed with an error. + if err != nil || shutdownErr != nil { + os.Exit(1) + } } func (app *App) runMainLoop(mainLoop MainLoopFunc, errs chan<- error) { @@ -212,7 +219,7 @@ func (app *App) runMainLoop(mainLoop MainLoopFunc, errs chan<- error) { errs <- mainLoop(app.mainLoopCtx) } -func (app *App) waitMainLoopOrSignal(errs <-chan error) { +func (app *App) waitMainLoopOrSignal(errs <-chan error) error { gracefulShutdownCtx, cancel := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM) defer cancel() @@ -220,14 +227,16 @@ func (app *App) waitMainLoopOrSignal(errs <-chan error) { case err := <-errs: if err != nil { log.Error().Err(err).Msg("[app] Main Loop finished by itself with error.") + return err } else { - log.Warn().Msg("[app] Main Loop finished by itself without error. Ideally the main loop should be finished by a graceful shutdown handler.") + log.Info().Msg("[app] Main Loop finished by itself.") } case <-gracefulShutdownCtx.Done(): log.Info(). Dur("grace_period", app.shutdown.gracePeriod). Msg("[app] Graceful shutdown signal received.") } + return nil } func (app *App) waitGracePeriod() { diff --git a/go.mod b/go.mod index 6ca1f64..ff40c47 100644 --- a/go.mod +++ b/go.mod @@ -1,12 +1,12 @@ module github.com/arquivei/go-app -go 1.25 +go 1.25.0 require ( github.com/prometheus/client_golang v1.23.2 github.com/rs/zerolog v1.34.0 github.com/stretchr/testify v1.11.1 - golang.org/x/text v0.34.0 + golang.org/x/text v0.35.0 ) require ( @@ -20,9 +20,9 @@ require ( github.com/pmezard/go-difflib v1.0.0 // indirect github.com/prometheus/client_model v0.6.2 // indirect github.com/prometheus/common v0.67.5 // indirect - github.com/prometheus/procfs v0.19.2 // indirect - go.yaml.in/yaml/v2 v2.4.3 // indirect - golang.org/x/sys v0.41.0 // indirect + github.com/prometheus/procfs v0.20.1 // indirect + go.yaml.in/yaml/v2 v2.4.4 // indirect + golang.org/x/sys v0.42.0 // indirect google.golang.org/protobuf v1.36.11 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index d93f375..c62a146 100644 --- a/go.sum +++ b/go.sum @@ -35,8 +35,8 @@ github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNw github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE= github.com/prometheus/common v0.67.5 h1:pIgK94WWlQt1WLwAC5j2ynLaBRDiinoAb86HZHTUGI4= github.com/prometheus/common v0.67.5/go.mod h1:SjE/0MzDEEAyrdr5Gqc6G+sXI67maCxzaT3A2+HqjUw= -github.com/prometheus/procfs v0.19.2 h1:zUMhqEW66Ex7OXIiDkll3tl9a1ZdilUOd/F6ZXw4Vws= -github.com/prometheus/procfs v0.19.2/go.mod h1:M0aotyiemPhBCM0z5w87kL22CxfcH05ZpYlu+b4J7mw= +github.com/prometheus/procfs v0.20.1 h1:XwbrGOIplXW/AU3YhIhLODXMJYyC1isLFfYCsTEycfc= +github.com/prometheus/procfs v0.20.1/go.mod h1:o9EMBZGRyvDrSPH1RqdxhojkuXstoe4UlK79eF5TGGo= github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= github.com/rs/xid v1.6.0/go.mod h1:7XoLgs4eV+QndskICGsho+ADou8ySMSjJKDIan90Nz0= @@ -46,15 +46,15 @@ github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= -go.yaml.in/yaml/v2 v2.4.3 h1:6gvOSjQoTB3vt1l+CU+tSyi/HOjfOjRLJ4YwYZGwRO0= -go.yaml.in/yaml/v2 v2.4.3/go.mod h1:zSxWcmIDjOzPXpjlTTbAsKokqkDNAVtZO0WOMiT90s8= +go.yaml.in/yaml/v2 v2.4.4 h1:tuyd0P+2Ont/d6e2rl3be67goVK4R6deVxCUX5vyPaQ= +go.yaml.in/yaml/v2 v2.4.4/go.mod h1:gMZqIpDtDqOfM0uNfy0SkpRhvUryYH0Z6wdMYcacYXQ= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.41.0 h1:Ivj+2Cp/ylzLiEU89QhWblYnOE9zerudt9Ftecq2C6k= -golang.org/x/sys v0.41.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= -golang.org/x/text v0.34.0 h1:oL/Qq0Kdaqxa1KbNeMKwQq0reLCCaFtqu2eNuSeNHbk= -golang.org/x/text v0.34.0/go.mod h1:homfLqTYRFyVYemLBFl5GgL/DWEiH5wcsQ5gSh1yziA= +golang.org/x/sys v0.42.0 h1:omrd2nAlyT5ESRdCLYdm3+fMfNFE/+Rf4bDIQImRJeo= +golang.org/x/sys v0.42.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= +golang.org/x/text v0.35.0 h1:JOVx6vVDFokkpaq1AEptVzLTpDe9KGpj5tR4/X+ybL8= +golang.org/x/text v0.35.0/go.mod h1:khi/HExzZJ2pGnjenulevKNX1W67CUy0AsXcNubPGCA= google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE= google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=