Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor(runtime/v2): simplify app manager #22300

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 19 additions & 24 deletions runtime/v2/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,26 +23,24 @@ import (
// done declaratively with an app config and the rest of it is done the old way.
// See simapp/app_v2.go for an example of this setup.
type App[T transaction.Tx] struct {
*appmanager.AppManager[T]
appmanager.AppManager[T]

// app manager dependencies
// app configuration
logger log.Logger
config *runtimev2.Module

// state
stf *stf.STF[T]
msgRouterBuilder *stf.MsgRouterBuilder
queryRouterBuilder *stf.MsgRouterBuilder
db Store
storeLoader StoreLoader

// app configuration
logger log.Logger
config *runtimev2.Module

// modules
interfaceRegistrar registry.InterfaceRegistrar
amino registry.AminoRegistrar
moduleManager *MM[T]

// QueryHandlers defines the query handlers
QueryHandlers map[string]appmodulev2.Handler

storeLoader StoreLoader
queryHandlers map[string]appmodulev2.Handler // queryHandlers defines the query handlers
}

// Name returns the app name.
Expand Down Expand Up @@ -85,24 +83,21 @@ func (a *App[T]) LoadLatestHeight() (uint64, error) {
return a.db.GetLatestVersion()
}

// Close is called in start cmd to gracefully cleanup resources.
func (a *App[T]) Close() error {
return nil
}

func (a *App[T]) GetAppManager() *appmanager.AppManager[T] {
return a.AppManager
}

func (a *App[T]) GetQueryHandlers() map[string]appmodulev2.Handler {
return a.QueryHandlers
// GetQueryHandlers returns the query handlers.
func (a *App[T]) QueryHandlers() map[string]appmodulev2.Handler {
return a.queryHandlers
}

// GetSchemaDecoderResolver returns the module schema resolver.
func (a *App[T]) GetSchemaDecoderResolver() decoding.DecoderResolver {
// SchemaDecoderResolver returns the module schema resolver.
func (a *App[T]) SchemaDecoderResolver() decoding.DecoderResolver {
moduleSet := map[string]any{}
for moduleName, module := range a.moduleManager.Modules() {
moduleSet[moduleName] = module
}
return decoding.ModuleSetDecoderResolver(moduleSet)
}

// Close is called in start cmd to gracefully cleanup resources.
func (a *App[T]) Close() error {
return nil
}
127 changes: 60 additions & 67 deletions runtime/v2/builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,6 @@ type AppBuilder[T transaction.Tx] struct {
postTxExec func(ctx context.Context, tx T, success bool) error
}

// DefaultGenesis returns a default genesis from the registered AppModule's.
func (a *AppBuilder[T]) DefaultGenesis() map[string]json.RawMessage {
return a.app.moduleManager.DefaultGenesis()
}

// RegisterModules registers the provided modules with the module manager.
// This is the primary hook for integrating with modules which are not registered using the app config.
func (a *AppBuilder[T]) RegisterModules(modules map[string]appmodulev2.AppModule) error {
Expand Down Expand Up @@ -98,7 +93,7 @@ func (a *AppBuilder[T]) Build(opts ...AppBuilderOption[T]) (*App[T], error) {

endBlocker, valUpdate := a.app.moduleManager.EndBlock()

stf, err := stf.NewSTF[T](
stf, err := stf.New[T](
a.app.logger.With("module", "stf"),
a.app.msgRouterBuilder,
a.app.queryRouterBuilder,
Expand All @@ -115,77 +110,75 @@ func (a *AppBuilder[T]) Build(opts ...AppBuilderOption[T]) (*App[T], error) {
}
a.app.stf = stf

appManagerBuilder := appmanager.Builder[T]{
STF: a.app.stf,
DB: a.app.db,
ValidateTxGasLimit: a.app.config.GasConfig.ValidateTxGasLimit,
QueryGasLimit: a.app.config.GasConfig.QueryGasLimit,
SimulationGasLimit: a.app.config.GasConfig.SimulationGasLimit,
InitGenesis: func(
ctx context.Context,
src io.Reader,
txHandler func(json.RawMessage) error,
) (store.WriterMap, error) {
// this implementation assumes that the state is a JSON object
bz, err := io.ReadAll(src)
if err != nil {
return nil, fmt.Errorf("failed to read import state: %w", err)
}
var genesisJSON map[string]json.RawMessage
if err = json.Unmarshal(bz, &genesisJSON); err != nil {
return nil, err
}

v, zeroState, err := a.app.db.StateLatest()
if err != nil {
return nil, fmt.Errorf("unable to get latest state: %w", err)
}
if v != 0 { // TODO: genesis state may be > 0, we need to set version on store
return nil, errors.New("cannot init genesis on non-zero state")
}
genesisCtx := services.NewGenesisContext(a.branch(zeroState))
genesisState, err := genesisCtx.Mutate(ctx, func(ctx context.Context) error {
err = a.app.moduleManager.InitGenesisJSON(ctx, genesisJSON, txHandler)
if err != nil {
return fmt.Errorf("failed to init genesis: %w", err)
}
return nil
})

return genesisState, err
a.app.AppManager = appmanager.New[T](
appmanager.Config{
ValidateTxGasLimit: a.app.config.GasConfig.ValidateTxGasLimit,
QueryGasLimit: a.app.config.GasConfig.QueryGasLimit,
SimulationGasLimit: a.app.config.GasConfig.SimulationGasLimit,
},
ExportGenesis: func(ctx context.Context, version uint64) ([]byte, error) {
state, err := a.app.db.StateAt(version)
if err != nil {
return nil, fmt.Errorf("unable to get state at given version: %w", err)
}
a.app.db,
a.app.stf,
a.initGenesis,
a.exportGenesis,
)

genesisJson, err := a.app.moduleManager.ExportGenesisForModules(
ctx,
func() store.WriterMap {
return a.branch(state)
},
)
if err != nil {
return nil, fmt.Errorf("failed to export genesis: %w", err)
}
return a.app, nil
}

bz, err := json.Marshal(genesisJson)
if err != nil {
return nil, fmt.Errorf("failed to marshal genesis: %w", err)
}
// initGenesis returns the app initialization genesis for modules
func (a *AppBuilder[T]) initGenesis(ctx context.Context, src io.Reader, txHandler func(json.RawMessage) error) (store.WriterMap, error) {
// this implementation assumes that the state is a JSON object
bz, err := io.ReadAll(src)
if err != nil {
return nil, fmt.Errorf("failed to read import state: %w", err)
}
var genesisJSON map[string]json.RawMessage
if err = json.Unmarshal(bz, &genesisJSON); err != nil {
return nil, err
}

v, zeroState, err := a.app.db.StateLatest()
if err != nil {
return nil, fmt.Errorf("unable to get latest state: %w", err)
}
if v != 0 { // TODO: genesis state may be > 0, we need to set version on store
return nil, errors.New("cannot init genesis on non-zero state")
}
genesisCtx := services.NewGenesisContext(a.branch(zeroState))
genesisState, err := genesisCtx.Mutate(ctx, func(ctx context.Context) error {
err = a.app.moduleManager.InitGenesisJSON(ctx, genesisJSON, txHandler)
if err != nil {
return fmt.Errorf("failed to init genesis: %w", err)
}
return nil
})

return bz, nil
return genesisState, err
}

// exportGenesis returns the app export genesis logic for modules
func (a *AppBuilder[T]) exportGenesis(ctx context.Context, version uint64) ([]byte, error) {
state, err := a.app.db.StateAt(version)
if err != nil {
return nil, fmt.Errorf("unable to get state at given version: %w", err)
}

genesisJson, err := a.app.moduleManager.ExportGenesisForModules(
ctx,
func() store.WriterMap {
return a.branch(state)
},
)
if err != nil {
return nil, fmt.Errorf("failed to export genesis: %w", err)
}

appManager, err := appManagerBuilder.Build()
bz, err := json.Marshal(genesisJson)
if err != nil {
return nil, fmt.Errorf("failed to build app manager: %w", err)
return nil, fmt.Errorf("failed to marshal genesis: %w", err)
}
a.app.AppManager = appManager

return a.app, nil
return bz, nil
}

// AppBuilderOption is a function that can be passed to AppBuilder.Build to customize the resulting app.
Expand Down
4 changes: 2 additions & 2 deletions runtime/v2/manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -636,7 +636,7 @@ func registerServices[T transaction.Tx](s appmodulev2.AppModule, app *App[T], re

// merge maps
for path, decoder := range c.queryHandlers {
app.QueryHandlers[path] = decoder
app.queryHandlers[path] = decoder
julienrbrt marked this conversation as resolved.
Show resolved Hide resolved
}
}

Expand All @@ -655,7 +655,7 @@ func registerServices[T transaction.Tx](s appmodulev2.AppModule, app *App[T], re
module.RegisterQueryHandlers(&wrapper)

for path, handler := range wrapper.handlers {
app.QueryHandlers[path] = handler
app.queryHandlers[path] = handler
}
}

Expand Down
2 changes: 1 addition & 1 deletion runtime/v2/module.go
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ func ProvideAppBuilder[T transaction.Tx](
amino: amino,
msgRouterBuilder: msgRouterBuilder,
queryRouterBuilder: stf.NewMsgRouterBuilder(), // TODO dedicated query router
QueryHandlers: map[string]appmodulev2.Handler{},
queryHandlers: map[string]appmodulev2.Handler{},
julienrbrt marked this conversation as resolved.
Show resolved Hide resolved
storeLoader: DefaultStoreLoader,
}
appBuilder := &AppBuilder[T]{app: app, storeBuilder: storeBuilder}
Expand Down
6 changes: 3 additions & 3 deletions server/v2/api/grpc/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,14 +57,14 @@ func (s *Server[T]) Init(appI serverv2.AppI[T], cfg map[string]any, logger log.L
return fmt.Errorf("failed to unmarshal config: %w", err)
}
}
methodsMap := appI.GetQueryHandlers()
methodsMap := appI.QueryHandlers()

grpcSrv := grpc.NewServer(
grpc.ForceServerCodec(newProtoCodec(appI.InterfaceRegistry()).GRPCCodec()),
grpc.MaxSendMsgSize(serverCfg.MaxSendMsgSize),
grpc.MaxRecvMsgSize(serverCfg.MaxRecvMsgSize),
grpc.UnknownServiceHandler(
makeUnknownServiceHandler(methodsMap, appI.GetAppManager()),
makeUnknownServiceHandler(methodsMap, appI),
julienrbrt marked this conversation as resolved.
Show resolved Hide resolved
),
)

Expand All @@ -85,7 +85,7 @@ func (s *Server[T]) StartCmdFlags() *pflag.FlagSet {
}

func makeUnknownServiceHandler(handlers map[string]appmodulev2.Handler, querier interface {
Query(ctx context.Context, version uint64, msg gogoproto.Message) (gogoproto.Message, error)
Query(ctx context.Context, version uint64, msg transaction.Msg) (transaction.Msg, error)
},
) grpc.StreamHandler {
getRegistry := sync.OnceValues(gogoproto.MergedRegistry)
Expand Down
4 changes: 2 additions & 2 deletions server/v2/api/rest/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,12 @@ const (
MaxBodySize = 1 << 20 // 1 MB
)

func NewDefaultHandler[T transaction.Tx](appManager *appmanager.AppManager[T]) http.Handler {
func NewDefaultHandler[T transaction.Tx](appManager appmanager.AppManager[T]) http.Handler {
return &DefaultHandler[T]{appManager: appManager}
}

type DefaultHandler[T transaction.Tx] struct {
appManager *appmanager.AppManager[T]
appManager appmanager.AppManager[T]
}

func (h *DefaultHandler[T]) ServeHTTP(w http.ResponseWriter, r *http.Request) {
Expand Down
2 changes: 1 addition & 1 deletion server/v2/api/rest/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ func (s *Server[T]) Init(appI serverv2.AppI[T], cfg map[string]any, logger log.L
}

s.router = http.NewServeMux()
s.router.Handle("/", NewDefaultHandler(appI.GetAppManager()))
s.router.Handle("/", NewDefaultHandler(appI))
s.config = serverCfg

return nil
Expand Down
Loading
Loading