57 lines
		
	
	
		
			1.3 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			57 lines
		
	
	
		
			1.3 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
package node
 | 
						|
 | 
						|
import (
 | 
						|
	"context"
 | 
						|
	"os"
 | 
						|
	"os/signal"
 | 
						|
	"syscall"
 | 
						|
)
 | 
						|
 | 
						|
type ShutdownHandler struct {
 | 
						|
	Component string
 | 
						|
	StopFunc  StopFunc
 | 
						|
}
 | 
						|
 | 
						|
// MonitorShutdown manages shutdown requests, by watching signals and invoking
 | 
						|
// the supplied handlers in order.
 | 
						|
//
 | 
						|
// It watches SIGTERM and SIGINT OS signals, as well as the trigger channel.
 | 
						|
// When any of them fire, it calls the supplied handlers in order. If any of
 | 
						|
// them errors, it merely logs the error.
 | 
						|
//
 | 
						|
// Once the shutdown has completed, it closes the returned channel. The caller
 | 
						|
// can watch this channel
 | 
						|
func MonitorShutdown(triggerCh <-chan struct{}, handlers ...ShutdownHandler) <-chan struct{} {
 | 
						|
	sigCh := make(chan os.Signal, 2)
 | 
						|
	out := make(chan struct{})
 | 
						|
 | 
						|
	go func() {
 | 
						|
		select {
 | 
						|
		case sig := <-sigCh:
 | 
						|
			log.Warnw("received shutdown", "signal", sig)
 | 
						|
		case <-triggerCh:
 | 
						|
			log.Warn("received shutdown")
 | 
						|
		}
 | 
						|
 | 
						|
		log.Warn("Shutting down...")
 | 
						|
 | 
						|
		// Call all the handlers, logging on failure and success.
 | 
						|
		for _, h := range handlers {
 | 
						|
			if err := h.StopFunc(context.TODO()); err != nil {
 | 
						|
				log.Errorf("shutting down %s failed: %s", h.Component, err)
 | 
						|
				continue
 | 
						|
			}
 | 
						|
			log.Infof("%s shut down successfully ", h.Component)
 | 
						|
		}
 | 
						|
 | 
						|
		log.Warn("Graceful shutdown successful")
 | 
						|
 | 
						|
		// Sync all loggers.
 | 
						|
		_ = log.Sync() //nolint:errcheck
 | 
						|
		close(out)
 | 
						|
	}()
 | 
						|
 | 
						|
	signal.Notify(sigCh, syscall.SIGTERM, syscall.SIGINT)
 | 
						|
	return out
 | 
						|
}
 |