From ed5c82beaa0ad5bcee6654967150367ae5adb5ba Mon Sep 17 00:00:00 2001 From: reasno Date: Tue, 18 Jan 2022 22:31:56 +0800 Subject: [PATCH 1/3] chore: upgrade koanf to v1.4.0 --- go.mod | 7 ++++--- go.sum | 20 +++++++++++++++++--- otgorm/otgorm_test.go | 12 +++++++----- 3 files changed, 28 insertions(+), 11 deletions(-) diff --git a/go.mod b/go.mod index 93d5a14f..c9e85359 100644 --- a/go.mod +++ b/go.mod @@ -5,6 +5,7 @@ go 1.17 require ( github.com/ClickHouse/clickhouse-go v1.4.5 // indirect github.com/aws/aws-sdk-go v1.40.45 + github.com/felixge/httpsnoop v1.0.1 github.com/fsnotify/fsnotify v1.4.9 github.com/gabriel-vasile/mimetype v1.1.2 github.com/go-gormigrate/gormigrate/v2 v2.0.0 @@ -17,7 +18,7 @@ require ( github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 github.com/hashicorp/go-version v1.3.0 // indirect github.com/heptiolabs/healthcheck v0.0.0-20180807145615-6ff867650f40 - github.com/knadh/koanf v0.15.0 + github.com/knadh/koanf v1.4.0 github.com/mitchellh/mapstructure v1.4.2 github.com/oklog/run v1.1.0 github.com/olivere/elastic/v7 v7.0.22 @@ -50,8 +51,6 @@ require ( gorm.io/gorm v1.21.10 ) -require github.com/felixge/httpsnoop v1.0.1 - require ( github.com/beorn7/perks v1.0.1 // indirect github.com/cespare/xxhash/v2 v2.1.2 // indirect @@ -76,6 +75,8 @@ require ( github.com/mailru/easyjson v0.7.6 // indirect github.com/mattn/go-sqlite3 v1.14.5 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect + github.com/mitchellh/copystructure v1.2.0 // indirect + github.com/mitchellh/reflectwalk v1.0.2 // indirect github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e // indirect github.com/pierrec/lz4 v2.6.0+incompatible // indirect github.com/pmezard/go-difflib v1.0.0 // indirect diff --git a/go.sum b/go.sum index 8fe17dba..5c0e2660 100644 --- a/go.sum +++ b/go.sum @@ -74,7 +74,16 @@ github.com/aws/aws-sdk-go v1.40.45 h1:QN1nsY27ssD/JmW4s83qmSb+uL6DG4GmCDzjmJB4xU github.com/aws/aws-sdk-go v1.40.45/go.mod h1:585smgzpB/KqRA+K3y/NL/oYRqQvpNJYvLm+LY1U59Q= github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g= github.com/aws/aws-sdk-go-v2 v1.9.1/go.mod h1:cK/D0BBs0b/oWPIcX/Z/obahJK1TT7IPVjy53i/mX/4= +github.com/aws/aws-sdk-go-v2 v1.9.2/go.mod h1:cK/D0BBs0b/oWPIcX/Z/obahJK1TT7IPVjy53i/mX/4= +github.com/aws/aws-sdk-go-v2/config v1.8.3/go.mod h1:4AEiLtAb8kLs7vgw2ZV3p2VZ1+hBavOc84hqxVNpCyw= +github.com/aws/aws-sdk-go-v2/credentials v1.4.3/go.mod h1:FNNC6nQZQUuyhq5aE5c7ata8o9e4ECGmS4lAXC7o1mQ= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.6.0/go.mod h1:gqlclDEZp4aqJOancXK6TN24aKhT0W0Ae9MHk3wzTMM= +github.com/aws/aws-sdk-go-v2/internal/ini v1.2.4/go.mod h1:ZcBrrI3zBKlhGFNYWvju0I3TR93I7YIgAfy82Fh4lcQ= +github.com/aws/aws-sdk-go-v2/service/appconfig v1.4.2/go.mod h1:FZ3HkCe+b10uFZZkFdvf98LHW21k49W8o8J366lqVKY= github.com/aws/aws-sdk-go-v2/service/cloudwatch v1.8.1/go.mod h1:CM+19rL1+4dFWnOQKwDc7H1KwXTz+h61oUSHyhV0b3o= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.3.2/go.mod h1:72HRZDLMtmVQiLG2tLfQcaWLCssELvGl+Zf2WVxMmR8= +github.com/aws/aws-sdk-go-v2/service/sso v1.4.2/go.mod h1:NBvT9R1MEF+Ud6ApJKM0G+IkPchKS7p7c2YPKwHmBOk= +github.com/aws/aws-sdk-go-v2/service/sts v1.7.2/go.mod h1:8EzeIqfWt2wWT4rJVu3f21TfrhJ8AEMzVybRNSb/b4g= github.com/aws/smithy-go v1.8.0/go.mod h1:SObp3lf9smib00L/v3U2eAKG8FyQ7iLrJnQiAmR5n+E= github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8= github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= @@ -481,8 +490,8 @@ github.com/klauspost/compress v1.9.8/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0 github.com/klauspost/compress v1.13.4/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg= github.com/klauspost/compress v1.13.6 h1:P76CopJELS0TiO2mebmnzgWaajssP/EszplttgQxcgc= github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= -github.com/knadh/koanf v0.15.0 h1:HMm8cJZZIokMn5ETu9Exut1jQhfu1dm3b0TZedvhSVo= -github.com/knadh/koanf v0.15.0/go.mod h1:Ut3d4JaTRZYfO5a0wdYIGE+oyGaGFo4vXQ3ZvaSWxNc= +github.com/knadh/koanf v1.4.0 h1:/k0Bh49SqLyLNfte9r6cvuZWrApOQhglOmhIU3L/zDw= +github.com/knadh/koanf v1.4.0/go.mod h1:1cfH5223ZeZUOs8FU2UdTmaNfHpqgtjV0+NHjRO43gs= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= @@ -539,6 +548,8 @@ github.com/minio/highwayhash v1.0.2/go.mod h1:BQskDq+xkJ12lmlUUi7U0M5Swg3EWR+dLT github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= github.com/mitchellh/cli v1.1.0/go.mod h1:xcISNoH86gajksDmfB23e/pu+B+GeFRMYmoHXxx3xhI= github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw= +github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= +github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-testing-interface v0.0.0-20171004221916-a61a99592b77/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= @@ -548,10 +559,12 @@ github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS4 github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= -github.com/mitchellh/mapstructure v1.2.2/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/mapstructure v1.4.2 h1:6h7AQ0yhTcIsmFmnAwQls75jp2Gzs4iB8W7pjMO+rqo= github.com/mitchellh/mapstructure v1.4.2/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= +github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= +github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= @@ -575,6 +588,7 @@ github.com/nats-io/nkeys v0.3.0/go.mod h1:gvUNGjVcM2IPr5rCsRsC6Wb3Hr2CQAm08dsxtV github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= +github.com/npillmayer/nestext v0.1.3/go.mod h1:h2lrijH8jpicr25dFY+oAJLyzlya6jhnuG+zWp9L0Uk= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= diff --git a/otgorm/otgorm_test.go b/otgorm/otgorm_test.go index d91ea88e..b5e9c370 100644 --- a/otgorm/otgorm_test.go +++ b/otgorm/otgorm_test.go @@ -26,12 +26,14 @@ func TestHook(t *testing.T) { }, drivers: map[string]func(dsn string) gorm.Dialector{"sqlite": sqlite.Open}, })(factoryIn{ - Conf: config.MapAdapter{"gorm": map[string]databaseConf{ - "default": { - Database: "sqlite", - Dsn: ":memory:", + Conf: config.MapAdapter{ + "gorm": map[string]interface{}{ + "default": map[string]interface{}{ + "database": "sqlite", + "dsn": ":memory:", + }, }, - }}, + }, Logger: log.NewNopLogger(), Tracer: tracer, }) From 1bde65534556807627c9b51ebe10cf5557f2e04b Mon Sep 17 00:00:00 2001 From: Reasno Date: Thu, 20 Jan 2022 10:37:58 +0800 Subject: [PATCH 2/3] feat: allow module field injection --- c.go | 46 ++++++++++++++++++++++++---------------------- c_test.go | 41 ++++++++++++++++++++++++++++++++++++++++- example_test.go | 22 +++++++++++++++++++++- 3 files changed, 85 insertions(+), 24 deletions(-) diff --git a/c.go b/c.go index cf13d37b..6a12c30d 100644 --- a/c.go +++ b/c.go @@ -196,33 +196,35 @@ func Default(opts ...CoreOption) *C { return c } -// AddModule adds one or more module(s) to the core. If any of the variadic -// arguments is an error, it would panic. This makes it easy to consume -// constructors directly, so instead of writing: -// -// component, err := components.New() -// if err != nil { -// panic(err) -// } -// c.AddModule(component) -// -// You can write: -// -// c.AddModule(component.New()) +// AddModule adds a module to the core. // // A Module is a group of functionality. It must provide some runnable stuff: // http handlers, grpc handlers, cron jobs, one-time command, etc. -func (c *C) AddModule(modules ...interface{}) { - for i := range modules { - switch x := modules[i].(type) { - case error: - panic(x) - case func(): - c.Container.AddModule(cleanup(x)) - default: - c.Container.AddModule(x) +// +// Optionally if the module embeds di.In, its fields will be injected by DI +// container. The semantics of injection follows the same rule of dig.Invoke. +// Note that the module added in this way will not retain any original field +// values, i.e. the module will only contain fields populated by DI container. +func (c *C) AddModule(modules interface{}) { + t := reflect.TypeOf(modules) + if t.Kind() == reflect.Ptr && dig.IsIn(t.Elem()) { + err := di.IntoPopulator(c.di).Populate(modules) + if err != nil { + panic(err) } + c.Container.AddModule(modules) + return + } + if dig.IsIn(t) { + copy := reflect.New(t) + err := di.IntoPopulator(c.di).Populate(copy.Interface()) + if err != nil { + panic(err) + } + c.Container.AddModule(copy.Elem().Interface()) + return } + c.Container.AddModule(modules) } // Provide adds dependencies provider to the core. Note the dependency provider diff --git a/c_test.go b/c_test.go index c27f7297..b1f01935 100644 --- a/c_test.go +++ b/c_test.go @@ -191,7 +191,7 @@ func TestC_cleanup(t *testing.T) { } }}) c.Invoke(func(_ struct{}) {}) - c.AddModule(func() func() { + c.AddModule(func() closer { return func() { moduleCleanupCalled = true } @@ -216,3 +216,42 @@ func TestContainer_Shutdown(t *testing.T) { container.Shutdown() assert.Equal(t, 1, seq) } + +func TestC_AddModule(t *testing.T) { + type Module struct { + di.In + Int int + Float float64 `optional:"true"` + } + for _, c := range []struct { + name string + module interface{} + assertion func(t *testing.T, c *C) + }{ + { + "di.In", + Module{Float: 2.0}, + func(t *testing.T, c *C) { + assert.Equal(t, 1, c.Modules()[0].(Module).Int) + assert.Equal(t, 0.0, c.Modules()[0].(Module).Float) + }, + }, + { + "*di.In", + &Module{Float: 2.0}, + func(t *testing.T, c *C) { + assert.Equal(t, 1, c.Modules()[0].(*Module).Int) + assert.Equal(t, 0.0, c.Modules()[0].(*Module).Float) + }, + }, + } { + t.Run(c.name, func(t *testing.T) { + cc := New() + cc.Provide(di.Deps{func() int { + return 1 + }}) + cc.AddModule(c.module) + c.assertion(t, cc) + }) + } +} diff --git a/example_test.go b/example_test.go index ea3e4346..bcabc757 100644 --- a/example_test.go +++ b/example_test.go @@ -6,11 +6,13 @@ import ( "fmt" "io/ioutil" "net/http" + "os" "strings" "time" "github.com/DoNewsCode/core" "github.com/DoNewsCode/core/di" + "github.com/go-kit/log" "github.com/gorilla/mux" "github.com/knadh/koanf/parsers/json" "github.com/knadh/koanf/providers/basicflag" @@ -29,7 +31,7 @@ func ExampleC_AddModuleFunc() { // core.cleanup core_test.Foo } -func ExampleC_AddModule() { +func ExampleC_AddModule_simple() { type Foo struct{} c := core.New() c.AddModule(Foo{}) @@ -38,6 +40,24 @@ func ExampleC_AddModule() { // core_test.Foo } +func ExampleC_AddModule_inject() { + type Foo struct { + di.In + Logger log.Logger + } + var f Foo + c := core.New() + c.Provide(di.Deps{func() log.Logger { + return log.NewLogfmtLogger(os.Stdout) + }}) + // If the module embeds di.In (directly or indirectly via pointer), then DI will + // populate its fields. + c.AddModule(&f) + f.Logger.Log("msg", "hello") + // Output: + // msg=hello +} + func ExampleC_Provide() { type Foo struct { Value string From cb1abd6d083b410179136578c48985e606be3c60 Mon Sep 17 00:00:00 2001 From: Trock <35254251+GGXXLL@users.noreply.github.com> Date: Thu, 20 Jan 2022 15:40:53 +0800 Subject: [PATCH 3/3] fix: strict variable name :beers: --- c.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/c.go b/c.go index e2be88e3..22860fa2 100644 --- a/c.go +++ b/c.go @@ -207,14 +207,14 @@ func Default(opts ...CoreOption) *C { // container. The semantics of injection follows the same rule of dig.Invoke. // Note that the module added in this way will not retain any original field // values, i.e. the module will only contain fields populated by DI container. -func (c *C) AddModule(modules interface{}) { - t := reflect.TypeOf(modules) +func (c *C) AddModule(module interface{}) { + t := reflect.TypeOf(module) if t.Kind() == reflect.Ptr && dig.IsIn(t.Elem()) { - err := di.IntoPopulator(c.di).Populate(modules) + err := di.IntoPopulator(c.di).Populate(module) if err != nil { panic(err) } - c.Container.AddModule(modules) + c.Container.AddModule(module) return } if dig.IsIn(t) { @@ -226,7 +226,7 @@ func (c *C) AddModule(modules interface{}) { c.Container.AddModule(copy.Elem().Interface()) return } - c.Container.AddModule(modules) + c.Container.AddModule(module) } // Provide adds dependencies provider to the core. Note the dependency provider