github.com/adoriasoft/tendermint@v0.34.0-dev1.0.20200722151356-96d84601a75a/proxy/multi_app_conn.go (about)

     1  package proxy
     2  
     3  import (
     4  	"fmt"
     5  
     6  	abcicli "github.com/tendermint/tendermint/abci/client"
     7  	tmlog "github.com/tendermint/tendermint/libs/log"
     8  	tmos "github.com/tendermint/tendermint/libs/os"
     9  	"github.com/tendermint/tendermint/libs/service"
    10  )
    11  
    12  const (
    13  	connConsensus = "consensus"
    14  	connMempool   = "mempool"
    15  	connQuery     = "query"
    16  	connSnapshot  = "snapshot"
    17  )
    18  
    19  // AppConns is the Tendermint's interface to the application that consists of
    20  // multiple connections.
    21  type AppConns interface {
    22  	service.Service
    23  
    24  	// Mempool connection
    25  	Mempool() AppConnMempool
    26  	// Consensus connection
    27  	Consensus() AppConnConsensus
    28  	// Query connection
    29  	Query() AppConnQuery
    30  	// Snapshot connection
    31  	Snapshot() AppConnSnapshot
    32  }
    33  
    34  // NewAppConns calls NewMultiAppConn.
    35  func NewAppConns(clientCreator ClientCreator) AppConns {
    36  	return NewMultiAppConn(clientCreator)
    37  }
    38  
    39  // multiAppConn implements AppConns.
    40  //
    41  // A multiAppConn is made of a few appConns and manages their underlying abci
    42  // clients.
    43  // TODO: on app restart, clients must reboot together
    44  type multiAppConn struct {
    45  	service.BaseService
    46  
    47  	consensusConn AppConnConsensus
    48  	mempoolConn   AppConnMempool
    49  	queryConn     AppConnQuery
    50  	snapshotConn  AppConnSnapshot
    51  
    52  	consensusConnClient abcicli.Client
    53  	mempoolConnClient   abcicli.Client
    54  	queryConnClient     abcicli.Client
    55  	snapshotConnClient  abcicli.Client
    56  
    57  	clientCreator ClientCreator
    58  }
    59  
    60  // NewMultiAppConn makes all necessary abci connections to the application.
    61  func NewMultiAppConn(clientCreator ClientCreator) AppConns {
    62  	multiAppConn := &multiAppConn{
    63  		clientCreator: clientCreator,
    64  	}
    65  	multiAppConn.BaseService = *service.NewBaseService(nil, "multiAppConn", multiAppConn)
    66  	return multiAppConn
    67  }
    68  
    69  func (app *multiAppConn) Mempool() AppConnMempool {
    70  	return app.mempoolConn
    71  }
    72  
    73  func (app *multiAppConn) Consensus() AppConnConsensus {
    74  	return app.consensusConn
    75  }
    76  
    77  func (app *multiAppConn) Query() AppConnQuery {
    78  	return app.queryConn
    79  }
    80  
    81  func (app *multiAppConn) Snapshot() AppConnSnapshot {
    82  	return app.snapshotConn
    83  }
    84  
    85  func (app *multiAppConn) OnStart() error {
    86  	c, err := app.abciClientFor(connQuery)
    87  	if err != nil {
    88  		return err
    89  	}
    90  	app.queryConnClient = c
    91  	app.queryConn = NewAppConnQuery(c)
    92  
    93  	c, err = app.abciClientFor(connSnapshot)
    94  	if err != nil {
    95  		app.stopAllClients()
    96  		return err
    97  	}
    98  	app.snapshotConnClient = c
    99  	app.snapshotConn = NewAppConnSnapshot(c)
   100  
   101  	c, err = app.abciClientFor(connMempool)
   102  	if err != nil {
   103  		app.stopAllClients()
   104  		return err
   105  	}
   106  	app.mempoolConnClient = c
   107  	app.mempoolConn = NewAppConnMempool(c)
   108  
   109  	c, err = app.abciClientFor(connConsensus)
   110  	if err != nil {
   111  		app.stopAllClients()
   112  		return err
   113  	}
   114  	app.consensusConnClient = c
   115  	app.consensusConn = NewAppConnConsensus(c)
   116  
   117  	// Kill Tendermint if the ABCI application crashes.
   118  	go app.killTMOnClientError()
   119  
   120  	return nil
   121  }
   122  
   123  func (app *multiAppConn) OnStop() {
   124  	app.stopAllClients()
   125  }
   126  
   127  func (app *multiAppConn) killTMOnClientError() {
   128  	killFn := func(conn string, err error, logger tmlog.Logger) {
   129  		logger.Error(
   130  			fmt.Sprintf("%s connection terminated. Did the application crash? Please restart tendermint", conn),
   131  			"err", err)
   132  		killErr := tmos.Kill()
   133  		if killErr != nil {
   134  			logger.Error("Failed to kill this process - please do so manually", "err", killErr)
   135  		}
   136  	}
   137  
   138  	select {
   139  	case <-app.consensusConnClient.Quit():
   140  		if err := app.consensusConnClient.Error(); err != nil {
   141  			killFn(connConsensus, err, app.Logger)
   142  		}
   143  	case <-app.mempoolConnClient.Quit():
   144  		if err := app.mempoolConnClient.Error(); err != nil {
   145  			killFn(connMempool, err, app.Logger)
   146  		}
   147  	case <-app.queryConnClient.Quit():
   148  		if err := app.queryConnClient.Error(); err != nil {
   149  			killFn(connQuery, err, app.Logger)
   150  		}
   151  	case <-app.snapshotConnClient.Quit():
   152  		if err := app.snapshotConnClient.Error(); err != nil {
   153  			killFn(connSnapshot, err, app.Logger)
   154  		}
   155  	}
   156  }
   157  
   158  func (app *multiAppConn) stopAllClients() {
   159  	if app.consensusConnClient != nil {
   160  		app.consensusConnClient.Stop()
   161  	}
   162  	if app.mempoolConnClient != nil {
   163  		app.mempoolConnClient.Stop()
   164  	}
   165  	if app.queryConnClient != nil {
   166  		app.queryConnClient.Stop()
   167  	}
   168  	if app.snapshotConnClient != nil {
   169  		app.snapshotConnClient.Stop()
   170  	}
   171  }
   172  
   173  func (app *multiAppConn) abciClientFor(conn string) (abcicli.Client, error) {
   174  	c, err := app.clientCreator.NewABCIClient()
   175  	if err != nil {
   176  		return nil, fmt.Errorf("error creating ABCI client (%s connection): %w", conn, err)
   177  	}
   178  	c.SetLogger(app.Logger.With("module", "abci-client", "connection", conn))
   179  	if err := c.Start(); err != nil {
   180  		return nil, fmt.Errorf("error starting ABCI client (%s connection): %w", conn, err)
   181  	}
   182  	return c, nil
   183  }