# interrupt Graceful shutdown handling for Go applications. This package provides utilities for handling OS signals (SIGINT, SIGTERM) to enable clean shutdowns and hot reloading capabilities. ## Features - **Signal Handling**: Clean handling of SIGINT, SIGTERM, and SIGHUP signals - **Graceful Shutdown**: Allows running goroutines to finish before exit - **Hot Reload Support**: Trigger application reloads on SIGHUP - **Context Integration**: Works seamlessly with Go's context package - **Custom Callbacks**: Execute custom cleanup logic during shutdown - **Non-blocking**: Doesn't block the main application loop ## Installation ```bash go get next.orly.dev/pkg/utils/interrupt ``` ## Usage ### Basic Shutdown Handling ```go package main import ( "context" "log" "time" "next.orly.dev/pkg/utils/interrupt" ) func main() { // Create interrupt handler handler := interrupt.New() // Start your application go func() { for { select { case <-handler.Shutdown(): log.Println("Shutting down worker...") return default: // Do work time.Sleep(time.Second) } } }() // Wait for shutdown signal <-handler.Done() log.Println("Application stopped") } ``` ### Context Integration ```go func worker(ctx context.Context) { handler := interrupt.New() // Create context that cancels on shutdown workCtx, cancel := context.WithCancel(ctx) defer cancel() go func() { <-handler.Shutdown() cancel() }() // Use workCtx for all operations for { select { case <-workCtx.Done(): return default: // Do work with context } } } ``` ### Custom Shutdown Callbacks ```go handler := interrupt.New() // Add cleanup callbacks handler.OnShutdown(func() { log.Println("Closing database connections...") db.Close() }) handler.OnShutdown(func() { log.Println("Saving application state...") saveState() }) // Callbacks execute in reverse order when shutdown occurs <-handler.Done() ``` ### Hot Reload Support ```go handler := interrupt.New() // Handle reload signals go func() { for { select { case <-handler.Reload(): log.Println("Reloading configuration...") reloadConfig() case <-handler.Shutdown(): return } } }() <-handler.Done() ``` ## API Reference ### Handler The main interrupt handler type. **Methods:** - `New() *Handler` - Create a new interrupt handler - `Shutdown() <-chan struct{}` - Channel closed on shutdown signals - `Reload() <-chan struct{}` - Channel closed on reload signals (SIGHUP) - `Done() <-chan struct{}` - Channel closed when all cleanup is complete - `OnShutdown(func())` - Add a callback to run during shutdown - `Wait()` - Block until shutdown signal received - `IsShuttingDown() bool` - Check if shutdown is in progress ### Signal Handling The package handles these signals: - **SIGINT**: Interrupt (Ctrl+C) - Triggers graceful shutdown - **SIGTERM**: Termination - Triggers graceful shutdown - **SIGHUP**: Hangup - Triggers reload (can be customized) ### Shutdown Process 1. Signal received (SIGINT/SIGTERM) 2. Shutdown callbacks execute (in reverse order added) 3. Shutdown channel closes 4. Application can perform final cleanup 5. Done channel closes ## Testing The interrupt package includes comprehensive tests: ### Running Tests ```bash # Run interrupt package tests go test ./pkg/utils/interrupt # Run with verbose output go test -v ./pkg/utils/interrupt # Run with race detection go test -race ./pkg/utils/interrupt ``` ### Integration Testing Part of the full test suite: ```bash # Run all tests including interrupt ./scripts/test.sh # Run specific package tests go test ./pkg/utils/... ``` ### Test Coverage Tests cover: - Signal handling for all supported signals - Callback execution order and timing - Context cancellation - Concurrent access patterns - Race condition prevention ### Example Test ```bash # Test signal handling go test -v ./pkg/utils/interrupt -run TestSignalHandling # Test callback execution go test -v ./pkg/utils/interrupt -run TestShutdownCallbacks ``` ## Examples ### HTTP Server with Graceful Shutdown ```go package main import ( "context" "log" "net/http" "time" "next.orly.dev/pkg/utils/interrupt" ) func main() { handler := interrupt.New() server := &http.Server{ Addr: ":8080", Handler: http.DefaultServeMux, } // Shutdown server gracefully handler.OnShutdown(func() { ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() server.Shutdown(ctx) }) go server.ListenAndServe() <-handler.Done() log.Println("Server stopped") } ``` ### Worker Pool with Cleanup ```go func main() { handler := interrupt.New() // Start worker pool pool := NewWorkerPool(10) pool.Start() // Clean shutdown handler.OnShutdown(func() { log.Println("Stopping worker pool...") pool.Stop() }) <-handler.Done() } ``` ## Development ### Building ```bash go build ./pkg/utils/interrupt ``` ### Code Quality - Comprehensive test coverage - Go best practices compliance - Thread-safe design - Proper signal handling - No external dependencies ## Integration This package integrates well with: - HTTP servers (graceful shutdown) - Database connections (cleanup) - Worker pools (coordination) - Long-running services (reload capability) ## License Part of the next.orly.dev project. See main LICENSE file.