From c7c4c0cab3229a869acccaf42b547d867392068b Mon Sep 17 00:00:00 2001 From: Federico Kunze Date: Mon, 21 Dec 2020 11:07:24 -0300 Subject: [PATCH 1/8] api, config: modular server --- server/api/server.go | 9 +++++++++ server/config/config.go | 8 ++++++++ 2 files changed, 17 insertions(+) diff --git a/server/api/server.go b/server/api/server.go index c2987f860d1a..ec9f33c34d41 100644 --- a/server/api/server.go +++ b/server/api/server.go @@ -24,6 +24,15 @@ import ( _ "github.com/cosmos/cosmos-sdk/client/docs/statik" ) +type CosmosServer interface { + Ctx() client.Context + GetRouter() *mux.Router + GetGRPCGatewayRouter() *runtime.ServeMux + + Start(config.ServerConfig) error + Stop() error +} + // Server defines the server's API interface. type Server struct { Router *mux.Router diff --git a/server/config/config.go b/server/config/config.go index 80e79f04558d..999969f7b648 100644 --- a/server/config/config.go +++ b/server/config/config.go @@ -18,6 +18,14 @@ const ( DefaultGRPCAddress = "0.0.0.0:9090" ) +type ServerConfig interface { + GetBaseConfig() BaseConfig + GetAPIConfig() APIConfig + GetGRPCConfig() GRPCConfig + GetTelemetryConfig() telemetry.Config + GetStateSyncConfig() StateSyncConfig +} + // BaseConfig defines the server's basic configuration type BaseConfig struct { // The minimum gas prices a validator is willing to accept for processing a From 15d36d31530ca1d1b78155625d8743b4ebd13fc4 Mon Sep 17 00:00:00 2001 From: Federico Kunze Date: Mon, 21 Dec 2020 11:09:10 -0300 Subject: [PATCH 2/8] api, config: modular server --- server/api/server.go | 2 +- server/config/config.go | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/server/api/server.go b/server/api/server.go index ec9f33c34d41..15863a578b2a 100644 --- a/server/api/server.go +++ b/server/api/server.go @@ -24,7 +24,7 @@ import ( _ "github.com/cosmos/cosmos-sdk/client/docs/statik" ) -type CosmosServer interface { +type SDKServer interface { Ctx() client.Context GetRouter() *mux.Router GetGRPCGatewayRouter() *runtime.ServeMux diff --git a/server/config/config.go b/server/config/config.go index 999969f7b648..2265b94f0061 100644 --- a/server/config/config.go +++ b/server/config/config.go @@ -126,6 +126,8 @@ type StateSyncConfig struct { SnapshotKeepRecent uint32 `mapstructure:"snapshot-keep-recent"` } +var _ ServerConfig = &Config{} + // Config defines the server's top level configuration type Config struct { BaseConfig `mapstructure:",squash"` @@ -137,6 +139,11 @@ type Config struct { StateSync StateSyncConfig `mapstructure:"state-sync"` } +// SetMinGasPrices sets the validator's minimum gas prices. +func (c *Config) GetBaseConfig() { + +} + // SetMinGasPrices sets the validator's minimum gas prices. func (c *Config) SetMinGasPrices(gasPrices sdk.DecCoins) { c.MinGasPrices = gasPrices.String() From cca1c3d9e021497e5eed8654f1dd20a02958d06f Mon Sep 17 00:00:00 2001 From: Federico Kunze Date: Mon, 21 Dec 2020 12:43:21 -0300 Subject: [PATCH 3/8] refactor server --- server/api/server.go | 36 +++++++++++++++++++++++++----------- server/config/config.go | 31 +++++++++++++++++++------------ server/config/config_test.go | 4 ++-- server/config/toml.go | 15 +++++++++------ server/start.go | 5 +++-- server/types/app.go | 4 ++++ simapp/app.go | 9 +++++++-- simapp/simd/cmd/testnet.go | 3 ++- 8 files changed, 71 insertions(+), 36 deletions(-) diff --git a/server/api/server.go b/server/api/server.go index 15863a578b2a..979c514c718c 100644 --- a/server/api/server.go +++ b/server/api/server.go @@ -30,9 +30,11 @@ type SDKServer interface { GetGRPCGatewayRouter() *runtime.ServeMux Start(config.ServerConfig) error - Stop() error + Close() error } +var _ SDKServer = &Server{} + // Server defines the server's API interface. type Server struct { Router *mux.Router @@ -58,7 +60,8 @@ func CustomGRPCHeaderMatcher(key string) (string, bool) { } } -func New(clientCtx client.Context, logger log.Logger) *Server { +// New creates the default SDK server instance. +func New(clientCtx client.Context, logger log.Logger) SDKServer { // The default JSON marshaller used by the gRPC-Gateway is unable to marshal non-nullable non-scalar fields. // Using the gogo/gateway package with the gRPC-Gateway WithMarshaler option fixes the scalar field marshalling issue. marshalerOption := &gateway.JSONPb{ @@ -87,13 +90,24 @@ func New(clientCtx client.Context, logger log.Logger) *Server { } } +// Ctx implements the SDKServer interface. +func (s Server) Ctx() client.Context { return s.ClientCtx } + +// GetRouter implements the SDKServer interface. +func (s Server) GetRouter() *mux.Router { return s.Router } + +// GetGRPCGatewayRouter implements the SDKServer interface. +func (s Server) GetGRPCGatewayRouter() *runtime.ServeMux { return s.GRPCGatewayRouter } + // Start starts the API server. Internally, the API server leverages Tendermint's // JSON RPC server. Configuration options are provided via config.APIConfig // and are delegated to the Tendermint JSON RPC server. The process is // non-blocking, so an external signal handler must be used. -func (s *Server) Start(cfg config.Config) error { - if cfg.Telemetry.Enabled { - m, err := telemetry.New(cfg.Telemetry) +func (s *Server) Start(cfg config.ServerConfig) error { + sdkCfg := cfg.GetSDKConfig() + + if sdkCfg.Telemetry.Enabled { + m, err := telemetry.New(sdkCfg.Telemetry) if err != nil { return err } @@ -103,12 +117,12 @@ func (s *Server) Start(cfg config.Config) error { } tmCfg := tmrpcserver.DefaultConfig() - tmCfg.MaxOpenConnections = int(cfg.API.MaxOpenConnections) - tmCfg.ReadTimeout = time.Duration(cfg.API.RPCReadTimeout) * time.Second - tmCfg.WriteTimeout = time.Duration(cfg.API.RPCWriteTimeout) * time.Second - tmCfg.MaxBodyBytes = int64(cfg.API.RPCMaxBodyBytes) + tmCfg.MaxOpenConnections = int(sdkCfg.API.MaxOpenConnections) + tmCfg.ReadTimeout = time.Duration(sdkCfg.API.RPCReadTimeout) * time.Second + tmCfg.WriteTimeout = time.Duration(sdkCfg.API.RPCWriteTimeout) * time.Second + tmCfg.MaxBodyBytes = int64(sdkCfg.API.RPCMaxBodyBytes) - listener, err := tmrpcserver.Listen(cfg.API.Address, tmCfg) + listener, err := tmrpcserver.Listen(sdkCfg.API.Address, tmCfg) if err != nil { return err } @@ -118,7 +132,7 @@ func (s *Server) Start(cfg config.Config) error { s.listener = listener var h http.Handler = s.Router - if cfg.API.EnableUnsafeCORS { + if sdkCfg.API.EnableUnsafeCORS { allowAllCORS := handlers.CORS(handlers.AllowedHeaders([]string{"Content-Type"})) return tmrpcserver.Serve(s.listener, allowAllCORS(h), s.logger, tmCfg) } diff --git a/server/config/config.go b/server/config/config.go index 2265b94f0061..4939c34fd7e6 100644 --- a/server/config/config.go +++ b/server/config/config.go @@ -19,11 +19,7 @@ const ( ) type ServerConfig interface { - GetBaseConfig() BaseConfig - GetAPIConfig() APIConfig - GetGRPCConfig() GRPCConfig - GetTelemetryConfig() telemetry.Config - GetStateSyncConfig() StateSyncConfig + GetSDKConfig() *Config } // BaseConfig defines the server's basic configuration @@ -139,9 +135,9 @@ type Config struct { StateSync StateSyncConfig `mapstructure:"state-sync"` } -// SetMinGasPrices sets the validator's minimum gas prices. -func (c *Config) GetBaseConfig() { - +// GetSDKConfig implements the ServerConfig interface. +func (c *Config) GetSDKConfig() *Config { + return c } // SetMinGasPrices sets the validator's minimum gas prices. @@ -172,7 +168,7 @@ func (c *Config) GetMinGasPrices() sdk.DecCoins { } // DefaultConfig returns server's default configuration. -func DefaultConfig() *Config { +func DefaultConfig() ServerConfig { return &Config{ BaseConfig: BaseConfig{ MinGasPrices: defaultMinGasPrices, @@ -207,8 +203,17 @@ func DefaultConfig() *Config { } } -// GetConfig returns a fully parsed Config object. -func GetConfig(v *viper.Viper) Config { +// Generator creates a general purpose server configuration +type Generator func(cfg *Config) ServerConfig + +// DefaultGenerator is the default generator for a configuration file that +// is passed to the served during its start. +func DefaultGenerator(cfg *Config) ServerConfig { + return cfg +} + +// GetConfig returns a fully parsed ServerConfig object. +func GetConfig(v *viper.Viper, cfgGen Generator) ServerConfig { globalLabelsRaw := v.Get("telemetry.global-labels").([]interface{}) globalLabels := make([][]string, 0, len(globalLabelsRaw)) for _, glr := range globalLabelsRaw { @@ -218,7 +223,7 @@ func GetConfig(v *viper.Viper) Config { } } - return Config{ + cfg := &Config{ BaseConfig: BaseConfig{ MinGasPrices: v.GetString("minimum-gas-prices"), InterBlockCache: v.GetBool("inter-block-cache"), @@ -259,4 +264,6 @@ func GetConfig(v *viper.Viper) Config { SnapshotKeepRecent: v.GetUint32("state-sync.snapshot-keep-recent"), }, } + + return cfgGen(cfg) } diff --git a/server/config/config_test.go b/server/config/config_test.go index e828a0716dc8..e5f7cc002dbf 100644 --- a/server/config/config_test.go +++ b/server/config/config_test.go @@ -9,12 +9,12 @@ import ( ) func TestDefaultConfig(t *testing.T) { - cfg := DefaultConfig() + cfg := DefaultConfig().GetSDKConfig() require.True(t, cfg.GetMinGasPrices().IsZero()) } func TestSetMinimumFees(t *testing.T) { - cfg := DefaultConfig() + cfg := DefaultConfig().GetSDKConfig() cfg.SetMinGasPrices(sdk.DecCoins{sdk.NewInt64DecCoin("foo", 5)}) require.Equal(t, "5.000000000000000000foo", cfg.MinGasPrices) } diff --git a/server/config/toml.go b/server/config/toml.go index b042da74293d..2e7814530ee7 100644 --- a/server/config/toml.go +++ b/server/config/toml.go @@ -8,7 +8,9 @@ import ( tmos "github.com/tendermint/tendermint/libs/os" ) -const defaultConfigTemplate = `# This is a TOML config file. +// DefaultConfigTemplate defines the standard config template for the application. +// It can be extended to allow for custom configurations. +var DefaultConfigTemplate = `# This is a TOML config file. # For more information, see https://github.com/toml-lang/toml ############################################################################### @@ -163,21 +165,22 @@ snapshot-interval = {{ .StateSync.SnapshotInterval }} snapshot-keep-recent = {{ .StateSync.SnapshotKeepRecent }} ` -var configTemplate *template.Template +// ConfigTemplate is the template variable for the configuration toml file. +var ConfigTemplate *template.Template func init() { var err error tmpl := template.New("appConfigFileTemplate") - if configTemplate, err = tmpl.Parse(defaultConfigTemplate); err != nil { + if ConfigTemplate, err = tmpl.Parse(DefaultConfigTemplate); err != nil { panic(err) } } // ParseConfig retrieves the default environment configuration for the // application. -func ParseConfig(v *viper.Viper) (*Config, error) { +func ParseConfig(v *viper.Viper) (ServerConfig, error) { conf := DefaultConfig() err := v.Unmarshal(conf) @@ -186,10 +189,10 @@ func ParseConfig(v *viper.Viper) (*Config, error) { // WriteConfigFile renders config using the template and writes it to // configFilePath. -func WriteConfigFile(configFilePath string, config *Config) { +func WriteConfigFile(configFilePath string, config ServerConfig) { var buffer bytes.Buffer - if err := configTemplate.Execute(&buffer, config); err != nil { + if err := ConfigTemplate.Execute(&buffer, config); err != nil { panic(err) } diff --git a/server/start.go b/server/start.go index 2cb165eb4fb0..d671e5dea8b0 100644 --- a/server/start.go +++ b/server/start.go @@ -261,7 +261,8 @@ func startInProcess(ctx *Context, clientCtx client.Context, appCreator types.App } ctx.Logger.Debug("initialization: tmNode started") - config := config.GetConfig(ctx.Viper) + // TODO: pass in custom generator + config := config.GetConfig(ctx.Viper, config.DefaultGenerator) // Add the tx service to the gRPC router. We only need to register this // service if API or gRPC is enabled, and avoid doing so in the general @@ -273,7 +274,7 @@ func startInProcess(ctx *Context, clientCtx client.Context, appCreator types.App app.RegisterTendermintService(clientCtx) } - var apiSrv *api.Server + var apiSrv api.SDKServer if config.API.Enable { genDoc, err := genDocProvider() diff --git a/server/types/app.go b/server/types/app.go index bac708729488..43e116403af1 100644 --- a/server/types/app.go +++ b/server/types/app.go @@ -36,6 +36,10 @@ type ( RegisterAPIRoutes(*api.Server, config.APIConfig) + // RegisterExternalServices is optional function to retegister custom services + // to the server that are not defined by the default SDK configuration. + RegisterExternalServices(api.SDKServer, config.ServerConfig) + // RegisterGRPCServer registers gRPC services directly with the gRPC // server. RegisterGRPCServer(grpc.Server) diff --git a/simapp/app.go b/simapp/app.go index 02aaa2297fe8..b7edaa03880e 100644 --- a/simapp/app.go +++ b/simapp/app.go @@ -570,10 +570,15 @@ func (app *SimApp) RegisterAPIRoutes(apiSvr *api.Server, apiConfig config.APICon // register swagger API from root so that other applications can override easily if apiConfig.Swagger { - RegisterSwaggerAPI(clientCtx, apiSvr.Router) + RegisterSwaggerAPI(apiSvr.Router) } } +// RegisterExternalServices implements the Application.RegisterExternalServices method. +// It performs a no-operation as SimApp doesn't expose extra services other than the +// default ones provided by the SDK. +func (app *SimApp) RegisterExternalServices(_ api.SDKServer, _ config.ServerConfig) {} + // RegisterTxService implements the Application.RegisterTxService method. func (app *SimApp) RegisterTxService(clientCtx client.Context) { authtx.RegisterTxService(app.BaseApp.GRPCQueryRouter(), clientCtx, app.BaseApp.Simulate, app.interfaceRegistry) @@ -585,7 +590,7 @@ func (app *SimApp) RegisterTendermintService(clientCtx client.Context) { } // RegisterSwaggerAPI registers swagger route with API Server -func RegisterSwaggerAPI(ctx client.Context, rtr *mux.Router) { +func RegisterSwaggerAPI(rtr *mux.Router) { statikFS, err := fs.New() if err != nil { panic(err) diff --git a/simapp/simd/cmd/testnet.go b/simapp/simd/cmd/testnet.go index 0717b398427c..114f1fb8b714 100644 --- a/simapp/simd/cmd/testnet.go +++ b/simapp/simd/cmd/testnet.go @@ -24,6 +24,7 @@ import ( "github.com/cosmos/cosmos-sdk/crypto/keyring" cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" "github.com/cosmos/cosmos-sdk/server" + "github.com/cosmos/cosmos-sdk/server/config" srvconfig "github.com/cosmos/cosmos-sdk/server/config" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/module" @@ -121,7 +122,7 @@ func InitTestnet( nodeIDs := make([]string, numValidators) valPubKeys := make([]cryptotypes.PubKey, numValidators) - simappConfig := srvconfig.DefaultConfig() + simappConfig, _ := srvconfig.DefaultConfig().(*config.Config) simappConfig.MinGasPrices = minGasPrices simappConfig.API.Enable = true simappConfig.Telemetry.Enabled = true From 52d355ec3918e542b3003da7ecb97e263f869881 Mon Sep 17 00:00:00 2001 From: Federico Kunze Date: Mon, 21 Dec 2020 13:14:38 -0300 Subject: [PATCH 4/8] split server logic --- server/api/server.go | 34 +++++++++++++--------------------- server/grpc/server.go | 2 +- server/start.go | 42 +++++++++++++++++++++++------------------- server/types/app.go | 8 ++++++-- simapp/app.go | 5 +++++ 5 files changed, 48 insertions(+), 43 deletions(-) diff --git a/server/api/server.go b/server/api/server.go index 979c514c718c..8b9322f0b830 100644 --- a/server/api/server.go +++ b/server/api/server.go @@ -24,19 +24,17 @@ import ( _ "github.com/cosmos/cosmos-sdk/client/docs/statik" ) -type SDKServer interface { - Ctx() client.Context - GetRouter() *mux.Router - GetGRPCGatewayRouter() *runtime.ServeMux +type Server interface { + Base() *BaseServer Start(config.ServerConfig) error Close() error } -var _ SDKServer = &Server{} +var _ Server = &BaseServer{} -// Server defines the server's API interface. -type Server struct { +// BaseServer defines the SDK server's API interface. +type BaseServer struct { Router *mux.Router GRPCGatewayRouter *runtime.ServeMux ClientCtx client.Context @@ -61,7 +59,7 @@ func CustomGRPCHeaderMatcher(key string) (string, bool) { } // New creates the default SDK server instance. -func New(clientCtx client.Context, logger log.Logger) SDKServer { +func New(clientCtx client.Context, logger log.Logger) Server { // The default JSON marshaller used by the gRPC-Gateway is unable to marshal non-nullable non-scalar fields. // Using the gogo/gateway package with the gRPC-Gateway WithMarshaler option fixes the scalar field marshalling issue. marshalerOption := &gateway.JSONPb{ @@ -71,7 +69,7 @@ func New(clientCtx client.Context, logger log.Logger) SDKServer { AnyResolver: clientCtx.InterfaceRegistry, } - return &Server{ + return &BaseServer{ Router: mux.NewRouter(), ClientCtx: clientCtx, logger: logger, @@ -90,20 +88,14 @@ func New(clientCtx client.Context, logger log.Logger) SDKServer { } } -// Ctx implements the SDKServer interface. -func (s Server) Ctx() client.Context { return s.ClientCtx } - -// GetRouter implements the SDKServer interface. -func (s Server) GetRouter() *mux.Router { return s.Router } - -// GetGRPCGatewayRouter implements the SDKServer interface. -func (s Server) GetGRPCGatewayRouter() *runtime.ServeMux { return s.GRPCGatewayRouter } +// Base implements the Server interface. +func (s *BaseServer) Base() *BaseServer { return s } // Start starts the API server. Internally, the API server leverages Tendermint's // JSON RPC server. Configuration options are provided via config.APIConfig // and are delegated to the Tendermint JSON RPC server. The process is // non-blocking, so an external signal handler must be used. -func (s *Server) Start(cfg config.ServerConfig) error { +func (s *BaseServer) Start(cfg config.ServerConfig) error { sdkCfg := cfg.GetSDKConfig() if sdkCfg.Telemetry.Enabled { @@ -142,15 +134,15 @@ func (s *Server) Start(cfg config.ServerConfig) error { } // Close closes the API server. -func (s *Server) Close() error { +func (s *BaseServer) Close() error { return s.listener.Close() } -func (s *Server) registerGRPCGatewayRoutes() { +func (s *BaseServer) registerGRPCGatewayRoutes() { s.Router.PathPrefix("/").Handler(s.GRPCGatewayRouter) } -func (s *Server) registerMetrics() { +func (s *BaseServer) registerMetrics() { metricsHandler := func(w http.ResponseWriter, r *http.Request) { format := strings.TrimSpace(r.FormValue("format")) diff --git a/server/grpc/server.go b/server/grpc/server.go index f03c1d87b9fd..2894508c1258 100644 --- a/server/grpc/server.go +++ b/server/grpc/server.go @@ -11,7 +11,7 @@ import ( "github.com/cosmos/cosmos-sdk/server/types" ) -// StartGRPCServer starts a gRPC server on the given address. +// StartGRPCServer creates, registers starts a gRPC server on the given address. func StartGRPCServer(app types.Application, address string) (*grpc.Server, error) { grpcSrv := grpc.NewServer() app.RegisterGRPCServer(grpcSrv) diff --git a/server/start.go b/server/start.go index d671e5dea8b0..9e381e4f56dd 100644 --- a/server/start.go +++ b/server/start.go @@ -261,37 +261,37 @@ func startInProcess(ctx *Context, clientCtx client.Context, appCreator types.App } ctx.Logger.Debug("initialization: tmNode started") - // TODO: pass in custom generator - config := config.GetConfig(ctx.Viper, config.DefaultGenerator) + config := config.GetConfig(ctx.Viper, app.ConfigGenerator()) + sdkCfg := config.GetSDKConfig() // Add the tx service to the gRPC router. We only need to register this // service if API or gRPC is enabled, and avoid doing so in the general // case, because it spawns a new local tendermint RPC client. - if config.API.Enable || config.GRPC.Enable { + if sdkCfg.API.Enable || sdkCfg.GRPC.Enable { clientCtx = clientCtx.WithClient(local.New(tmNode)) app.RegisterTxService(clientCtx) app.RegisterTendermintService(clientCtx) } - var apiSrv api.SDKServer + genDoc, err := genDocProvider() + if err != nil { + return err + } - if config.API.Enable { - genDoc, err := genDocProvider() - if err != nil { - return err - } + clientCtx = clientCtx. + WithHomeDir(home). + WithChainID(genDoc.ChainID) - clientCtx := clientCtx. - WithHomeDir(home). - WithChainID(genDoc.ChainID) + srv := api.New(clientCtx, ctx.Logger.With("module", "server")) - apiSrv = api.New(clientCtx, ctx.Logger.With("module", "api-server")) - app.RegisterAPIRoutes(apiSrv, config.API) + if sdkCfg.API.Enable { + // register routes and start server + app.RegisterAPIRoutes(srv.Base(), sdkCfg.API) errCh := make(chan error) go func() { - if err := apiSrv.Start(config); err != nil { + if err := srv.Start(sdkCfg); err != nil { errCh <- err } }() @@ -304,13 +304,17 @@ func startInProcess(ctx *Context, clientCtx client.Context, appCreator types.App } var grpcSrv *grpc.Server - if config.GRPC.Enable { - grpcSrv, err = servergrpc.StartGRPCServer(app, config.GRPC.Address) + if sdkCfg.GRPC.Enable { + // initialize, register and start gRPC server + grpcSrv, err = servergrpc.StartGRPCServer(app, sdkCfg.GRPC.Address) if err != nil { return err } } + // register services that are external to the default services provided by the SDK + app.RegisterExternalServices(srv, config) + defer func() { if tmNode.IsRunning() { _ = tmNode.Stop() @@ -320,8 +324,8 @@ func startInProcess(ctx *Context, clientCtx client.Context, appCreator types.App cpuProfileCleanup() } - if apiSrv != nil { - _ = apiSrv.Close() + if srv != nil { + _ = srv.Close() } if grpcSrv != nil { diff --git a/server/types/app.go b/server/types/app.go index 43e116403af1..2bdf0719fc51 100644 --- a/server/types/app.go +++ b/server/types/app.go @@ -34,11 +34,15 @@ type ( Application interface { abci.Application - RegisterAPIRoutes(*api.Server, config.APIConfig) + // ConfigGenerator retrieves the chain's config.toml generator function that is + // used to retrieve the config.toml during the start of the server. + ConfigGenerator() config.Generator + + RegisterAPIRoutes(*api.BaseServer, config.APIConfig) // RegisterExternalServices is optional function to retegister custom services // to the server that are not defined by the default SDK configuration. - RegisterExternalServices(api.SDKServer, config.ServerConfig) + RegisterExternalServices(api.Server, config.ServerConfig) // RegisterGRPCServer registers gRPC services directly with the gRPC // server. diff --git a/simapp/app.go b/simapp/app.go index b7edaa03880e..ee04fd58c789 100644 --- a/simapp/app.go +++ b/simapp/app.go @@ -552,6 +552,11 @@ func (app *SimApp) SimulationManager() *module.SimulationManager { return app.sm } +// ConfigGenerator uses the default SDK config generator. +func (app *SimApp) ConfigGenerator() config.Generator { + return config.DefaultGenerator +} + // RegisterAPIRoutes registers all application module routes with the provided // API server. func (app *SimApp) RegisterAPIRoutes(apiSvr *api.Server, apiConfig config.APIConfig) { From 4c90a06046d1d41400f2a4ae453866e7eb49386c Mon Sep 17 00:00:00 2001 From: Federico Kunze Date: Mon, 21 Dec 2020 16:10:08 -0300 Subject: [PATCH 5/8] server constructor --- server/api/server.go | 10 +++++----- server/start.go | 5 ++--- server/types/app.go | 3 +++ simapp/app.go | 9 +++++++-- testutil/network/network.go | 4 ++-- testutil/network/util.go | 2 +- 6 files changed, 20 insertions(+), 13 deletions(-) diff --git a/server/api/server.go b/server/api/server.go index 8b9322f0b830..14c793af590a 100644 --- a/server/api/server.go +++ b/server/api/server.go @@ -25,7 +25,7 @@ import ( ) type Server interface { - Base() *BaseServer + BaseServer() *BaseServer Start(config.ServerConfig) error Close() error @@ -59,7 +59,7 @@ func CustomGRPCHeaderMatcher(key string) (string, bool) { } // New creates the default SDK server instance. -func New(clientCtx client.Context, logger log.Logger) Server { +func New(clientCtx client.Context, logger log.Logger) *BaseServer { // The default JSON marshaller used by the gRPC-Gateway is unable to marshal non-nullable non-scalar fields. // Using the gogo/gateway package with the gRPC-Gateway WithMarshaler option fixes the scalar field marshalling issue. marshalerOption := &gateway.JSONPb{ @@ -72,7 +72,7 @@ func New(clientCtx client.Context, logger log.Logger) Server { return &BaseServer{ Router: mux.NewRouter(), ClientCtx: clientCtx, - logger: logger, + logger: logger.With("module", "api-server"), GRPCGatewayRouter: runtime.NewServeMux( // Custom marshaler option is required for gogo proto runtime.WithMarshalerOption(runtime.MIMEWildcard, marshalerOption), @@ -88,8 +88,8 @@ func New(clientCtx client.Context, logger log.Logger) Server { } } -// Base implements the Server interface. -func (s *BaseServer) Base() *BaseServer { return s } +// BaseServer implements the Server interface. +func (s *BaseServer) BaseServer() *BaseServer { return s } // Start starts the API server. Internally, the API server leverages Tendermint's // JSON RPC server. Configuration options are provided via config.APIConfig diff --git a/server/start.go b/server/start.go index 9e381e4f56dd..ea275bcb6628 100644 --- a/server/start.go +++ b/server/start.go @@ -21,7 +21,6 @@ import ( "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client/flags" - "github.com/cosmos/cosmos-sdk/server/api" "github.com/cosmos/cosmos-sdk/server/config" servergrpc "github.com/cosmos/cosmos-sdk/server/grpc" "github.com/cosmos/cosmos-sdk/server/types" @@ -283,11 +282,11 @@ func startInProcess(ctx *Context, clientCtx client.Context, appCreator types.App WithHomeDir(home). WithChainID(genDoc.ChainID) - srv := api.New(clientCtx, ctx.Logger.With("module", "server")) + srv := app.NewServer(clientCtx, ctx.Logger, config) if sdkCfg.API.Enable { // register routes and start server - app.RegisterAPIRoutes(srv.Base(), sdkCfg.API) + app.RegisterAPIRoutes(srv.BaseServer(), sdkCfg.API) errCh := make(chan error) go func() { diff --git a/server/types/app.go b/server/types/app.go index 2bdf0719fc51..536a22c2873e 100644 --- a/server/types/app.go +++ b/server/types/app.go @@ -38,6 +38,9 @@ type ( // used to retrieve the config.toml during the start of the server. ConfigGenerator() config.Generator + // NewServer creates a custom server for the application. + NewServer(clientCtx client.Context, logger log.Logger, cfg config.ServerConfig) api.Server + RegisterAPIRoutes(*api.BaseServer, config.APIConfig) // RegisterExternalServices is optional function to retegister custom services diff --git a/simapp/app.go b/simapp/app.go index ee04fd58c789..32f53d3933a3 100644 --- a/simapp/app.go +++ b/simapp/app.go @@ -552,6 +552,11 @@ func (app *SimApp) SimulationManager() *module.SimulationManager { return app.sm } +// NewServer creates the default SDK base server. +func (app *SimApp) NewServer(clientCtx client.Context, logger log.Logger, _ config.ServerConfig) api.Server { + return api.New(clientCtx, logger) +} + // ConfigGenerator uses the default SDK config generator. func (app *SimApp) ConfigGenerator() config.Generator { return config.DefaultGenerator @@ -559,7 +564,7 @@ func (app *SimApp) ConfigGenerator() config.Generator { // RegisterAPIRoutes registers all application module routes with the provided // API server. -func (app *SimApp) RegisterAPIRoutes(apiSvr *api.Server, apiConfig config.APIConfig) { +func (app *SimApp) RegisterAPIRoutes(apiSvr *api.BaseServer, apiConfig config.APIConfig) { clientCtx := apiSvr.ClientCtx rpc.RegisterRoutes(clientCtx, apiSvr.Router) // Register legacy tx routes. @@ -582,7 +587,7 @@ func (app *SimApp) RegisterAPIRoutes(apiSvr *api.Server, apiConfig config.APICon // RegisterExternalServices implements the Application.RegisterExternalServices method. // It performs a no-operation as SimApp doesn't expose extra services other than the // default ones provided by the SDK. -func (app *SimApp) RegisterExternalServices(_ api.SDKServer, _ config.ServerConfig) {} +func (app *SimApp) RegisterExternalServices(_ api.Server, _ config.ServerConfig) {} // RegisterTxService implements the Application.RegisterTxService method. func (app *SimApp) RegisterTxService(clientCtx client.Context) { diff --git a/testutil/network/network.go b/testutil/network/network.go index 23706c12ca80..aeb98e0a4296 100644 --- a/testutil/network/network.go +++ b/testutil/network/network.go @@ -158,7 +158,7 @@ type ( RPCClient tmclient.Client tmNode *node.Node - api *api.Server + api api.Server grpc *grpc.Server } ) @@ -196,7 +196,7 @@ func New(t *testing.T, cfg Config) *Network { // generate private keys, node IDs, and initial transactions for i := 0; i < cfg.NumValidators; i++ { - appCfg := srvconfig.DefaultConfig() + appCfg := srvconfig.DefaultConfig().GetSDKConfig() appCfg.Pruning = cfg.PruningStrategy appCfg.MinGasPrices = cfg.MinGasPrices appCfg.API.Enable = true diff --git a/testutil/network/util.go b/testutil/network/util.go index 8906c929e093..b48711a8b6bb 100644 --- a/testutil/network/util.go +++ b/testutil/network/util.go @@ -78,7 +78,7 @@ func startInProcess(cfg Config, val *Validator) error { errCh := make(chan error) go func() { - if err := apiSrv.Start(*val.AppConfig); err != nil { + if err := apiSrv.Start(val.AppConfig); err != nil { errCh <- err } }() From 7c92e59d664b8c70bb1f9880c8dc2b1399b5208a Mon Sep 17 00:00:00 2001 From: Federico Kunze Date: Thu, 31 Dec 2020 14:05:25 -0300 Subject: [PATCH 6/8] few updates from ADR --- server/grpc/server.go | 42 ----------- server/{ => services}/grpc/server_test.go | 0 server/services/grpc/service.go | 81 +++++++++++++++++++++ server/services/tendermint/service.go | 89 +++++++++++++++++++++++ server/types/service.go | 18 +++++ 5 files changed, 188 insertions(+), 42 deletions(-) delete mode 100644 server/grpc/server.go rename server/{ => services}/grpc/server_test.go (100%) create mode 100644 server/services/grpc/service.go create mode 100644 server/services/tendermint/service.go create mode 100644 server/types/service.go diff --git a/server/grpc/server.go b/server/grpc/server.go deleted file mode 100644 index 2894508c1258..000000000000 --- a/server/grpc/server.go +++ /dev/null @@ -1,42 +0,0 @@ -package grpc - -import ( - "fmt" - "net" - "time" - - "google.golang.org/grpc" - "google.golang.org/grpc/reflection" - - "github.com/cosmos/cosmos-sdk/server/types" -) - -// StartGRPCServer creates, registers starts a gRPC server on the given address. -func StartGRPCServer(app types.Application, address string) (*grpc.Server, error) { - grpcSrv := grpc.NewServer() - app.RegisterGRPCServer(grpcSrv) - - // Reflection allows external clients to see what services and methods - // the gRPC server exposes. - reflection.Register(grpcSrv) - - listener, err := net.Listen("tcp", address) - if err != nil { - return nil, err - } - - errCh := make(chan error) - go func() { - err = grpcSrv.Serve(listener) - if err != nil { - errCh <- fmt.Errorf("failed to serve: %w", err) - } - }() - - select { - case err := <-errCh: - return nil, err - case <-time.After(5 * time.Second): // assume server started successfully - return grpcSrv, nil - } -} diff --git a/server/grpc/server_test.go b/server/services/grpc/server_test.go similarity index 100% rename from server/grpc/server_test.go rename to server/services/grpc/server_test.go diff --git a/server/services/grpc/service.go b/server/services/grpc/service.go new file mode 100644 index 000000000000..714c433e0e7f --- /dev/null +++ b/server/services/grpc/service.go @@ -0,0 +1,81 @@ +package grpc + +import ( + "fmt" + "net" + "time" + + "google.golang.org/grpc" + "google.golang.org/grpc/reflection" + + "github.com/cosmos/cosmos-sdk/server/config" + "github.com/cosmos/cosmos-sdk/server/types" +) + +var _ types.Service = &Service{} + +// Service defines the gRPC service used on the Cosmos SDK. +type Service struct { + // standard gRPC server + grpcServer *grpc.Server + // listen address + address string +} + +// NewService creates a new gRPC server instance with a defined listener address. +func NewService(address string) *Service { + return &Service{ + grpcServer: grpc.NewServer(), + address: address, + } +} + +// Name returns the gRPC service name +func (Service) Name() string { + return "gRPC" +} + +// RegisterRoutes registers the gRPC server to the application. +func (s *Service) RegisterRoutes() bool { + // TODO: register on app + // app.RegisterGRPCServer(s.grpcServer) + + // Reflection allows external clients to see what services and methods + // the gRPC server exposes. + reflection.Register(s.grpcServer) + return true +} + +// Start starts the gRPC server on the registered address +func (s *Service) Start(cfg config.ServerConfig) error { + if !cfg.GetSDKConfig().GRPC.Enable { + return nil + } + + listener, err := net.Listen("tcp", s.address) + if err != nil { + return err + } + + errCh := make(chan error) + go func() { + err = s.grpcServer.Serve(listener) + if err != nil { + errCh <- fmt.Errorf("failed to serve: %w", err) + } + }() + + select { + case err := <-errCh: + return err + case <-time.After(5 * time.Second): // assume server started successfully + return nil + } +} + +// Stop stops the gRPC service gracefully. It stops the server from accepting new connections and +// RPCs and blocks until all the pending RPCs are finished. +func (s *Service) Stop() error { + s.grpcServer.GracefulStop() + return nil +} diff --git a/server/services/tendermint/service.go b/server/services/tendermint/service.go new file mode 100644 index 000000000000..402f33ba4a60 --- /dev/null +++ b/server/services/tendermint/service.go @@ -0,0 +1,89 @@ +package tendermint + +import ( + "net" + "net/http" + "time" + + "github.com/gorilla/handlers" + "github.com/gorilla/mux" + + "github.com/tendermint/tendermint/libs/log" + tmrpcserver "github.com/tendermint/tendermint/rpc/jsonrpc/server" + + "github.com/cosmos/cosmos-sdk/server/config" + "github.com/cosmos/cosmos-sdk/server/types" +) + +var _ types.Service = &Service{} + +type Service struct { + listener net.Listener + router *mux.Router + logger log.Logger +} + +// NewService returns a new Tendermint RPC service instance +func NewService(logger log.Logger) *Service { + return &Service{ + logger: logger.With("service", "tendermint-rpc"), + } +} + +// Name is the tendermint RPC service name +func (Service) Name() string { + return "Tendermint RPC" +} + +// RegisterRoutes performs a no-op (?) +func (s *Service) RegisterRoutes() bool { + // app.RegisterAPIRoutes(srv.BaseServer(), sdkCfg.API) + return true +} + +func (s *Service) Start(cfg config.ServerConfig) error { + sdkCfg := cfg.GetSDKConfig() + + if !sdkCfg.API.Enable { + return nil + } + + tmCfg := tmrpcserver.DefaultConfig() + tmCfg.MaxOpenConnections = int(sdkCfg.API.MaxOpenConnections) + tmCfg.ReadTimeout = time.Duration(sdkCfg.API.RPCReadTimeout) * time.Second + tmCfg.WriteTimeout = time.Duration(sdkCfg.API.RPCWriteTimeout) * time.Second + tmCfg.MaxBodyBytes = int64(sdkCfg.API.RPCMaxBodyBytes) + + var err error + s.listener, err = tmrpcserver.Listen(sdkCfg.API.Address, tmCfg) + if err != nil { + return err + } + + var handler http.Handler = s.router + if sdkCfg.API.EnableUnsafeCORS { + allowAllCORS := handlers.CORS(handlers.AllowedHeaders([]string{"Content-Type"})) + handler = allowAllCORS(s.router) + } + + s.logger.Info("starting RPC service...") + + errCh := make(chan error) + go func() { + if err := tmrpcserver.Serve(s.listener, handler, s.logger, tmCfg); err != nil { + errCh <- err + } + }() + + select { + case err := <-errCh: + return err + case <-time.After(5 * time.Second): // assume server started successfully + return nil + } +} + +// Stop closes the Tendermint RPC listener connection. +func (s *Service) Stop() error { + return s.listener.Close() +} diff --git a/server/types/service.go b/server/types/service.go new file mode 100644 index 000000000000..eef9600305d0 --- /dev/null +++ b/server/types/service.go @@ -0,0 +1,18 @@ +package types + +import "github.com/cosmos/cosmos-sdk/server/config" + +type Server interface { + GetService(name string) Service + RegisterServices() error + + Start(config.ServerConfig) error + Stop() error +} + +type Service interface { + Name() string + RegisterRoutes() bool + Start(config.ServerConfig) error + Stop() error +} From 61687696a972343e11c191c917f330f3913303ce Mon Sep 17 00:00:00 2001 From: Federico Kunze Date: Mon, 4 Jan 2021 11:40:24 -0300 Subject: [PATCH 7/8] update services --- server/api/server.go | 93 +++++++++++++++------------ server/services/tendermint/service.go | 5 +- server/start.go | 48 ++++---------- server/types/app.go | 6 +- server/types/service.go | 2 +- simapp/app.go | 9 +-- 6 files changed, 72 insertions(+), 91 deletions(-) diff --git a/server/api/server.go b/server/api/server.go index 14c793af590a..d8666b528d0b 100644 --- a/server/api/server.go +++ b/server/api/server.go @@ -5,17 +5,17 @@ import ( "net" "net/http" "strings" - "time" "github.com/gogo/gateway" - "github.com/gorilla/handlers" "github.com/gorilla/mux" "github.com/grpc-ecosystem/grpc-gateway/runtime" "github.com/tendermint/tendermint/libs/log" - tmrpcserver "github.com/tendermint/tendermint/rpc/jsonrpc/server" "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/server/config" + grpcservice "github.com/cosmos/cosmos-sdk/server/services/grpc" + tmservice "github.com/cosmos/cosmos-sdk/server/services/tendermint" + "github.com/cosmos/cosmos-sdk/server/types" "github.com/cosmos/cosmos-sdk/telemetry" grpctypes "github.com/cosmos/cosmos-sdk/types/grpc" "github.com/cosmos/cosmos-sdk/types/rest" @@ -24,17 +24,13 @@ import ( _ "github.com/cosmos/cosmos-sdk/client/docs/statik" ) -type Server interface { - BaseServer() *BaseServer +var _ types.Server = &BaseServer{} - Start(config.ServerConfig) error - Close() error -} - -var _ Server = &BaseServer{} - -// BaseServer defines the SDK server's API interface. +// BaseServer defines the SDK server's. type BaseServer struct { + services map[string]types.Service + config config.ServerConfig + Router *mux.Router GRPCGatewayRouter *runtime.ServeMux ClientCtx client.Context @@ -59,7 +55,7 @@ func CustomGRPCHeaderMatcher(key string) (string, bool) { } // New creates the default SDK server instance. -func New(clientCtx client.Context, logger log.Logger) *BaseServer { +func New(clientCtx client.Context, logger log.Logger, cfg config.ServerConfig) *BaseServer { // The default JSON marshaller used by the gRPC-Gateway is unable to marshal non-nullable non-scalar fields. // Using the gogo/gateway package with the gRPC-Gateway WithMarshaler option fixes the scalar field marshalling issue. marshalerOption := &gateway.JSONPb{ @@ -69,8 +65,18 @@ func New(clientCtx client.Context, logger log.Logger) *BaseServer { AnyResolver: clientCtx.InterfaceRegistry, } + router := mux.NewRouter() + tmsrv := tmservice.NewService(logger, router) + grpcsrv := grpcservice.NewService("") + + services := make(map[string]types.Service) + services[tmsrv.Name()] = tmsrv + services[grpcsrv.Name()] = grpcsrv + return &BaseServer{ - Router: mux.NewRouter(), + services: services, + config: cfg, + Router: router, ClientCtx: clientCtx, logger: logger.With("module", "api-server"), GRPCGatewayRouter: runtime.NewServeMux( @@ -88,16 +94,21 @@ func New(clientCtx client.Context, logger log.Logger) *BaseServer { } } -// BaseServer implements the Server interface. -func (s *BaseServer) BaseServer() *BaseServer { return s } +// GetService implements the Server interface. +func (s *BaseServer) GetService(name string) types.Service { + service, _ := s.services[name] + return service +} -// Start starts the API server. Internally, the API server leverages Tendermint's -// JSON RPC server. Configuration options are provided via config.APIConfig -// and are delegated to the Tendermint JSON RPC server. The process is -// non-blocking, so an external signal handler must be used. -func (s *BaseServer) Start(cfg config.ServerConfig) error { - sdkCfg := cfg.GetSDKConfig() +// RegisterServices implements the Server interface. +func (s *BaseServer) RegisterServices() error { + for name, service := range s.services { + if !service.RegisterRoutes() { + return fmt.Errorf("failed to register routes for service %s", name) + } + } + sdkCfg := s.config.GetSDKConfig() if sdkCfg.Telemetry.Enabled { m, err := telemetry.New(sdkCfg.Telemetry) if err != nil { @@ -108,34 +119,34 @@ func (s *BaseServer) Start(cfg config.ServerConfig) error { s.registerMetrics() } - tmCfg := tmrpcserver.DefaultConfig() - tmCfg.MaxOpenConnections = int(sdkCfg.API.MaxOpenConnections) - tmCfg.ReadTimeout = time.Duration(sdkCfg.API.RPCReadTimeout) * time.Second - tmCfg.WriteTimeout = time.Duration(sdkCfg.API.RPCWriteTimeout) * time.Second - tmCfg.MaxBodyBytes = int64(sdkCfg.API.RPCMaxBodyBytes) - - listener, err := tmrpcserver.Listen(sdkCfg.API.Address, tmCfg) - if err != nil { - return err - } - s.registerGRPCGatewayRoutes() - s.listener = listener - var h http.Handler = s.Router + return nil +} - if sdkCfg.API.EnableUnsafeCORS { - allowAllCORS := handlers.CORS(handlers.AllowedHeaders([]string{"Content-Type"})) - return tmrpcserver.Serve(s.listener, allowAllCORS(h), s.logger, tmCfg) +// Start starts the API server. Internally, the API server leverages Tendermint's +// JSON RPC server. Configuration options are provided via config.APIConfig +// and are delegated to the Tendermint JSON RPC server. The process is +// non-blocking, so an external signal handler must be used. +func (s *BaseServer) Start() error { + for name, service := range s.services { + if err := service.Start(); err != nil { + return fmt.Errorf("service %s start failed: %w", name, err) + } } - s.logger.Info("starting API server...") - return tmrpcserver.Serve(s.listener, s.Router, s.logger, tmCfg) + return nil } // Close closes the API server. func (s *BaseServer) Close() error { - return s.listener.Close() + for name, service := range s.services { + if err := service.Stop(); err != nil { + return fmt.Errorf("service %s stop failed: %w", name, err) + } + } + + return nil } func (s *BaseServer) registerGRPCGatewayRoutes() { diff --git a/server/services/tendermint/service.go b/server/services/tendermint/service.go index 402f33ba4a60..f44fa07c993d 100644 --- a/server/services/tendermint/service.go +++ b/server/services/tendermint/service.go @@ -19,14 +19,15 @@ var _ types.Service = &Service{} type Service struct { listener net.Listener - router *mux.Router logger log.Logger + router *mux.Router } // NewService returns a new Tendermint RPC service instance -func NewService(logger log.Logger) *Service { +func NewService(logger log.Logger, router *mux.Router) *Service { return &Service{ logger: logger.With("service", "tendermint-rpc"), + router: router, } } diff --git a/server/start.go b/server/start.go index ea275bcb6628..81defea4a0f3 100644 --- a/server/start.go +++ b/server/start.go @@ -6,7 +6,6 @@ import ( "fmt" "os" "runtime/pprof" - "time" "github.com/spf13/cobra" "github.com/tendermint/tendermint/abci/server" @@ -17,12 +16,10 @@ import ( pvm "github.com/tendermint/tendermint/privval" "github.com/tendermint/tendermint/proxy" "github.com/tendermint/tendermint/rpc/client/local" - "google.golang.org/grpc" "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client/flags" "github.com/cosmos/cosmos-sdk/server/config" - servergrpc "github.com/cosmos/cosmos-sdk/server/grpc" "github.com/cosmos/cosmos-sdk/server/types" storetypes "github.com/cosmos/cosmos-sdk/store/types" ) @@ -284,39 +281,22 @@ func startInProcess(ctx *Context, clientCtx client.Context, appCreator types.App srv := app.NewServer(clientCtx, ctx.Logger, config) - if sdkCfg.API.Enable { - // register routes and start server - app.RegisterAPIRoutes(srv.BaseServer(), sdkCfg.API) - errCh := make(chan error) - - go func() { - if err := srv.Start(sdkCfg); err != nil { - errCh <- err - } - }() - - select { - case err := <-errCh: - return err - case <-time.After(5 * time.Second): // assume server started successfully - } + // register all the server services + if err := srv.RegisterServices(); err != nil { + return err } - var grpcSrv *grpc.Server - if sdkCfg.GRPC.Enable { - // initialize, register and start gRPC server - grpcSrv, err = servergrpc.StartGRPCServer(app, sdkCfg.GRPC.Address) - if err != nil { - return err - } + // start all services + // NOTE: each service needs to be handled in it's own goroutine + if err := srv.Start(); err != nil { + return err } - // register services that are external to the default services provided by the SDK - app.RegisterExternalServices(srv, config) - defer func() { if tmNode.IsRunning() { - _ = tmNode.Stop() + if err := tmNode.Stop(); err != nil { + ctx.Logger.Error("failed to stop tendermint node", "error", err) + } } if cpuProfileCleanup != nil { @@ -324,11 +304,9 @@ func startInProcess(ctx *Context, clientCtx client.Context, appCreator types.App } if srv != nil { - _ = srv.Close() - } - - if grpcSrv != nil { - grpcSrv.Stop() + if err := srv.Stop(); err != nil { + ctx.Logger.Error("failed to stop server", "error", err) + } } ctx.Logger.Info("exiting...") diff --git a/server/types/app.go b/server/types/app.go index 536a22c2873e..708dfd7d8b0a 100644 --- a/server/types/app.go +++ b/server/types/app.go @@ -39,14 +39,10 @@ type ( ConfigGenerator() config.Generator // NewServer creates a custom server for the application. - NewServer(clientCtx client.Context, logger log.Logger, cfg config.ServerConfig) api.Server + NewServer(clientCtx client.Context, logger log.Logger, cfg config.ServerConfig) Server RegisterAPIRoutes(*api.BaseServer, config.APIConfig) - // RegisterExternalServices is optional function to retegister custom services - // to the server that are not defined by the default SDK configuration. - RegisterExternalServices(api.Server, config.ServerConfig) - // RegisterGRPCServer registers gRPC services directly with the gRPC // server. RegisterGRPCServer(grpc.Server) diff --git a/server/types/service.go b/server/types/service.go index eef9600305d0..486b73ccc34c 100644 --- a/server/types/service.go +++ b/server/types/service.go @@ -6,7 +6,7 @@ type Server interface { GetService(name string) Service RegisterServices() error - Start(config.ServerConfig) error + Start() error Stop() error } diff --git a/simapp/app.go b/simapp/app.go index 32f53d3933a3..d60394471853 100644 --- a/simapp/app.go +++ b/simapp/app.go @@ -553,8 +553,8 @@ func (app *SimApp) SimulationManager() *module.SimulationManager { } // NewServer creates the default SDK base server. -func (app *SimApp) NewServer(clientCtx client.Context, logger log.Logger, _ config.ServerConfig) api.Server { - return api.New(clientCtx, logger) +func (app *SimApp) NewServer(clientCtx client.Context, logger log.Logger, cfg config.ServerConfig) servertypes.Server { + return api.New(clientCtx, logger, cfg) } // ConfigGenerator uses the default SDK config generator. @@ -584,11 +584,6 @@ func (app *SimApp) RegisterAPIRoutes(apiSvr *api.BaseServer, apiConfig config.AP } } -// RegisterExternalServices implements the Application.RegisterExternalServices method. -// It performs a no-operation as SimApp doesn't expose extra services other than the -// default ones provided by the SDK. -func (app *SimApp) RegisterExternalServices(_ api.Server, _ config.ServerConfig) {} - // RegisterTxService implements the Application.RegisterTxService method. func (app *SimApp) RegisterTxService(clientCtx client.Context) { authtx.RegisterTxService(app.BaseApp.GRPCQueryRouter(), clientCtx, app.BaseApp.Simulate, app.interfaceRegistry) From eda64fce7b6cbb715bc3f9fdbbba67f4ecf1febf Mon Sep 17 00:00:00 2001 From: Federico Kunze Date: Mon, 4 Jan 2021 13:42:26 -0300 Subject: [PATCH 8/8] build --- server/api/server.go | 13 ++++--------- server/types/app.go | 8 -------- testutil/network/network.go | 13 ++++++------- testutil/network/util.go | 23 ++++++++--------------- 4 files changed, 18 insertions(+), 39 deletions(-) diff --git a/server/api/server.go b/server/api/server.go index d8666b528d0b..3357e5f57015 100644 --- a/server/api/server.go +++ b/server/api/server.go @@ -2,7 +2,6 @@ package api import ( "fmt" - "net" "net/http" "strings" @@ -30,14 +29,11 @@ var _ types.Server = &BaseServer{} type BaseServer struct { services map[string]types.Service config config.ServerConfig + metrics *telemetry.Metrics Router *mux.Router GRPCGatewayRouter *runtime.ServeMux ClientCtx client.Context - - logger log.Logger - metrics *telemetry.Metrics - listener net.Listener } // CustomGRPCHeaderMatcher for mapping request headers to @@ -78,7 +74,6 @@ func New(clientCtx client.Context, logger log.Logger, cfg config.ServerConfig) * config: cfg, Router: router, ClientCtx: clientCtx, - logger: logger.With("module", "api-server"), GRPCGatewayRouter: runtime.NewServeMux( // Custom marshaler option is required for gogo proto runtime.WithMarshalerOption(runtime.MIMEWildcard, marshalerOption), @@ -130,7 +125,7 @@ func (s *BaseServer) RegisterServices() error { // non-blocking, so an external signal handler must be used. func (s *BaseServer) Start() error { for name, service := range s.services { - if err := service.Start(); err != nil { + if err := service.Start(s.config); err != nil { return fmt.Errorf("service %s start failed: %w", name, err) } } @@ -138,8 +133,8 @@ func (s *BaseServer) Start() error { return nil } -// Close closes the API server. -func (s *BaseServer) Close() error { +// Stop implements the Server interface. +func (s *BaseServer) Stop() error { for name, service := range s.services { if err := service.Stop(); err != nil { return fmt.Errorf("service %s stop failed: %w", name, err) diff --git a/server/types/app.go b/server/types/app.go index 708dfd7d8b0a..1cc3eef43070 100644 --- a/server/types/app.go +++ b/server/types/app.go @@ -4,7 +4,6 @@ import ( "encoding/json" "io" - "github.com/gogo/protobuf/grpc" "github.com/spf13/cobra" abci "github.com/tendermint/tendermint/abci/types" "github.com/tendermint/tendermint/libs/log" @@ -12,7 +11,6 @@ import ( dbm "github.com/tendermint/tm-db" "github.com/cosmos/cosmos-sdk/client" - "github.com/cosmos/cosmos-sdk/server/api" "github.com/cosmos/cosmos-sdk/server/config" ) @@ -41,12 +39,6 @@ type ( // NewServer creates a custom server for the application. NewServer(clientCtx client.Context, logger log.Logger, cfg config.ServerConfig) Server - RegisterAPIRoutes(*api.BaseServer, config.APIConfig) - - // RegisterGRPCServer registers gRPC services directly with the gRPC - // server. - RegisterGRPCServer(grpc.Server) - // RegisterTxService registers the gRPC Query service for tx (such as tx // simulation, fetching txs by hash...). RegisterTxService(clientCtx client.Context) diff --git a/testutil/network/network.go b/testutil/network/network.go index 3de94b473670..50f004f814c0 100644 --- a/testutil/network/network.go +++ b/testutil/network/network.go @@ -33,7 +33,6 @@ import ( "github.com/cosmos/cosmos-sdk/crypto/keyring" cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" "github.com/cosmos/cosmos-sdk/server" - "github.com/cosmos/cosmos-sdk/server/api" srvconfig "github.com/cosmos/cosmos-sdk/server/config" servertypes "github.com/cosmos/cosmos-sdk/server/types" "github.com/cosmos/cosmos-sdk/simapp" @@ -60,8 +59,8 @@ func NewAppConstructor(encodingCfg params.EncodingConfig) AppConstructor { val.Ctx.Logger, dbm.NewMemDB(), nil, true, make(map[int64]bool), val.Ctx.Config.RootDir, 0, encodingCfg, simapp.EmptyAppOptions{}, - baseapp.SetPruning(storetypes.NewPruningOptionsFromString(val.AppConfig.Pruning)), - baseapp.SetMinGasPrices(val.AppConfig.MinGasPrices), + baseapp.SetPruning(storetypes.NewPruningOptionsFromString(val.AppConfig.GetSDKConfig().Pruning)), + baseapp.SetMinGasPrices(val.AppConfig.GetSDKConfig().MinGasPrices), ) } } @@ -143,7 +142,7 @@ type ( // a client can make RPC and API calls and interact with any client command // or handler. Validator struct { - AppConfig *srvconfig.Config + AppConfig srvconfig.ServerConfig ClientCtx client.Context Ctx *server.Context Dir string @@ -158,7 +157,7 @@ type ( RPCClient tmclient.Client tmNode *node.Node - api api.Server + server servertypes.Server grpc *grpc.Server } ) @@ -460,8 +459,8 @@ func (n *Network) Cleanup() { _ = v.tmNode.Stop() } - if v.api != nil { - _ = v.api.Close() + if v.server != nil { + _ = v.server.Stop() } if v.grpc != nil { diff --git a/testutil/network/util.go b/testutil/network/util.go index b48711a8b6bb..57f5f362d46b 100644 --- a/testutil/network/util.go +++ b/testutil/network/util.go @@ -15,7 +15,6 @@ import ( tmtime "github.com/tendermint/tendermint/types/time" "github.com/cosmos/cosmos-sdk/server/api" - servergrpc "github.com/cosmos/cosmos-sdk/server/grpc" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" "github.com/cosmos/cosmos-sdk/x/genutil" @@ -60,7 +59,7 @@ func startInProcess(cfg Config, val *Validator) error { } // We'll need a RPC client if the validator exposes a gRPC or REST endpoint. - if val.APIAddress != "" || val.AppConfig.GRPC.Enable { + if val.APIAddress != "" || val.AppConfig.GetSDKConfig().GRPC.Enable { val.ClientCtx = val.ClientCtx. WithClient(val.RPCClient) @@ -72,13 +71,16 @@ func startInProcess(cfg Config, val *Validator) error { } if val.APIAddress != "" { - apiSrv := api.New(val.ClientCtx, logger.With("module", "api-server")) - app.RegisterAPIRoutes(apiSrv, val.AppConfig.API) + apiSrv := api.New(val.ClientCtx, logger.With("module", "api-server"), val.AppConfig) + + if err := apiSrv.RegisterServices(); err != nil { + return err + } errCh := make(chan error) go func() { - if err := apiSrv.Start(val.AppConfig); err != nil { + if err := apiSrv.Start(); err != nil { errCh <- err } }() @@ -89,16 +91,7 @@ func startInProcess(cfg Config, val *Validator) error { case <-time.After(5 * time.Second): // assume server started successfully } - val.api = apiSrv - } - - if val.AppConfig.GRPC.Enable { - grpcSrv, err := servergrpc.StartGRPCServer(app, val.AppConfig.GRPC.Address) - if err != nil { - return err - } - - val.grpc = grpcSrv + val.server = apiSrv } return nil