1+ // Copyright (c) 2025 A Bit of Help, Inc.
2+
3+ // Package shutdown provides functionality for graceful application shutdown.
4+ //
5+ // This package implements a robust system for handling application termination,
6+ // ensuring that resources are properly released and in-flight operations are
7+ // completed before the application exits. It handles OS signals (SIGINT, SIGTERM, SIGHUP)
8+ // and context cancellation to trigger graceful shutdown.
9+ //
10+ // Proper shutdown handling is critical for production applications to prevent:
11+ // - Data loss from incomplete operations
12+ // - Resource leaks from unclosed connections
13+ // - Inconsistent state from abrupt termination
14+ // - Service disruption for users during deployments
15+ //
16+ // Key features:
17+ // - Signal-based shutdown handling (SIGINT, SIGTERM, SIGHUP)
18+ // - Context-based shutdown initiation for programmatic control
19+ // - Timeout management to prevent hanging during shutdown
20+ // - Multiple signal handling with forced exit on second signal
21+ // - Comprehensive logging of shutdown events
22+ // - Error propagation from shutdown operations
23+ //
24+ // The package provides two main functions:
25+ // - GracefulShutdown: Blocks until shutdown is triggered, then executes cleanup
26+ // - SetupGracefulShutdown: Sets up background shutdown handling without blocking
27+ //
28+ // Example usage with GracefulShutdown (blocking approach):
29+ //
30+ // func main() {
31+ // // Initialize application components
32+ // logger := logging.NewContextLogger(zapLogger)
33+ // server := startServer()
34+ // db := connectToDatabase()
35+ //
36+ // // Define shutdown function
37+ // shutdownFunc := func() error {
38+ // // Close resources in reverse order of creation
39+ // serverErr := server.Shutdown(context.Background())
40+ // dbErr := db.Close()
41+ //
42+ // // Return combined error if any
43+ // if serverErr != nil || dbErr != nil {
44+ // return fmt.Errorf("shutdown errors: server=%v, db=%v", serverErr, dbErr)
45+ // }
46+ // return nil
47+ // }
48+ //
49+ // // Wait for shutdown signal and execute cleanup
50+ // if err := shutdown.GracefulShutdown(context.Background(), logger, shutdownFunc); err != nil {
51+ // logger.Error(context.Background(), "Shutdown completed with errors", zap.Error(err))
52+ // os.Exit(1)
53+ // }
54+ // }
55+ //
56+ // Example usage with SetupGracefulShutdown (non-blocking approach):
57+ //
58+ // func main() {
59+ // // Initialize application components
60+ // logger := logging.NewContextLogger(zapLogger)
61+ // server := startServer()
62+ // db := connectToDatabase()
63+ //
64+ // // Define shutdown function
65+ // shutdownFunc := func() error {
66+ // // Close resources in reverse order of creation
67+ // serverErr := server.Shutdown(context.Background())
68+ // dbErr := db.Close()
69+ //
70+ // // Return combined error if any
71+ // if serverErr != nil || dbErr != nil {
72+ // return fmt.Errorf("shutdown errors: server=%v, db=%v", serverErr, dbErr)
73+ // }
74+ // return nil
75+ // }
76+ //
77+ // // Set up graceful shutdown in the background
78+ // cancel, errCh := shutdown.SetupGracefulShutdown(context.Background(), logger, shutdownFunc)
79+ // defer cancel() // Ensure shutdown is triggered if main exits
80+ //
81+ // // Continue with application logic
82+ // // ...
83+ //
84+ // // Optionally wait for shutdown to complete and check for errors
85+ // if err := <-errCh; err != nil {
86+ // logger.Error(context.Background(), "Shutdown completed with errors", zap.Error(err))
87+ // os.Exit(1)
88+ // }
89+ // }
90+ //
91+ // The package is designed to be used at the application's entry point (main function)
92+ // to ensure proper resource cleanup during termination.
93+ package shutdown
0 commit comments