in router/core/router.go [1253:1377]
func (r *Router) Shutdown(ctx context.Context) (err error) {
if !r.shutdown.CompareAndSwap(false, true) {
return nil
}
// Respect grace period
if r.routerGracePeriod > 0 {
ctxWithTimer, cancel := context.WithTimeout(ctx, r.routerGracePeriod)
defer cancel()
ctx = ctxWithTimer
}
if r.configPoller != nil {
if subErr := r.configPoller.Stop(ctx); subErr != nil {
err = errors.Join(err, fmt.Errorf("failed to stop config poller: %w", subErr))
}
}
if r.httpServer != nil {
if subErr := r.httpServer.Shutdown(ctx); subErr != nil {
if errors.Is(err, context.DeadlineExceeded) {
r.logger.Warn(
"Shutdown deadline exceeded. Router took too long to shutdown. Consider increasing the grace period",
zap.Duration("grace_period", r.routerGracePeriod),
)
}
err = errors.Join(err, fmt.Errorf("failed to shutdown router: %w", subErr))
}
}
var wg sync.WaitGroup
if r.prometheusServer != nil {
wg.Add(1)
go func() {
defer wg.Done()
if subErr := r.prometheusServer.Close(); subErr != nil {
err = errors.Join(err, fmt.Errorf("failed to shutdown prometheus server: %w", subErr))
}
}()
}
if r.tracerProvider != nil {
wg.Add(1)
go func() {
defer wg.Done()
if subErr := r.tracerProvider.Shutdown(ctx); subErr != nil {
err = errors.Join(err, fmt.Errorf("failed to shutdown tracer: %w", subErr))
}
}()
}
if r.gqlMetricsExporter != nil {
wg.Add(1)
go func() {
defer wg.Done()
if subErr := r.gqlMetricsExporter.Shutdown(ctx); subErr != nil {
err = errors.Join(err, fmt.Errorf("failed to shutdown graphql metrics exporter: %w", subErr))
}
}()
}
if r.promMeterProvider != nil {
wg.Add(1)
go func() {
defer wg.Done()
if subErr := r.promMeterProvider.Shutdown(ctx); subErr != nil {
err = errors.Join(err, fmt.Errorf("failed to shutdown prometheus meter provider: %w", subErr))
}
}()
}
if r.otlpMeterProvider != nil {
wg.Add(1)
go func() {
defer wg.Done()
if subErr := r.otlpMeterProvider.Shutdown(ctx); subErr != nil {
err = errors.Join(err, fmt.Errorf("failed to shutdown OTLP meter provider: %w", subErr))
}
}()
}
if r.redisClient != nil {
wg.Add(1)
go func() {
defer wg.Done()
if closeErr := r.redisClient.Close(); closeErr != nil {
err = errors.Join(err, fmt.Errorf("failed to close redis client: %w", closeErr))
}
}()
}
wg.Add(1)
go func() {
defer wg.Done()
for _, module := range r.modules {
if cleaner, ok := module.(Cleaner); ok {
if subErr := cleaner.Cleanup(); subErr != nil {
err = errors.Join(err, fmt.Errorf("failed to clean module %s: %w", module.Module().ID, subErr))
}
}
}
}()
// Shutdown the CDN operation client and free up resources
if r.persistedOperationClient != nil {
r.persistedOperationClient.Close()
}
wg.Wait()
return err
}