Skip to content

rgzr/graceful

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

graceful

graceful is a Go package for handling application lifecycle, signal-driven shutdown, and structured exit events.
It provides a single Run entrypoint that runs your application, listens for exit signals, and coordinates graceful → cancel → forced shutdown sequences with configurable timeouts.

Features

  • Run your application with clean lifecycle management.
  • Capture termination signals (SIGTERM, SIGINT).
  • Execute graceful, cancel, and forced shutdown logic in order.
  • Configurable timeouts for each phase.
  • Structured events (ExitType, Action) for observability.
  • Optional hooks (EventsFunc, ExitFunc) for telemetry and cleanup.

Shutdown sequence

When receiving an exit signal or programmatic exit, graceful coordinates shutdown in phases:

1. Graceful shutdown

If GracefulFunc is configured and GracefulTimeout > 0, it is called.
Typical use: stop accepting new work, but let ongoing operations finish.
If your application does not exit before the timeout, the cancel phase begins.

2. Cancel shutdown

If CancelFunc is configured and CancelTimeout > 0, it is called.
Typical use: cancel contexts, return errors to clients, clean up resources.
If your application does not exit before the timeout, the forced phase begins.

3. Forced shutdown

If ForcedFunc is configured and ForcedTimeout > 0, it is called.
Typical use: log an error about stuck operations, release critical resources.
If your application still does not exit, the program is aborted.

4. Abort

Immediately exits the application.

Note, a second signal received at any time also immediately aborts the application.

Install

go get github.com/rgzr/graceful

Usage

package main

import (
    "fmt"
    "time"

    "github.com/rgzr/graceful"
)

func main() {
    graceful.Run(&graceful.Config{
        RunFunc: func() error {
            fmt.Println("application running")
            // Simulate workload until killed
            select {}
        },

        GracefulFunc: func() {
            fmt.Println("stopping new work, letting ongoing operations finish")
            // maybe call *http.Server.Shutdown() here
        },

        CancelFunc: func() {
            fmt.Println("cancelling ongoing operations")
            // maybe pass the app context here and cancel it
        },

        ForcedFunc: func() {
            fmt.Println("forcing shutdown, some operations may be lost")
            // maybe signal parents to stop waiting for children here and return errors instead
        },

        GracefulTimeout: 5 * time.Second,
        CancelTimeout:   3 * time.Second,
        ForcedTimeout:   1 * time.Second,

        EventsFunc: func(e *graceful.Event) {
            fmt.Printf("event: exitType=%s action=%s\n", e.ExitType, e.Action)
        },

        ExitFunc: func(err error) {
            fmt.Printf("exiting with error: %v\n", err)
        },
    })
}

About

Graceful golang application shutdown.

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages