github.com/shrimpyuk/bor@v0.2.15-0.20220224151350-fb4ec6020bae/internal/cli/server/command.go (about)

     1  package server
     2  
     3  import (
     4  	"fmt"
     5  	"os"
     6  	"os/signal"
     7  	"syscall"
     8  
     9  	"github.com/ethereum/go-ethereum/log"
    10  	"github.com/mitchellh/cli"
    11  )
    12  
    13  // Command is the command to start the sever
    14  type Command struct {
    15  	UI cli.Ui
    16  
    17  	// cli configuration
    18  	cliConfig *Config
    19  
    20  	// final configuration
    21  	config *Config
    22  
    23  	configFile []string
    24  
    25  	srv *Server
    26  }
    27  
    28  // Help implements the cli.Command interface
    29  func (c *Command) Help() string {
    30  	return `Usage: bor [options]
    31    
    32  	Run the Bor server.
    33    ` + c.Flags().Help()
    34  }
    35  
    36  // Synopsis implements the cli.Command interface
    37  func (c *Command) Synopsis() string {
    38  	return "Run the Bor server"
    39  }
    40  
    41  // Run implements the cli.Command interface
    42  func (c *Command) Run(args []string) int {
    43  	flags := c.Flags()
    44  	if err := flags.Parse(args); err != nil {
    45  		c.UI.Error(err.Error())
    46  		return 1
    47  	}
    48  
    49  	// read config file
    50  	config := DefaultConfig()
    51  	for _, configFile := range c.configFile {
    52  		cfg, err := readConfigFile(configFile)
    53  		if err != nil {
    54  			c.UI.Error(err.Error())
    55  			return 1
    56  		}
    57  		if err := config.Merge(cfg); err != nil {
    58  			c.UI.Error(err.Error())
    59  			return 1
    60  		}
    61  	}
    62  	if err := config.Merge(c.cliConfig); err != nil {
    63  		c.UI.Error(err.Error())
    64  		return 1
    65  	}
    66  	c.config = config
    67  
    68  	srv, err := NewServer(config)
    69  	if err != nil {
    70  		c.UI.Error(err.Error())
    71  		return 1
    72  	}
    73  	c.srv = srv
    74  
    75  	return c.handleSignals()
    76  }
    77  
    78  func (c *Command) handleSignals() int {
    79  	signalCh := make(chan os.Signal, 4)
    80  	signal.Notify(signalCh, os.Interrupt, syscall.SIGTERM, syscall.SIGHUP)
    81  
    82  	sig := <-signalCh
    83  
    84  	c.UI.Output(fmt.Sprintf("Caught signal: %v", sig))
    85  	c.UI.Output("Gracefully shutting down agent...")
    86  
    87  	gracefulCh := make(chan struct{})
    88  	go func() {
    89  		c.srv.Stop()
    90  		close(gracefulCh)
    91  	}()
    92  
    93  	for i := 10; i > 0; i-- {
    94  		select {
    95  		case <-signalCh:
    96  			log.Warn("Already shutting down, interrupt more force stop.", "times", i-1)
    97  		case <-gracefulCh:
    98  			return 0
    99  		}
   100  	}
   101  	return 1
   102  }