Documentation
¶
Overview ¶
Package app provides a managed lifecycle for command-line applications, ensuring graceful shutdown on OS signals.
The Run function is the main entry point. It wraps your application components (Runnables), executing them concurrently. It listens for interrupt signals (like SIGINT/SIGTERM) and propagates a cancellation signal via a context. This allows your application to perform cleanup tasks before exiting.
Usage ¶
A typical use case involves starting workers or servers that run until interrupted. The Run function handles signal trapping, concurrency, and timeouts, letting you focus on the business logic.
func main() {
// 1. Configure a logger (slog).
logger := slog.New(slog.NewTextHandler(os.Stdout, nil))
// 2. Define the application components.
// These functions block until ctx is canceled or an error occurs.
worker := func(ctx context.Context) error {
logger.Info("Worker started")
// Simulate a task that runs periodically.
ticker := time.NewTicker(1 * time.Second)
defer ticker.Stop()
for {
select {
case <-ctx.Done():
// Context canceled (signal received or sibling component failed).
logger.Info("Worker stopping...")
// Perform cleanup (e.g., closing DB connections).
time.Sleep(500 * time.Millisecond)
return nil
case t := <-ticker.C:
logger.Info("Working...", "time", t.Format(time.TimeOnly))
}
}
}
server := func(ctx context.Context) error {
logger.Info("Server started")
<-ctx.Done()
logger.Info("Server stopping...")
return nil
}
// 3. Run the application components concurrently.
err := app.RunAll(
[]app.Runnable{worker, server},
app.WithLogger(logger),
)
if err != nil {
logger.Error("Application failed", "error", err)
os.Exit(1)
}
Index ¶
Constants ¶
const DefaultTimeout = 10 * time.Second
DefaultTimeout is the default duration to wait for the application to gracefully shut down after receiving a termination signal.
Variables ¶
This section is empty.
Functions ¶
func Run ¶
Run provides a managed execution environment for a single Runnable. It launches the Runnable in a separate goroutine and blocks until it completes, an OS interrupt signal is caught, or the parent context is canceled. For running multiple components concurrently, see RunAll.
func RunAll ¶ added in v1.1.13
RunAll provides a managed execution environment for multiple Runnables. It launches each Runnable in a separate goroutine and blocks until they all complete on their own, an OS interrupt signal is caught, the parent context (if specified via WithContext) is canceled, or any single Runnable returns an error.
Upon receiving a signal or encountering an error in any Runnable, it cancels the context passed to all Runnables and waits for the specified shutdown timeout. The Runnables are expected to honor the context cancellation and perform any necessary cleanup before returning. RunAll returns any error from the Runnables themselves, or an error if the shutdown process times out.
Types ¶
type Option ¶
type Option func(*config)
Option is a function that configures the application runner.
func WithContext ¶
WithContext sets a parent context for the runner. The runner's main context will be a child of this parent. Cancelling the parent context triggers a graceful shutdown. If not set, context.Background() is used as the default parent. A nil value will be ignored.
func WithLogger ¶
WithLogger provides a custom logger for the application runner. If not set, the runner defaults to slog.Default(). A nil value will be ignored.
func WithSignals ¶
WithSignals allows customization of which OS signals trigger a shutdown. If not used, it defaults to SIGTERM and SIGINT.
func WithTimeout ¶
WithTimeout sets a custom timeout for the graceful shutdown process. If the application components take longer than this duration to return after a shutdown signal is received, the runner will exit with an error. A negative or zero duration will be ignored, and the DefaultTimeout is used instead.
type Runnable ¶
Runnable defines a function that can be executed by the application runner. It receives a context that is canceled when a shutdown signal is received, or if another concurrently running Runnable returns an error. The function should perform its cleanup and return when the context is done.