// Package shutdown provides graceful shutdown handling for services. package shutdown import ( "context" "os" "os/signal" "syscall" ) // Hook is a cleanup function called during shutdown. type Hook struct { Name string Fn func() error } // simpleLogger is the minimal interface required from a logger. type simpleLogger interface { Info(string) Error(string, error) } // Handle blocks until SIGTERM or SIGINT is received, then cancels the context // and runs hooks in order. Each hook error is logged but does not abort remaining hooks. func Handle(ctx context.Context, cancel context.CancelFunc, hooks []Hook, logger simpleLogger) { quit := make(chan os.Signal, 1) signal.Notify(quit, syscall.SIGTERM, syscall.SIGINT) defer signal.Stop(quit) select { case sig := <-quit: logger.Info("shutdown signal received: " + sig.String()) case <-ctx.Done(): logger.Info("context cancelled, shutting down") } cancel() for _, h := range hooks { logger.Info("running shutdown hook: " + h.Name) if err := h.Fn(); err != nil { logger.Error("shutdown hook "+h.Name+" failed", err) } } }