fix: unify shutdown resource cleanup

This commit is contained in:
MiMoCode
2026-07-10 18:52:00 +08:00
parent 6fe0a8415d
commit 1b60c8df33
3 changed files with 145 additions and 35 deletions
+39 -28
View File
@@ -25,6 +25,36 @@ func main() {
}
}
type shutdownStep struct {
name string
run func(context.Context) error
}
func waitForShutdown(stop <-chan os.Signal, serverErr <-chan error) error {
select {
case <-stop:
log.Printf("[main] shutdown signal received")
return nil
case err := <-serverErr:
if errors.Is(err, http.ErrServerClosed) {
return nil
}
return fmt.Errorf("server: %w", err)
}
}
func shutdownAll(ctx context.Context, cancelRoot context.CancelFunc, steps ...shutdownStep) error {
defer cancelRoot()
var shutdownErr error
for _, step := range steps {
if err := step.run(ctx); err != nil {
log.Printf("[main] %s shutdown: %v", step.name, err)
shutdownErr = errors.Join(shutdownErr, fmt.Errorf("%s shutdown: %w", step.name, err))
}
}
return shutdownErr
}
func run() error {
cfg, err := config.Load()
if err != nil {
@@ -73,37 +103,18 @@ func run() error {
stop := make(chan os.Signal, 1)
signal.Notify(stop, syscall.SIGINT, syscall.SIGTERM)
var runErr error
select {
case <-stop:
log.Printf("[main] shutdown signal received")
case err := <-serverErr:
if !errors.Is(err, http.ErrServerClosed) {
runErr = fmt.Errorf("server: %w", err)
}
}
runErr := waitForShutdown(stop, serverErr)
signal.Stop(stop)
// HTTP、升级连接日志排空共享同一个关闭总预算。
// HTTP、升级连接日志排空和数据库共享同一个关闭总预算。
shutdownCtx, shutdownCancel := context.WithTimeout(context.Background(), 30*time.Second)
defer shutdownCancel()
if err := srv.Shutdown(shutdownCtx); err != nil {
log.Printf("[main] http shutdown: %v", err)
}
if err := h.Shutdown(shutdownCtx); err != nil {
log.Printf("[main] upgraded connection shutdown: %v", err)
}
queueStopped := true
if err := queue.Stop(shutdownCtx); err != nil {
log.Printf("[main] queue shutdown: %v", err)
queueStopped = false
}
cancel()
if queueStopped {
pool.Close()
} else {
log.Printf("[main] skip db close while queue workers are still exiting")
}
shutdownErr := shutdownAll(shutdownCtx, cancel,
shutdownStep{name: "http", run: srv.Shutdown},
shutdownStep{name: "upgraded connection", run: h.Shutdown},
shutdownStep{name: "queue", run: func(ctx context.Context) error { return queue.Stop(ctx) }},
shutdownStep{name: "db", run: pool.Close},
)
log.Printf("[main] bye")
return runErr
return errors.Join(runErr, shutdownErr)
}