code.vegaprotocol.io/vega@v0.79.0/cmd/blockexplorer/commands/start.go (about)

     1  // Copyright (C) 2023 Gobalsky Labs Limited
     2  //
     3  // This program is free software: you can redistribute it and/or modify
     4  // it under the terms of the GNU Affero General Public License as
     5  // published by the Free Software Foundation, either version 3 of the
     6  // License, or (at your option) any later version.
     7  //
     8  // This program is distributed in the hope that it will be useful,
     9  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    10  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    11  // GNU Affero General Public License for more details.
    12  //
    13  // You should have received a copy of the GNU Affero General Public License
    14  // along with this program.  If not, see <http://www.gnu.org/licenses/>.
    15  
    16  package commands
    17  
    18  import (
    19  	"context"
    20  	"fmt"
    21  	"os"
    22  	"os/signal"
    23  	"syscall"
    24  
    25  	"code.vegaprotocol.io/vega/blockexplorer"
    26  	"code.vegaprotocol.io/vega/blockexplorer/config"
    27  	"code.vegaprotocol.io/vega/blockexplorer/store"
    28  	"code.vegaprotocol.io/vega/logging"
    29  
    30  	"github.com/jessevdk/go-flags"
    31  	"go.uber.org/zap"
    32  )
    33  
    34  type Start struct {
    35  	config.VegaHomeFlag
    36  	config.Config
    37  }
    38  
    39  func (opts *Start) Execute(_ []string) error {
    40  	logger := logging.NewLoggerFromConfig(logging.NewDefaultConfig())
    41  	defer logger.AtExit()
    42  
    43  	cfg, err := loadConfig(logger, opts.VegaHome)
    44  	if err != nil {
    45  		return err
    46  	}
    47  
    48  	be := blockexplorer.NewFromConfig(*cfg)
    49  
    50  	// Used to retrieve the error from the block explorer in the main thread.
    51  	errCh := make(chan error, 1)
    52  	defer close(errCh)
    53  
    54  	// Use to shutdown the block explorer.
    55  	beCtx, stopBlockExplorer := context.WithCancel(context.Background())
    56  
    57  	// make sure the database has been migrated to the latest version
    58  	err = store.MigrateToLatestSchema(logger, cfg.Store)
    59  	if err != nil {
    60  		return fmt.Errorf("creating db schema: %w", err)
    61  	}
    62  
    63  	blockExplorerStopped := make(chan any)
    64  	go func() {
    65  		if err := be.Run(beCtx); err != nil {
    66  			errCh <- err
    67  		}
    68  		close(blockExplorerStopped)
    69  	}()
    70  
    71  	err = waitUntilInterruption(logger, errCh)
    72  
    73  	stopBlockExplorer()
    74  	<-blockExplorerStopped
    75  
    76  	return err
    77  }
    78  
    79  func Run(_ context.Context, parser *flags.Parser) error {
    80  	runCmd := Start{}
    81  
    82  	short := "Start block explorer backend"
    83  	long := "Start the various API grpc/rest APIs to query the tendermint postgres transaction index"
    84  
    85  	_, err := parser.AddCommand("start", short, long, &runCmd)
    86  	return err
    87  }
    88  
    89  // waitUntilInterruption will wait for a sigterm or sigint interrupt.
    90  func waitUntilInterruption(logger *logging.Logger, errChan <-chan error) error {
    91  	gracefulStop := make(chan os.Signal, 1)
    92  	defer func() {
    93  		signal.Stop(gracefulStop)
    94  		close(gracefulStop)
    95  	}()
    96  
    97  	signal.Notify(gracefulStop, syscall.SIGTERM, syscall.SIGINT, syscall.SIGQUIT)
    98  
    99  	select {
   100  	case sig := <-gracefulStop:
   101  		logger.Info("OS signal received", zap.String("signal", fmt.Sprintf("%+v", sig)))
   102  		return nil
   103  	case err := <-errChan:
   104  		logger.Error("Initiating shutdown due to an internal error reported by the block explorer", zap.Error(err))
   105  		return err
   106  	}
   107  }