Table of contents
Part of nurago, a collection of independent Go packages for backend services.
import "github.com/tecnickcom/nurago/pkg/srvlifecycle"
The start and shutdown state machine shared by httpserver and grpcserver, exported for any other network server.
life, err := srvlifecycle.New(srv, listener,
srvlifecycle.WithName("admin"),
srvlifecycle.WithShutdownTimeout(5*time.Second),
srvlifecycle.WithShutdownWaitGroup(wg),
srvlifecycle.WithShutdownSignalChan(sc),
)
life.Start(ctx)
Any server with Serve and Shutdown
A Server needs Serve(net.Listener) error and Shutdown(context.Context) error. *http.Server satisfies it as is; a gRPC server, an SMTP server or a custom TCP protocol needs a few lines of adapter.
The point is that a custom server then stops exactly like the built-in ones, on the same wait group and signal channel, without reimplementing the corner cases below.
The corner cases it handles
- Start runs once. Later calls, and calls after a shutdown, are ignored, and the wait group is incremented before
Startreturns, so aWaitright after it cannot miss the server. - Shutdown is idempotent and concurrent-safe. The wait group is decremented exactly once, and only for a server that was started.
- An unstarted listener is closed. Only
Servetakes ownership of the listener, so shutting down a server that never started would otherwise leak the socket. - A failed Serve triggers the shutdown. Any error that does not denote a normal stop is published on
ServeErrorand starts the shutdown, so the application is not left waiting on a server that has already died.
WithServerClosedFunc decides which Serve errors count as a normal stop, since http.ErrServerClosed is specific to net/http.
Three triggers, one shutdown
The shutdown starts on a value received on the signal channel, the channel being closed, the context passed to Start being canceled, or a direct Shutdown call. The first two run it under a context bounded by WithShutdownTimeout.
Close the signal channel rather than sending a value when several servers share it: a send wakes one receiver, a close wakes all of them.
Done is closed once the first shutdown has released the wait group or the listener.
Dependencies
This package reaches no external module: it uses only the Go standard library. make depcheck fails the build if it ever does.
Links
- Reference documentation
- Source code
- Built on it: httpserver, grpcserver
- The shared wait group and signal: bootstrap
- All nurago packages