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 }