### Ordered Service Shutdown in Go with GS Source: https://context7.com/shengyanli1982/gs/llms.txt This example shows how to use the GS library to gracefully shut down dependent services in a specific order. It involves creating and connecting a database, initializing a cache, and starting an API server, then shutting them down sequentially upon receiving a termination signal. ```Go package main import ( "fmt" "os" "time" "github.com/shengyanli1982/gs" ) type Database struct { connected bool } func (d *Database) Connect() { d.connected = true fmt.Println("Database connected") } func (d *Database) Close() { if d.connected { fmt.Println("Closing database...") time.Sleep(100 * time.Millisecond) d.connected = false fmt.Println("Database closed") } } type Cache struct { db *Database } func (c *Cache) Initialize(db *Database) { c.db = db fmt.Println("Cache initialized") } func (c *Cache) Close() { fmt.Println("Flushing cache...") time.Sleep(50 * time.Millisecond) fmt.Println("Cache closed") } type APIServer struct { cache *Cache } func (a *APIServer) Start(cache *Cache) { a.cache = cache fmt.Println("API server started") } func (a *APIServer) Stop() { fmt.Println("Stopping API server...") time.Sleep(150 * time.Millisecond) fmt.Println("API server stopped") } func main() { db := &Database{} db.Connect() cache := &Cache{} cache.Initialize(db) api := &APIServer{} api.Start(cache) sig := gs.NewTerminateSignal() sig.RegisterCancelHandles( api.Stop, cache.Close, db.Close, ) go func() { time.Sleep(2 * time.Second) p, _ := os.FindProcess(os.Getpid()) p.Signal(os.Interrupt) }() gs.WaitForForceSync(sig) fmt.Println("All services shut down in correct order") } ``` -------------------------------- ### Implement graceful shutdown with TerminateSignal in Go Source: https://github.com/shengyanli1982/gs/blob/main/README.md This Go example uses the gs library to coordinate graceful termination of multiple services. It registers Close, Shutdown, and Terminate handlers, sends an interrupt signal to the current process (effective on Linux/macOS), and waits for all handlers to complete. The code requires the gs package and works only on platforms that support os.Process.Signal. ```go package main import ( "fmt" "os" "time" "github.com/shengyanli1982/gs" ) // 模拟一个服务 // Simulate a service type testTerminateSignal struct{} // Close 方法用于关闭 testTerminateSignal 服务 // The Close method is used to close the testTerminateSignal service func (t *testTerminateSignal) Close() { fmt.Println("testTerminateSignal.Close()") } // 模拟一个服务 // Simulate a service type testTerminateSignal2 struct{} // Shutdown 方法用于关闭 testTerminateSignal2 服务 // The Shutdown method is used to close the testTerminateSignal2 service func (t *testTerminateSignal2) Shutdown() { fmt.Println("testTerminateSignal2.Shutdown()") } // 模拟一个服务 // Simulate a service type testTerminateSignal3 struct{} // Terminate 方法用于关闭 testTerminateSignal3 服务 // The Terminate method is used to close the testTerminateSignal3 service func (t *testTerminateSignal3) Terminate() { fmt.Println("testTerminateSignal3.Terminate()") } func main() { // 创建一个新的 TerminateSignal 实例 // Create a new TerminateSignal instance s := gs.NewTerminateSignal() // 创建三个测试服务的实例 // Create instances of three test services t1 := &testTerminateSignal{} t2 := &testTerminateSignal2{} t3 := &testTerminateSignal3{} // 注册需要在终止信号发生时执行的处理函数 // Register the handle functions to be executed when the termination signal occurs s.RegisterCancelHandles(t1.Close, t2.Shutdown, t3.Terminate) // 在新的 goroutine 中执行一个函数 // Execute a function in a new goroutine go func() { // 等待 2 秒 // Wait for 2 seconds time.Sleep(2 * time.Second) // 查找当前进程 // Find the current process p, err := os.FindProcess(os.Getpid()) if err != nil { fmt.Println(err.Error()) } // 向当前进程发送中断信号, os.Process.Signal() 对 Linux 和 MacOS 有效, Windows 无效 // Send an interrupt signal to the current process, os.Process.Signal() is valid for Linux and MacOS, invalid for Windows err = p.Signal(os.Interrupt) if err != nil { fmt.Println(err.Error()) } }() // 等待所有的异步关闭信号 // Wait for all asynchronous shutdown signals gs.WaitForAsync(s) // 打印一条消息,表示服务已经优雅地关闭 // Print a message indicating that the service has been gracefully shut down fmt.Println("shutdown gracefully") } ``` -------------------------------- ### HTTP server graceful shutdown integration (Go) Source: https://context7.com/shengyanli1982/gs/llms.txt Demonstrates graceful HTTP server shutdown using gs signal handling. Integrates with http.Server.Shutdown() with timeout context. Shows production-ready pattern for web services. ```go package main import ( "context" "fmt" "net/http" "os" "time" "github.com/shengyanli1982/gs" ) func main() { sig := gs.NewTerminateSignal() mux := http.NewServeMux() mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, "Hello, World!") }) server := &http.Server{ Addr: ":8080", Handler: mux, } sig.RegisterCancelHandles(func() { fmt.Println("Shutting down HTTP server...") ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() if err := server.Shutdown(ctx); err != nil { fmt.Printf("Server shutdown error: %v\n", err) } fmt.Println("HTTP server stopped") }) go func() { fmt.Println("Starting server on :8080") if err := server.ListenAndServe(); err != http.ErrServerClosed { fmt.Printf("Server error: %v\n", err) } }() go func() { time.Sleep(3 * time.Second) p, _ := os.FindProcess(os.Getpid()) p.Signal(os.Interrupt) }() gs.WaitForAsync(sig) fmt.Println("Application shutdown complete") } ``` -------------------------------- ### Create Basic Termination Handler - Go Source: https://context7.com/shengyanli1982/gs/llms.txt Creates a new TerminateSignal using a default background context, registers cleanup functions for a DatabaseService and a CacheService, triggers an os.Interrupt to simulate shutdown, and waits for the handlers to complete asynchronously. Demonstrates typical usage of the library for graceful shutdown. ```go package main import ( "fmt" "os" "time" "github.com/shengyanli1982/gs" ) type DatabaseService struct{} func (d *DatabaseService) Close() { fmt.Println("Closing database connections...") time.Sleep(100 * time.Millisecond) // Simulate cleanup fmt.Println("Database closed") } type CacheService struct{} func (c *CacheService) Shutdown() { fmt.Println("Flushing cache...") time.Sleep(50 * time.Millisecond) // Simulate cleanup fmt.Println("Cache shutdown complete") } func main() { sig := gs.NewTerminateSignal() db := &DatabaseService{} cache := &CacheService{} sig.RegisterCancelHandles(db.Close, cache.Shutdown) go func() { time.Sleep(2 * time.Second) p, _ := os.FindProcess(os.Getpid()) p.Signal(os.Interrupt) }() gs.WaitForAsync(sig) fmt.Println("Application shutdown gracefully") } // Output: // Flushing cache... // Closing database connections... // Cache shutdown complete // Database closed // Application shutdown gracefully ``` -------------------------------- ### Register Multiple Cleanup Handlers - Go Source: https://context7.com/shengyanli1982/gs/llms.txt Demonstrates registering multiple cleanup handlers (flushMetrics, closeLogFile, notifyMonitoring) with a single call to RegisterCancelHandles, shows typical data flushing and coordination using a mutex, triggers an interrupt, and waits asynchronously. Highlights handler invocation order and concurrency considerations. ```go package main import ( "fmt" "os" "sync" "time" "github.com/shengyanli1982/gs" ) var ( requestCount int mu sync.Mutex ) func flushMetrics() { mu.Lock() defer mu.Unlock() fmt.Printf("Flushing metrics: %d requests processed\n", requestCount) } func closeLogFile() { fmt.Println("Closing log file handles") } func notifyMonitoring() { fmt.Println("Notifying monitoring system of shutdown") } func main() { sig := gs.NewTerminateSignal() sig.RegisterCancelHandles( flushMetrics, closeLogFile, notifyMonitoring, ) requestCount = 12345 go func() { time.Sleep(1 * time.Second) p, _ := os.FindProcess(os.Getpid()) p.Signal(os.Interrupt) }() gs.WaitForAsync(sig) } // Output (order may vary due to async execution): // Flushing metrics: 12345 requests processed // Closing log file handles // Notifying monitoring system of shutdown ``` -------------------------------- ### Wait for OS signal with full synchronous execution (Go) Source: https://context7.com/shengyanli1982/gs/llms.txt Blocks until OS signal received, executes all signal handlers sequentially. Uses github.com/shengyanli1982/gs package. Shows strict ordered execution for critical shutdown procedures. ```go package main import ( "fmt" "os" "time" "github.com/shengyanli1982/gs" ) func main() { sig := gs.NewTerminateSignal() sig.RegisterCancelHandles( func() { fmt.Println("1. Stopping new request acceptance") time.Sleep(100 * time.Millisecond) }, func() { fmt.Println("2. Completing in-flight requests") time.Sleep(100 * time.Millisecond) }, func() { fmt.Println("3. Flushing buffers") time.Sleep(100 * time.Millisecond) }, func() { fmt.Println("4. Closing database pool") time.Sleep(100 * time.Millisecond) }, ) go func() { time.Sleep(1 * time.Second) p, _ := os.FindProcess(os.Getpid()) p.Signal(os.Interrupt) }() gs.WaitForForceSync(sig) fmt.Println("Fully synchronous shutdown complete") } ``` -------------------------------- ### Wait for OS signal with sequential execution (Go) Source: https://context7.com/shengyanli1982/gs/llms.txt Blocks until OS signal received, closes TerminateSignals sequentially while handlers run concurrently. Uses github.com/shengyanli1982/gs package. Demonstrates ordered shutdown of multiple signal groups. ```go package main import ( "fmt" "os" "time" "github.com/shengyanli1982/gs" ) func main() { sig1 := gs.NewTerminateSignal() sig2 := gs.NewTerminateSignal() sig3 := gs.NewTerminateSignal() sig1.RegisterCancelHandles( func() { fmt.Println("Signal 1: Handler A") }, func() { fmt.Println("Signal 1: Handler B") }, ) sig2.RegisterCancelHandles( func() { fmt.Println("Signal 2: Handler A") }, func() { fmt.Println("Signal 2: Handler B") }, ) sig3.RegisterCancelHandles( func() { fmt.Println("Signal 3: Handler A") }, ) go func() { time.Sleep(1 * time.Second) p, _ := os.FindProcess(os.Getpid()) p.Signal(os.Interrupt) }() gs.WaitForSync(sig1, sig2, sig3) fmt.Println("All signals closed in order") } ``` -------------------------------- ### Create Handler with Custom Context - Go Source: https://context7.com/shengyanli1982/gs/llms.txt Creates a TerminateSignal with a custom context that has a 3-second timeout, registers a long-running cleanup that exceeds the timeout, triggers an interrupt, and waits asynchronously. Demonstrates time-bounded graceful shutdown and behavior when the context expires. ```go package main import ( "context" "fmt" "os" "time" "github.com/shengyanli1982/gs" ) func longRunningCleanup() { fmt.Println("Starting long cleanup operation...") time.Sleep(5 * time.Second) fmt.Println("Cleanup completed") } func main() { ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second) defer cancel() sig := gs.NewTerminateSignalWithContext(ctx) sig.RegisterCancelHandles(longRunningCleanup) go func() { time.Sleep(1 * time.Second) p, _ := os.FindProcess(os.Getpid()) p.Signal(os.Interrupt) }() gs.WaitForAsync(sig) fmt.Println("Shutdown complete (may have been interrupted by timeout)") } // Output: // Starting long cleanup operation... // Shutdown complete (may have been interrupted by timeout) ``` -------------------------------- ### WaitForAsync() - Wait for Signal with Async Execution Go Source: https://context7.com/shengyanli1982/gs/llms.txt Blocks until an OS signal is received and then closes the TerminateSignal, executing registered handlers concurrently. This combination allows for efficient signal handling and asynchronous shutdown procedures, letting multiple tasks complete before application termination. ```Go package main import ( "fmt" "os" "time" "github.com/shengyanli1982/gs" ) type HTTPServer struct{} func (h *HTTPServer) Stop() { fmt.Println("HTTP server stopped") } type MessageQueue struct{} func (m *MessageQueue) Close() { fmt.Println("Message queue closed") } type Redis struct{} func (r *Redis) Disconnect() { fmt.Println("Redis disconnected") } func main() { sig := gs.NewTerminateSignal() http := &HTTPServer{} mq := &MessageQueue{} redis := &Redis{} sig.RegisterCancelHandles( http.Stop, mq.Close, redis.Disconnect, ) fmt.Println("Application running... Press Ctrl+C to shutdown") go func() { time.Sleep(2 * time.Second) p, _ := os.FindProcess(os.Getpid()) p.Signal(os.Interrupt) }() gs.WaitForAsync(sig) fmt.Println("Application terminated") } ``` -------------------------------- ### SyncClose() - Synchronous Shutdown Go Source: https://context7.com/shengyanli1982/gs/llms.txt Closes the TerminateSignal and executes all registered handlers sequentially. This is important when the order of shutdown matters, such as closing database connections before HTTP servers. The handlers will run one after the other, ensuring a specific order of operations. ```Go package main import ( "fmt" "time" "github.com/shengyanli1982/gs" ) func main() { sig := gs.NewTerminateSignal() sig.RegisterCancelHandles( func() { fmt.Println("Step 1: Stopping HTTP server") time.Sleep(100 * time.Millisecond) }, func() { fmt.Println("Step 2: Closing cache connections") time.Sleep(100 * time.Millisecond) }, func() { fmt.Println("Step 3: Closing database connections") time.Sleep(100 * time.Millisecond) }, ) sig.SyncClose(nil) fmt.Println("Shutdown complete") } ``` -------------------------------- ### GetStopContext() - Go Source: https://context7.com/shengyanli1982/gs/llms.txt Retrieves the internal context for integration with other components supporting context-based cancellation. This allows for coordinated shutdowns across multiple services or workers. The function utilizes Go's context package for signaling cancellation. ```Go package main import ( "context" "fmt" "os" "time" "github.com/shengyanli1982/gs" ) func worker(ctx context.Context, id int) { for { select { case <-ctx.Done(): fmt.Printf("Worker %d: received shutdown signal, stopping\n", id) return default: fmt.Printf("Worker %d: processing...\n", id) time.Sleep(500 * time.Millisecond) } } } func main() { sig := gs.NewTerminateSignal() ctx := sig.GetStopContext() for i := 1; i <= 3; i++ { go worker(ctx, i) } sig.RegisterCancelHandles(func() { fmt.Println("All workers stopped via context cancellation") }) go func() { time.Sleep(2 * time.Second) p, _ := os.FindProcess(os.Getpid()) p.Signal(os.Interrupt) }() gs.WaitForAsync(sig) } ``` -------------------------------- ### Close() - Asynchronous Shutdown Go Source: https://context7.com/shengyanli1982/gs/llms.txt Closes the TerminateSignal and executes all registered handlers concurrently. This is useful for scenarios where the order of handler execution is not critical, and speed is desired. It uses Go's goroutines to execute handlers in parallel. ```Go package main import ( "fmt" "sync" "time" "github.com/shengyanli1982/gs" ) func main() { sig := gs.NewTerminateSignal() sig.RegisterCancelHandles( func() { fmt.Println("Handler 1: start") time.Sleep(200 * time.Millisecond) fmt.Println("Handler 1: complete") }, func() { fmt.Println("Handler 2: start") time.Sleep(100 * time.Millisecond) fmt.Println("Handler 2: complete") }, func() { fmt.Println("Handler 3: start") time.Sleep(150 * time.Millisecond) fmt.Println("Handler 3: complete") }, ) wg := sync.WaitGroup{} wg.Add(1) sig.Close(&wg) wg.Wait() fmt.Println("All handlers completed") } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.