Documentation ¶
Overview ¶
Package shutdown provides management of your shutdown process.
The package will enable you to get notifications for your application and handle the shutdown process.
See more information about the how to use it in the README.md file ¶
Package home: https://github.com/klauspost/shutdown
This package has been updated to a new version. If you are starting a new project, use the new package:
* Package home: https://github.com/klauspost/shutdown2 * Godoc: https://godoc.org/github.com/klauspost/shutdown2
Version 2 mainly contains minor adjustments to the API to make it a bit easier to use.
This package remains here to maintain compatibility.
Index ¶
- Variables
- func Exit(code int)
- func Lock() bool
- func OnSignal(exitCode int, sig ...os.Signal)
- func SetTimeout(d time.Duration)
- func SetTimeoutN(s Stage, d time.Duration)
- func Shutdown()
- func Started() bool
- func Unlock()
- func Wait()
- func WrapHandler(h http.Handler) http.Handler
- func WrapHandlerFunc(h http.HandlerFunc) http.HandlerFunc
- type Notifier
- func First() Notifier
- func FirstFunc(fn ShutdownFn, v interface{}) Notifier
- func PreShutdown() Notifier
- func PreShutdownFunc(fn ShutdownFn, v interface{}) Notifier
- func Second() Notifier
- func SecondFunc(fn ShutdownFn, v interface{}) Notifier
- func Third() Notifier
- func ThirdFunc(fn ShutdownFn, v interface{}) Notifier
- type ShutdownFn
- type Stage
Examples ¶
Constants ¶
This section is empty.
Variables ¶
Logger used for output. This can be exchanged with your own.
var Preshutdown = Stage{0} // Indicates stage when waiting for locks to be released.
var Stage1 = Stage{1} // Indicates first stage of timeouts.
var Stage2 = Stage{2} // Indicates second stage of timeouts.
var Stage3 = Stage{3} // Indicates third stage of timeouts.
Functions ¶
func Exit ¶
func Exit(code int)
Exit performs shutdown operations and exits with the given exit code.
func Lock ¶
func Lock() bool
Lock will signal that you have a function running, that you do not want to be interrupted by a shutdown.
If the function returns false shutdown has already been initiated, and you did not get a lock. You should therefore not call Unlock.
If the function returned true, you must call Unlock() once to release the lock.
You should not hold a lock when you start a shutdown.
Example ¶
Note that the same effect of this example can also be achieved using the WrapHandlerFunc helper.
http.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) { // Get a lock while we have the lock, the server will not shut down. if Lock() { defer Unlock() } else { // We are currently shutting down, return http.StatusServiceUnavailable w.WriteHeader(http.StatusServiceUnavailable) return } // ... }) http.ListenAndServe(":8080", nil)
Output:
func OnSignal ¶
OnSignal will start the shutdown when any of the given signals arrive
A good shutdown default is
shutdown.OnSignal(0, os.Interrupt, syscall.SIGTERM)
which will do shutdown on Ctrl+C and when the program is terminated.
func SetTimeout ¶
SetTimeout sets maximum delay to wait for each stage to finish. When the timeout has expired for a stage the next stage will be initiated.
func SetTimeoutN ¶
SetTimeoutN set maximum delay to wait for a specific stage to finish. When the timeout expired for a stage the next stage will be initiated. The stage can be obtained by using the exported variables called 'Stage1, etc.
Example ¶
Change timeout for a single stage
// Set timout for all stages SetTimeout(time.Second) // But give second stage more time SetTimeoutN(Stage2, time.Second*10)
Output:
func Shutdown ¶
func Shutdown()
Shutdown will signal all notifiers in three stages. It will first check that all locks have been released - see Lock()
func Started ¶
func Started() bool
Started returns true if shutdown has been started. Note that shutdown can have been started before you check the value.
func Unlock ¶
func Unlock()
Unlock will release a shutdown lock. This may only be called if you have previously called Lock and it has returned true
func Wait ¶
func Wait()
Wait will wait until shutdown has finished. This can be used to keep a main function from exiting until shutdown has been called, either by a goroutine or a signal.
Example ¶
This is an example, that could be your main function.
We wait for jobs to finish in another goroutine, from where we initialize the shutdown.
This is of course not a real-world problem, but there are many cases where you would want to initialize shutdown from other places than your main function, and where you would still like it to be able to do some final cleanup.
x := make([]struct{}, 10) var wg sync.WaitGroup wg.Add(len(x)) for i := range x { go func(i int) { time.Sleep(time.Millisecond * time.Duration(i)) wg.Done() }(i) } // ignore this reset, for test purposes only reset() // Wait for the jobs above to finish go func() { wg.Wait() fmt.Println("jobs done") Shutdown() }() // Since this is main, we wait for a shutdown to occur before // exiting. Wait() fmt.Println("exiting main") // Note than the output will always be in this order.
Output: jobs done exiting main
func WrapHandler ¶
WrapHandler will return an http Handler That will lock shutdown until all have completed and will return http.StatusServiceUnavailable if shutdown has been initiated.
Example ¶
This example creates a fileserver and wraps the handler, so all request will finish before shutdown is started.
If requests take too long to finish the shutdown will proceed and clients will be disconnected when the server shuts down. To modify the timeout use SetTimeoutN(Preshutdown, duration)
// Set a custom timeout, if the 5 second default doesn't fit your needs. SetTimeoutN(Preshutdown, time.Second*30) // Catch OS signals OnSignal(0, os.Interrupt, syscall.SIGTERM) // Create a fileserver handler fh := http.FileServer(http.Dir("/examples")) // Wrap the handler function http.Handle("/", WrapHandler(fh)) // Start the server http.ListenAndServe(":8080", nil)
Output:
func WrapHandlerFunc ¶
func WrapHandlerFunc(h http.HandlerFunc) http.HandlerFunc
WrapHandlerFunc will return an http.HandlerFunc that will lock shutdown until all have completed. The handler will return http.StatusServiceUnavailable if shutdown has been initiated.
Example ¶
This example creates a custom function handler and wraps the handler, so all request will finish before shutdown is started.
If requests take too long to finish (see the shutdown will proceed and clients will be disconnected when the server shuts down. To modify the timeout use SetTimeoutN(Preshutdown, duration)
// Set a custom timeout, if the 5 second default doesn't fit your needs. SetTimeoutN(Preshutdown, time.Second*30) // Catch OS signals OnSignal(0, os.Interrupt, syscall.SIGTERM) // Example handler function fn := func(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, "Hello, %q", html.EscapeString(r.URL.Path)) } // Wrap the handler function http.HandleFunc("/", WrapHandlerFunc(fn)) // Start the server http.ListenAndServe(":8080", nil)
Output:
Types ¶
type Notifier ¶
type Notifier chan chan struct{}
Notifier is a channel, that will be sent a channel once the application shuts down. When you have performed your shutdown actions close the channel you are given.
Example ¶
Get a notifier and perform our own code when we shutdown
shutdown := First() select { case n := <-shutdown: // Do shutdown code ... // Signal we are done close(n) }
Output:
func First ¶
func First() Notifier
First returns a notifier that will be called in the first stage of shutdowns
func FirstFunc ¶
func FirstFunc(fn ShutdownFn, v interface{}) Notifier
FirstFunc executes a function in the first stage of the shutdown
func PreShutdown ¶
func PreShutdown() Notifier
PreShutdown will return a Notifier that will be fired as soon as the shutdown is signalled, before locks are released. This allows to for instance send signals to upstream servers not to send more requests.
func PreShutdownFunc ¶
func PreShutdownFunc(fn ShutdownFn, v interface{}) Notifier
PreShutdownFunc registers a function that will be called as soon as the shutdown is signalled, before locks are released. This allows to for instance send signals to upstream servers not to send more requests.
func Second ¶
func Second() Notifier
Second returns a notifier that will be called in the second stage of shutdowns
func SecondFunc ¶
func SecondFunc(fn ShutdownFn, v interface{}) Notifier
SecondFunc executes a function in the second stage of the shutdown
func Third ¶
func Third() Notifier
Third returns a notifier that will be called in the third stage of shutdowns
func ThirdFunc ¶
func ThirdFunc(fn ShutdownFn, v interface{}) Notifier
ThirdFunc executes a function in the third stage of the shutdown The returned Notifier is only really useful for cancelling the shutdown function
type ShutdownFn ¶
type ShutdownFn func(interface{})
Example ¶
Get a notifier and perform our own function when we shutdown
_ = FirstFunc(func(i interface{}) { // This function is called on shutdown fmt.Println(i.(string)) }, "Example parameter") // Will print the parameter when Shutdown() is called
Output: