|
1 |
| -// Package ctrl provides a set of control functions for assertions, termination, and so on. |
| 1 | +// Package ctrl provides a set of control functions for assertions, error handling, HTTP server management, |
| 2 | +// and graceful shutdown handling in Go applications. Built for Go 1.21+, it offers a clean API with flexible |
| 3 | +// configuration options and no external runtime dependencies. |
| 4 | +// |
| 5 | +// # Assertions |
| 6 | +// |
| 7 | +// The package provides assertion functions that panic when conditions are not met, useful for runtime |
| 8 | +// invariant checking: |
| 9 | +// |
| 10 | +// ctrl.Assert(user.IsAuthenticated()) |
| 11 | +// ctrl.Assertf(count > 0, "expected positive count, got %d", count) |
| 12 | +// ctrl.AssertFunc(func() bool { return database.IsConnected() }) |
| 13 | +// ctrl.AssertFuncf(func() bool { return cache.Size() < maxSize }, "cache exceeded: %d", cache.Size()) |
| 14 | +// |
| 15 | +// # Error Handling |
| 16 | +// |
| 17 | +// For scenarios where returning an error is more appropriate than panicking, the package provides |
| 18 | +// ErrorOr variants: |
| 19 | +// |
| 20 | +// if err := ctrl.ErrorOr(user.IsAuthenticated()); err != nil { |
| 21 | +// return err |
| 22 | +// } |
| 23 | +// if err := ctrl.ErrorOrf(count > 0, "expected positive count, got %d", count); err != nil { |
| 24 | +// return err |
| 25 | +// } |
| 26 | +// if err := ctrl.ErrorOrFunc(func() bool { return database.IsConnected() }); err != nil { |
| 27 | +// return err |
| 28 | +// } |
| 29 | +// if err := ctrl.ErrorOrFuncf(func() bool { return cache.Size() < maxSize }, |
| 30 | +// "cache size exceeded: %d/%d", cache.Size(), maxSize); err != nil { |
| 31 | +// return err |
| 32 | +// } |
| 33 | +// customErr := errors.New("database not connected") |
| 34 | +// if err := ctrl.ErrorOrWithErr(database.IsConnected(), customErr); err != nil { |
| 35 | +// return err // Returns customErr if condition fails |
| 36 | +// } |
| 37 | +// if err := ctrl.ErrorOrFuncWithErr(func() bool { return cache.Size() < maxSize }, ErrCacheFull); err != nil { |
| 38 | +// return err // Returns ErrCacheFull if condition fails |
| 39 | +// } |
| 40 | +// |
| 41 | +// # HTTP Server Management |
| 42 | +// |
| 43 | +// The package helps manage HTTP server lifecycle, particularly graceful shutdown: |
| 44 | +// |
| 45 | +// // Shutdown an HTTP server with a timeout |
| 46 | +// err := ctrl.ShutdownHTTPServer(ctx, server, |
| 47 | +// ctrl.WithHTTPShutdownTimeout(5*time.Second)) |
| 48 | +// |
| 49 | +// // Run a server with context-aware shutdown |
| 50 | +// errCh := ctrl.RunHTTPServerWithContext(ctx, server, |
| 51 | +// func() error { return server.ListenAndServe() }, |
| 52 | +// ctrl.WithHTTPShutdownTimeout(5*time.Second), |
| 53 | +// ctrl.WithHTTPLogger(logger)) |
| 54 | +// |
| 55 | +// # Graceful Shutdown |
| 56 | +// |
| 57 | +// The package provides robust handling of process termination signals: |
| 58 | +// |
| 59 | +// // Basic setup |
| 60 | +// ctx, cancel := ctrl.GracefulShutdown() |
| 61 | +// defer cancel() |
| 62 | +// |
| 63 | +// // With custom configuration |
| 64 | +// ctx, cancel := ctrl.GracefulShutdown( |
| 65 | +// ctrl.WithTimeout(30*time.Second), |
| 66 | +// ctrl.WithSignals(syscall.SIGINT, syscall.SIGTERM, syscall.SIGHUP), |
| 67 | +// ctrl.WithExitCode(2), |
| 68 | +// ctrl.WithOnShutdown(func(sig os.Signal) { |
| 69 | +// log.Printf("shutting down due to %s signal", sig) |
| 70 | +// database.Close() |
| 71 | +// }), |
| 72 | +// ctrl.WithOnForceExit(func() { |
| 73 | +// log.Printf("force exiting after timeout") |
| 74 | +// }), |
| 75 | +// ctrl.WithLogger(logger)) |
| 76 | +// |
| 77 | +// # Best Practices |
| 78 | +// |
| 79 | +// Use assertions for internal invariants that should never fail in correct code: |
| 80 | +// |
| 81 | +// ctrl.Assert(len(buffer) >= headerSize) // Internal invariant |
| 82 | +// |
| 83 | +// Use ErrorOr variants for validating external input or recoverable conditions: |
| 84 | +// |
| 85 | +// if err := ctrl.ErrorOr(len(userInput) < maxLength); err != nil { |
| 86 | +// return err // External input validation |
| 87 | +// } |
| 88 | +// |
| 89 | +// For HTTP servers, combine graceful shutdown with server lifecycle management: |
| 90 | +// |
| 91 | +// ctx, cancel := ctrl.GracefulShutdown(ctrl.WithTimeout(10*time.Second)) |
| 92 | +// defer cancel() |
| 93 | +// errCh := ctrl.RunHTTPServerWithContext(ctx, server, server.ListenAndServe) |
| 94 | +// if err := <-errCh; err != nil { |
| 95 | +// log.Fatalf("server error: %v", err) |
| 96 | +// } |
2 | 97 | package ctrl
|
0 commit comments