Skip to content

Commit 05fb492

Browse files
authored
refactor(server/v2): clean up storage use and config (#22008)
1 parent 43c41be commit 05fb492

23 files changed

+344
-277
lines changed

runtime/v2/app.go

-20
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@ package runtime
22

33
import (
44
"encoding/json"
5-
"errors"
6-
"slices"
75

86
runtimev2 "cosmossdk.io/api/cosmos/app/runtime/v2"
97
appmodulev2 "cosmossdk.io/core/appmodule/v2"
@@ -36,8 +34,6 @@ type App[T transaction.Tx] struct {
3634
logger log.Logger
3735
config *runtimev2.Module
3836

39-
// modules configuration
40-
storeKeys []string
4137
interfaceRegistrar registry.InterfaceRegistrar
4238
amino registry.AminoRegistrar
4339
moduleManager *MM[T]
@@ -93,22 +89,6 @@ func (a *App[T]) Close() error {
9389
return nil
9490
}
9591

96-
// GetStoreKeys returns all the app store keys.
97-
func (a *App[T]) GetStoreKeys() []string {
98-
return a.storeKeys
99-
}
100-
101-
// UnsafeFindStoreKey fetches a registered StoreKey from the App in linear time.
102-
// NOTE: This should only be used in testing.
103-
func (a *App[T]) UnsafeFindStoreKey(storeKey string) (string, error) {
104-
i := slices.IndexFunc(a.storeKeys, func(s string) bool { return s == storeKey })
105-
if i == -1 {
106-
return "", errors.New("store key not found")
107-
}
108-
109-
return a.storeKeys[i], nil
110-
}
111-
11292
// GetStore returns the app store.
11393
func (a *App[T]) GetStore() Store {
11494
return a.db

runtime/v2/builder.go

+15-12
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,15 @@ import (
1515
"cosmossdk.io/server/v2/appmanager"
1616
"cosmossdk.io/server/v2/stf"
1717
"cosmossdk.io/server/v2/stf/branch"
18+
"cosmossdk.io/store/v2/root"
1819
)
1920

2021
// AppBuilder is a type that is injected into a container by the runtime/v2 module
2122
// (as *AppBuilder) which can be used to create an app which is compatible with
2223
// the existing app.go initialization conventions.
2324
type AppBuilder[T transaction.Tx] struct {
24-
app *App[T]
25+
app *App[T]
26+
storeBuilder root.Builder
2527

2628
// the following fields are used to overwrite the default
2729
branch func(state store.ReaderMap) store.WriterMap
@@ -62,14 +64,6 @@ func (a *AppBuilder[T]) RegisterModules(modules map[string]appmodulev2.AppModule
6264
return nil
6365
}
6466

65-
// RegisterStores registers the provided store keys.
66-
// This method should only be used for registering extra stores
67-
// which is necessary for modules that not registered using the app config.
68-
// To be used in combination of RegisterModules.
69-
func (a *AppBuilder[T]) RegisterStores(keys ...string) {
70-
a.app.storeKeys = append(a.app.storeKeys, keys...)
71-
}
72-
7367
// Build builds an *App instance.
7468
func (a *AppBuilder[T]) Build(opts ...AppBuilderOption[T]) (*App[T], error) {
7569
for _, opt := range opts {
@@ -93,8 +87,9 @@ func (a *AppBuilder[T]) Build(opts ...AppBuilderOption[T]) (*App[T], error) {
9387
}
9488
}
9589

90+
a.app.db = a.storeBuilder.Get()
9691
if a.app.db == nil {
97-
return nil, fmt.Errorf("app.db is not set, it is required to build the app")
92+
return nil, fmt.Errorf("storeBuilder did not return a db")
9893
}
9994

10095
if err := a.app.moduleManager.RegisterServices(a.app); err != nil {
@@ -205,15 +200,23 @@ func AppBuilderWithBranch[T transaction.Tx](branch func(state store.ReaderMap) s
205200

206201
// AppBuilderWithTxValidator sets the tx validator for the app.
207202
// It overrides all default tx validators defined by modules.
208-
func AppBuilderWithTxValidator[T transaction.Tx](txValidators func(ctx context.Context, tx T) error) AppBuilderOption[T] {
203+
func AppBuilderWithTxValidator[T transaction.Tx](
204+
txValidators func(
205+
ctx context.Context, tx T,
206+
) error,
207+
) AppBuilderOption[T] {
209208
return func(a *AppBuilder[T]) {
210209
a.txValidator = txValidators
211210
}
212211
}
213212

214213
// AppBuilderWithPostTxExec sets logic that will be executed after each transaction.
215214
// When not provided, a no-op function will be used.
216-
func AppBuilderWithPostTxExec[T transaction.Tx](postTxExec func(ctx context.Context, tx T, success bool) error) AppBuilderOption[T] {
215+
func AppBuilderWithPostTxExec[T transaction.Tx](
216+
postTxExec func(
217+
ctx context.Context, tx T, success bool,
218+
) error,
219+
) AppBuilderOption[T] {
217220
return func(a *AppBuilder[T]) {
218221
a.postTxExec = postTxExec
219222
}

runtime/v2/module.go

+42-76
Original file line numberDiff line numberDiff line change
@@ -19,15 +19,14 @@ import (
1919
"cosmossdk.io/core/event"
2020
"cosmossdk.io/core/header"
2121
"cosmossdk.io/core/registry"
22-
"cosmossdk.io/core/server"
2322
"cosmossdk.io/core/store"
2423
"cosmossdk.io/core/transaction"
2524
"cosmossdk.io/depinject"
2625
"cosmossdk.io/depinject/appconfig"
2726
"cosmossdk.io/log"
2827
"cosmossdk.io/runtime/v2/services"
2928
"cosmossdk.io/server/v2/stf"
30-
rootstore "cosmossdk.io/store/v2/root"
29+
"cosmossdk.io/store/v2/root"
3130
)
3231

3332
var (
@@ -97,9 +96,9 @@ func init() {
9796
appconfig.Register(&runtimev2.Module{},
9897
appconfig.Provide(
9998
ProvideAppBuilder[transaction.Tx],
100-
ProvideEnvironment[transaction.Tx],
10199
ProvideModuleManager[transaction.Tx],
102-
ProvideStoreBuilder,
100+
ProvideEnvironment,
101+
ProvideKVService,
103102
),
104103
appconfig.Invoke(SetupAppBuilder),
105104
)
@@ -108,6 +107,7 @@ func init() {
108107
func ProvideAppBuilder[T transaction.Tx](
109108
interfaceRegistrar registry.InterfaceRegistrar,
110109
amino registry.AminoRegistrar,
110+
storeBuilder root.Builder,
111111
) (
112112
*AppBuilder[T],
113113
*stf.MsgRouterBuilder,
@@ -127,15 +127,14 @@ func ProvideAppBuilder[T transaction.Tx](
127127

128128
msgRouterBuilder := stf.NewMsgRouterBuilder()
129129
app := &App[T]{
130-
storeKeys: nil,
131130
interfaceRegistrar: interfaceRegistrar,
132131
amino: amino,
133132
msgRouterBuilder: msgRouterBuilder,
134133
queryRouterBuilder: stf.NewMsgRouterBuilder(), // TODO dedicated query router
135134
QueryHandlers: map[string]appmodulev2.Handler{},
136135
storeLoader: DefaultStoreLoader,
137136
}
138-
appBuilder := &AppBuilder[T]{app: app}
137+
appBuilder := &AppBuilder[T]{app: app, storeBuilder: storeBuilder}
139138

140139
return appBuilder, msgRouterBuilder, appModule[T]{app}, protoFiles, protoTypes
141140
}
@@ -149,12 +148,7 @@ type AppInputs struct {
149148
InterfaceRegistrar registry.InterfaceRegistrar
150149
LegacyAmino registry.AminoRegistrar
151150
Logger log.Logger
152-
// StoreBuilder is a builder for a store/v2 RootStore satisfying the Store interface
153-
StoreBuilder *StoreBuilder
154-
// StoreOptions are required as input for the StoreBuilder. If not provided, the default options are used.
155-
StoreOptions *rootstore.Options `optional:"true"`
156-
// DynamicConfig can be nil in client wiring, but is required in server wiring.
157-
DynamicConfig server.DynamicConfig `optional:"true"`
151+
StoreBuilder root.Builder
158152
}
159153

160154
func SetupAppBuilder(inputs AppInputs) {
@@ -164,24 +158,8 @@ func SetupAppBuilder(inputs AppInputs) {
164158
app.moduleManager = inputs.ModuleManager
165159
app.moduleManager.RegisterInterfaces(inputs.InterfaceRegistrar)
166160
app.moduleManager.RegisterLegacyAminoCodec(inputs.LegacyAmino)
167-
168-
if inputs.DynamicConfig == nil {
169-
return
170-
}
171-
storeOptions := rootstore.DefaultStoreOptions()
172-
if inputs.StoreOptions != nil {
173-
storeOptions = *inputs.StoreOptions
174-
}
175-
var err error
176-
app.db, err = inputs.StoreBuilder.Build(
177-
inputs.Logger,
178-
app.storeKeys,
179-
inputs.DynamicConfig,
180-
storeOptions,
181-
)
182-
if err != nil {
183-
panic(err)
184-
}
161+
// STF requires some state to run
162+
inputs.StoreBuilder.RegisterKey("stf")
185163
}
186164

187165
func ProvideModuleManager[T transaction.Tx](
@@ -192,44 +170,47 @@ func ProvideModuleManager[T transaction.Tx](
192170
return NewModuleManager[T](logger, config, modules)
193171
}
194172

195-
// ProvideEnvironment provides the environment for keeper modules, while maintaining backward compatibility and provide services directly as well.
196-
func ProvideEnvironment[T transaction.Tx](
197-
logger log.Logger,
173+
func ProvideKVService(
198174
config *runtimev2.Module,
199175
key depinject.ModuleKey,
200-
appBuilder *AppBuilder[T],
201176
kvFactory store.KVStoreServiceFactory,
202-
headerService header.Service,
203-
eventService event.Service,
204-
) (
205-
appmodulev2.Environment,
206-
store.KVStoreService,
207-
store.MemoryStoreService,
208-
) {
209-
var (
210-
kvService store.KVStoreService = failingStoreService{}
211-
memKvService store.MemoryStoreService = failingStoreService{}
212-
)
213-
177+
storeBuilder root.Builder,
178+
) (store.KVStoreService, store.MemoryStoreService) {
214179
// skips modules that have no store
215-
if !slices.Contains(config.SkipStoreKeys, key.Name()) {
216-
var kvStoreKey string
217-
storeKeyOverride := storeKeyOverride(config, key.Name())
218-
if storeKeyOverride != nil {
219-
kvStoreKey = storeKeyOverride.KvStoreKey
220-
} else {
221-
kvStoreKey = key.Name()
222-
}
180+
if slices.Contains(config.SkipStoreKeys, key.Name()) {
181+
return &failingStoreService{}, &failingStoreService{}
182+
}
183+
var kvStoreKey string
184+
override := storeKeyOverride(config, key.Name())
185+
if override != nil {
186+
kvStoreKey = override.KvStoreKey
187+
} else {
188+
kvStoreKey = key.Name()
189+
}
223190

224-
registerStoreKey(appBuilder, kvStoreKey)
225-
kvService = kvFactory([]byte(kvStoreKey))
191+
storeBuilder.RegisterKey(kvStoreKey)
192+
return kvFactory([]byte(kvStoreKey)), stf.NewMemoryStoreService([]byte(fmt.Sprintf("memory:%s", kvStoreKey)))
193+
}
226194

227-
memStoreKey := fmt.Sprintf("memory:%s", key.Name())
228-
registerStoreKey(appBuilder, memStoreKey)
229-
memKvService = stf.NewMemoryStoreService([]byte(memStoreKey))
195+
func storeKeyOverride(config *runtimev2.Module, moduleName string) *runtimev2.StoreKeyConfig {
196+
for _, cfg := range config.OverrideStoreKeys {
197+
if cfg.ModuleName == moduleName {
198+
return cfg
199+
}
230200
}
201+
return nil
202+
}
231203

232-
env := appmodulev2.Environment{
204+
// ProvideEnvironment provides the environment for keeper modules, while maintaining backward compatibility and provide services directly as well.
205+
func ProvideEnvironment(
206+
logger log.Logger,
207+
key depinject.ModuleKey,
208+
kvService store.KVStoreService,
209+
memKvService store.MemoryStoreService,
210+
headerService header.Service,
211+
eventService event.Service,
212+
) appmodulev2.Environment {
213+
return appmodulev2.Environment{
233214
Logger: logger,
234215
BranchService: stf.BranchService{},
235216
EventService: eventService,
@@ -241,28 +222,13 @@ func ProvideEnvironment[T transaction.Tx](
241222
KVStoreService: kvService,
242223
MemStoreService: memKvService,
243224
}
244-
245-
return env, kvService, memKvService
246-
}
247-
248-
func registerStoreKey[T transaction.Tx](builder *AppBuilder[T], key string) {
249-
builder.app.storeKeys = append(builder.app.storeKeys, key)
250-
}
251-
252-
func storeKeyOverride(config *runtimev2.Module, moduleName string) *runtimev2.StoreKeyConfig {
253-
for _, cfg := range config.OverrideStoreKeys {
254-
if cfg.ModuleName == moduleName {
255-
return cfg
256-
}
257-
}
258-
259-
return nil
260225
}
261226

262227
// DefaultServiceBindings provides default services for the following service interfaces:
263228
// - store.KVStoreServiceFactory
264229
// - header.Service
265230
// - comet.Service
231+
// - event.Service
266232
//
267233
// They are all required. For most use cases these default services bindings should be sufficient.
268234
// Power users (or tests) may wish to provide their own services bindings, in which case they must

0 commit comments

Comments
 (0)