68 lines
1.4 KiB
Go
68 lines
1.4 KiB
Go
package app
|
|
|
|
import (
|
|
"context"
|
|
"sync"
|
|
"time"
|
|
|
|
"go.opentelemetry.io/otel/codes"
|
|
)
|
|
|
|
// Watches contexts and channels for the
|
|
// app to be finished and calls shutdown once
|
|
// the app is done
|
|
func (a *App) run() {
|
|
select {
|
|
case <-a.AppContext.Done():
|
|
a.l.Warn().Str("reason", a.AppContext.Err().Error()).
|
|
Msg("shutting down on context done")
|
|
case <-a.HTTP.httpDone:
|
|
a.l.Warn().Msg("shutting down early on http server done")
|
|
}
|
|
a.Shutdown()
|
|
|
|
a.appDone <- nil
|
|
}
|
|
|
|
// Typically invoked when AppContext is done
|
|
// or Server has exited. Not intended to be called
|
|
// manually
|
|
func (a *App) Shutdown() {
|
|
now := time.Now()
|
|
|
|
doneCtx, cncl := context.WithTimeout(context.Background(), 15*time.Second)
|
|
defer func() {
|
|
if doneCtx.Err() == context.DeadlineExceeded {
|
|
a.l.Err(doneCtx.Err()).
|
|
Dur("shutdownTime", time.Since(now)).
|
|
Msg("app shutdown aborted")
|
|
} else {
|
|
a.l.Info().
|
|
Int("shutdownFuncsCalled", len(a.shutdownFuncs)).
|
|
Dur("shutdownTime", time.Since(now)).
|
|
Msg("app shutdown normally")
|
|
}
|
|
cncl()
|
|
}()
|
|
|
|
doneCtx, span := a.tracer.Start(doneCtx, "shutdown")
|
|
defer span.End()
|
|
|
|
var wg sync.WaitGroup
|
|
wg.Add(len(a.shutdownFuncs))
|
|
|
|
for _, f := range a.shutdownFuncs {
|
|
go func() {
|
|
defer wg.Done()
|
|
err := f(doneCtx)
|
|
if err != nil {
|
|
span.SetStatus(codes.Error, "shutdown failed")
|
|
span.RecordError(err)
|
|
a.l.Err(err).Send()
|
|
}
|
|
}()
|
|
}
|
|
|
|
wg.Wait()
|
|
}
|