Skip to content

Commit

Permalink
Merge branch 'main' of github.com:cosmos/cosmos-sdk into aaronc/11907…
Browse files Browse the repository at this point in the history
…-container-build
  • Loading branch information
aaronc committed May 10, 2022
2 parents 30ca967 + 624539a commit 96248be
Show file tree
Hide file tree
Showing 4 changed files with 60 additions and 34 deletions.
30 changes: 26 additions & 4 deletions container/container.go
Original file line number Diff line number Diff line change
Expand Up @@ -133,19 +133,26 @@ func (c *container) getResolver(typ reflect.Type) (resolver, error) {
return c.resolvers[typ], nil
}

var stringType = reflect.TypeOf("")

func (c *container) addNode(provider *ProviderDescriptor, key *moduleKey) (interface{}, error) {
providerGraphNode, err := c.locationGraphNode(provider.Location, key)
if err != nil {
return nil, err
}

hasModuleKeyParam := false
hasOwnModuleKeyParam := false
for _, in := range provider.Inputs {
typ := in.Type
if typ == moduleKeyType {
hasModuleKeyParam = true
}

if typ == ownModuleKeyType {
hasOwnModuleKeyParam = true
}

if isAutoGroupType(typ) {
return nil, fmt.Errorf("auto-group type %v can't be used as an input parameter", typ)
} else if isOnePerModuleType(typ) {
Expand All @@ -170,7 +177,7 @@ func (c *container) addNode(provider *ProviderDescriptor, key *moduleKey) (inter
c.addGraphEdge(typeGraphNode, providerGraphNode)
}

if key != nil || !hasModuleKeyParam {
if !hasModuleKeyParam {
c.logf("Registering %s", provider.Location.String())
c.indentLogger()
defer c.dedentLogger()
Expand Down Expand Up @@ -214,9 +221,10 @@ func (c *container) addNode(provider *ProviderDescriptor, key *moduleKey) (inter
}

vr = &simpleResolver{
node: sp,
typ: typ,
graphNode: typeGraphNode,
node: sp,
typ: typ,
graphNode: typeGraphNode,
idxInValues: i,
}
c.resolvers[typ] = vr
}
Expand All @@ -226,6 +234,11 @@ func (c *container) addNode(provider *ProviderDescriptor, key *moduleKey) (inter

return sp, nil
} else {
if hasOwnModuleKeyParam {
return nil, errors.Errorf("%T and %T must not be declared as dependencies on the same provided",
ModuleKey{}, OwnModuleKey{})
}

c.logf("Registering module-scoped provider: %s", provider.Location.String())
c.indentLogger()
defer c.dedentLogger()
Expand Down Expand Up @@ -313,6 +326,15 @@ func (c *container) resolve(in ProviderInput, moduleKey *moduleKey, caller Locat
return reflect.ValueOf(ModuleKey{moduleKey}), nil
}

if in.Type == ownModuleKeyType {
if moduleKey == nil {
return reflect.Value{}, errors.Errorf("trying to resolve %T for %s but not inside of any module's scope", moduleKey, caller)
}
c.logf("Providing OwnModuleKey %s", moduleKey.name)
markGraphNodeAsUsed(typeGraphNode)
return reflect.ValueOf(OwnModuleKey{moduleKey}), nil
}

vr, err := c.getResolver(in.Type)
if err != nil {
return reflect.Value{}, err
Expand Down
38 changes: 17 additions & 21 deletions container/container_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,13 @@ type KVStoreKey struct {
name string
}

type ModuleKey string

type MsgClientA struct {
key ModuleKey
key string
}

type KeeperA struct {
key KVStoreKey
key KVStoreKey
name string
}

type KeeperB struct {
Expand All @@ -46,18 +45,14 @@ func ProvideKVStoreKey(moduleKey container.ModuleKey) KVStoreKey {
return KVStoreKey{name: moduleKey.Name()}
}

func ProvideModuleKey(moduleKey container.ModuleKey) (ModuleKey, error) {
return ModuleKey(moduleKey.Name()), nil
}

func ProvideMsgClientA(_ container.ModuleKey, key ModuleKey) MsgClientA {
return MsgClientA{key}
func ProvideMsgClientA(key container.ModuleKey) MsgClientA {
return MsgClientA{key.Name()}
}

type ModuleA struct{}

func (ModuleA) Provide(key KVStoreKey) (KeeperA, Handler, Command) {
return KeeperA{key}, Handler{}, Command{}
func (ModuleA) Provide(key KVStoreKey, moduleKey container.OwnModuleKey) (KeeperA, Handler, Command) {
return KeeperA{key: key, name: container.ModuleKey(moduleKey).Name()}, Handler{}, Command{}
}

type ModuleB struct{}
Expand All @@ -76,7 +71,7 @@ type BProvides struct {
Commands []Command
}

func (ModuleB) Provide(dependencies BDependencies, _ container.ModuleKey) (BProvides, Handler, error) {
func (ModuleB) Provide(dependencies BDependencies) (BProvides, Handler, error) {
return BProvides{
KeeperB: KeeperB{
key: dependencies.Key,
Expand All @@ -96,11 +91,8 @@ func TestScenario(t *testing.T) {
require.NoError(t,
container.Build(
container.Options(
container.Provide(
ProvideKVStoreKey,
ProvideModuleKey,
ProvideMsgClientA,
),
container.Provide(ProvideMsgClientA),
container.ProvideInModule("runtime", ProvideKVStoreKey),
container.ProvideInModule("a", wrapMethod0(ModuleA{})),
container.ProvideInModule("b", wrapMethod0(ModuleB{})),
),
Expand All @@ -115,7 +107,8 @@ func TestScenario(t *testing.T) {
require.Equal(t, Handler{}, handlers["b"])
require.Len(t, commands, 3)
require.Equal(t, KeeperA{
key: KVStoreKey{name: "a"},
key: KVStoreKey{name: "a"},
name: "a",
}, a)
require.Equal(t, KeeperB{
key: KVStoreKey{name: "b"},
Expand Down Expand Up @@ -506,6 +499,7 @@ type TestOutput struct {
container.Out

X string
Y int64
}

func TestStructArgs(t *testing.T) {
Expand All @@ -527,13 +521,15 @@ func TestStructArgs(t *testing.T) {
require.Equal(t, 1.3, input.Y)

var x string
var y int64
require.NoError(t, container.Build(
container.Provide(func() (TestOutput, error) {
return TestOutput{X: "A"}, nil
return TestOutput{X: "A", Y: -10}, nil
}),
&x,
&x, &y,
))
require.Equal(t, "A", x)
require.Equal(t, int64(-10), y)

require.Error(t, container.Build(
container.Provide(func() (TestOutput, error) {
Expand Down
23 changes: 15 additions & 8 deletions container/module_key.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,17 @@ import (

// ModuleKey is a special type used to scope a provider to a "module".
//
// Special module-scoped providers can be used with Provide by declaring a
// provider with an input parameter of type ModuleKey. These providers
// may construct a unique value of a dependency for each module and will
// be called at most once per module.
// Special module-scoped providers can be used with Provide and ProvideInModule
// by declaring a provider with an input parameter of type ModuleKey. These
// providers may construct a unique value of a dependency for each module and
// will be called at most once per module.
//
// Providers passed to ProvideInModule can also declare an input parameter
// of type ModuleKey to retrieve their module key but these providers will be
// called at most once.
// When being used with ProvideInModule, the provider will not receive its
// own ModuleKey but rather the key of the module requesting the dependency
// so that modules can provide module-scoped dependencies to other modules.
//
// In order for a module to retrieve their own module key they can define
// a provider which requires the OwnModuleKey type and DOES NOT require ModuleKey.
type ModuleKey struct {
*moduleKey
}
Expand All @@ -28,4 +31,8 @@ func (k ModuleKey) Name() string {

var moduleKeyType = reflect.TypeOf(ModuleKey{})

var stringType = reflect.TypeOf("")
// OwnModuleKey is a type which can be used in a module to retrieve its own
// ModuleKey. It MUST NOT be used together with a ModuleKey dependency.
type OwnModuleKey ModuleKey

var ownModuleKeyType = reflect.TypeOf((*OwnModuleKey)(nil)).Elem()
3 changes: 2 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@ require (
sigs.k8s.io/yaml v1.3.0
)

require github.com/google/uuid v1.3.0

require (
cloud.google.com/go v0.100.2 // indirect
cloud.google.com/go/compute v1.5.0 // indirect
Expand Down Expand Up @@ -93,7 +95,6 @@ require (
github.com/golang/snappy v0.0.4 // indirect
github.com/google/btree v1.0.1 // indirect
github.com/google/orderedcode v0.0.1 // indirect
github.com/google/uuid v1.3.0 // indirect
github.com/googleapis/gax-go/v2 v2.3.0 // indirect
github.com/gorilla/websocket v1.5.0 // indirect
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 // indirect
Expand Down

0 comments on commit 96248be

Please sign in to comment.