graceful
Signal-aware shutdown for servers, workers, and batch jobs. Independent of cli.
import "github.com/pressly/cli/graceful"
At a glance
Each name links to godoc.
FUNCTIONS
func Run(fn func(context.Context) error, opts ...Option)
func ListenAndServe(srv *http.Server, shutdownGrace time.Duration) func(context.Context) error
OPTIONS
func WithRunTimeout(d time.Duration) Option
func WithTerminationTimeout(d time.Duration) Option
func WithImmediateTermination() Option
func WithLogger(logger *slog.Logger) Option
func WithStderr(w io.Writer) Option
Behavior
- The first signal cancels the run context.
- A second signal exits immediately.
- A run timeout cancels the context; the function must still return.
- A termination timeout caps the whole shutdown.
Exit codes:
0: successful completion1: run function returned an error124: shutdown timeout exceeded130: forced shutdown (second signal or immediate termination)
Examples
HTTP server
server := &http.Server{
Addr: ":8080",
Handler: mux,
}
graceful.Run(
// Drain requests for up to 15 seconds.
graceful.ListenAndServe(server, 15*time.Second),
// Give the whole shutdown 30 seconds.
graceful.WithTerminationTimeout(30*time.Second),
)
Batch job with a hard deadline
graceful.Run(
func(ctx context.Context) error {
// The function must return when ctx is canceled.
return processBatch(ctx)
},
graceful.WithRunTimeout(1*time.Hour),
)
Immediate termination on first signal
graceful.Run(
func(ctx context.Context) error {
return runTask(ctx)
},
graceful.WithImmediateTermination(),
)
Silence shutdown messages
graceful.Run(fn,
graceful.WithLogger(slog.New(slog.DiscardHandler)),
)