main.go from a generated project:
cmd/app/main.go
copper.New() builds the app container, which parses command-line flags, loads config, and sets up the logger and lifecycle:
Runners
Anything with aRun() error method can be run by the app:
chttp.Server and csql.Migrator both implement it, and you are free to implement it with your own types, such as a job worker, a queue consumer, or a one-off script.
Run vs. Start
app.Run(runners...)is for short-lived work. It runs each runner in order, then shuts down. This is how the migrate binary works:app.Run(migrator).app.Start(runners...)is for long-lived work. It runs each runner, then blocks until the process receivesSIGINTorSIGTERM, and shuts down gracefully. This is how the HTTP server runs.
Registering Cleanup with OnStop
You may register cleanup work, such as closing a database connection or flushing a client, usingOnStop. Copper will run these functions during shutdown, each with a deadline context:
Running Background Goroutines
You should not use a barego statement for long-running work, since the app has no way to wait for it during shutdown. Instead, use Lifecycle.Go. Goroutines started this way are tracked, awaited on shutdown, and recovered from panics, so a panic is logged with its stack trace instead of crashing the app:
Graceful Shutdown
Shutdown happens in two phases, which is what makes it graceful:Lifecycle.Shutdown()is a channel that closes when shutdown begins. Loops should select on it to exit.Lifecycle.Context()is a context that stays valid during shutdown so that in-flight work can finish. It is only canceled at the very end.