-
Notifications
You must be signed in to change notification settings - Fork 0
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
dig: use our dig fork #2
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
# This script walk through all subdirectories and run go mod tidy if go.mod exists. | ||
# It prints out the directory name if go mod tidy is run. | ||
|
||
set -e | ||
|
||
find . -name "go.mod" | xargs -n1 dirname | while read dir; do | ||
echo "go mod tidy in $dir" | ||
(cd "$dir" && go mod tidy) | ||
done |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
go-mod-tidy-all: | ||
sh ./_tools/go_mod_tidy_all.sh |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,7 +2,8 @@ package xfoundation | |
|
||
import ( | ||
"context" | ||
"fmt" | ||
"github.com/expectedsh/dig" | ||
"github.com/samber/lo" | ||
"go.uber.org/zap" | ||
"os" | ||
"os/signal" | ||
|
@@ -16,38 +17,39 @@ type ( | |
} | ||
|
||
App struct { | ||
Container | ||
Env string | ||
Container *dig.Container | ||
|
||
Env AppEnv | ||
Logger *zap.Logger | ||
Providers []Provider | ||
startHooks []func(ctx context.Context) error | ||
stopHooks []func(ctx context.Context) error | ||
} | ||
|
||
Container struct { | ||
values map[reflect.Type]reflect.Value | ||
} | ||
AppEnv string | ||
) | ||
|
||
const ( | ||
AppEnvProduction = "production" | ||
AppEnvDevelopment = "development" | ||
AppEnvProduction AppEnv = "production" | ||
AppEnvDevelopment AppEnv = "development" | ||
) | ||
|
||
func (app *App) Run() { | ||
app.values = make(map[reflect.Type]reflect.Value) | ||
app.Container = dig.New() | ||
|
||
if app.Env == "" { | ||
app.Env = AppEnvDevelopment | ||
} | ||
|
||
if app.Logger == nil { | ||
if app.Env == AppEnvProduction { | ||
app.Logger = panicOnError(zap.NewProduction()) | ||
app.Logger = lo.Must(zap.NewProduction()) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Use of lo library to just not create code not tested |
||
} else { | ||
app.Logger = panicOnError(zap.NewDevelopment()) | ||
app.Logger = lo.Must(zap.NewDevelopment()) | ||
} | ||
} | ||
app.Provide(app.Logger) | ||
|
||
lo.Must0(app.Provide(ProvideSingleValueFunc(app.Logger))) | ||
|
||
for _, provider := range app.Providers { | ||
log := app.Logger.With(zap.Any("provider", reflect.TypeOf(provider))) | ||
|
@@ -83,40 +85,21 @@ func (app *App) OnStop(hook func(ctx context.Context) error) { | |
app.stopHooks = append(app.stopHooks, hook) | ||
} | ||
|
||
func (c *Container) Provide(v any) { | ||
c.values[reflect.TypeOf(v)] = reflect.ValueOf(v) | ||
func (app *App) Provide(v any) error { | ||
return app.Container.Provide(v) | ||
} | ||
|
||
func (c *Container) Invoke(f any) ([]reflect.Value, error) { | ||
fType := reflect.TypeOf(f) | ||
if fType.Kind() != reflect.Func { | ||
return nil, fmt.Errorf("app.Invoke: invalid func type %v", fType) | ||
} | ||
var dependencies []reflect.Value | ||
for i := 0; i < fType.NumIn(); i++ { | ||
depType := fType.In(i) | ||
value, ok := c.values[depType] | ||
if !ok { | ||
return nil, fmt.Errorf("app.Invoke: cannot find dependency %v", depType) | ||
} | ||
dependencies = append(dependencies, value) | ||
} | ||
|
||
returnValues := reflect.ValueOf(f).Call(dependencies) | ||
if returnValuesLen := len(returnValues); returnValuesLen > 0 { | ||
if err, ok := returnValues[returnValuesLen-1].Interface().(error); ok { | ||
if err != nil { | ||
return nil, err | ||
} | ||
returnValues = returnValues[:returnValuesLen-1] | ||
} | ||
} | ||
return returnValues, nil | ||
func ProvideSingleValueFunc[T any](v T) func() T { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Add utility func to pass single value as function for Provide |
||
return func() T { return v } | ||
} | ||
|
||
func panicOnError[T any](value T, err error) T { | ||
func (a App) Invoke(f any) ([]reflect.Value, error) { | ||
invokeInfo := dig.InvokeInfo{} | ||
|
||
err := a.Container.Invoke(f, dig.FillInvokeInfo(&invokeInfo)) | ||
if err != nil { | ||
panic(err) | ||
return nil, err | ||
} | ||
return value | ||
|
||
return invokeInfo.Outputs, nil | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,7 +3,21 @@ module github.com/caumette-co/x/xfoundation | |
go 1.21.0 | ||
|
||
require ( | ||
go.uber.org/dig v1.17.0 // indirect | ||
github.com/expectedsh/dig v0.0.1-expected | ||
github.com/samber/lo v1.38.1 | ||
go.uber.org/zap v1.25.0 | ||
) | ||
|
||
require ( | ||
go.uber.org/multierr v1.11.0 // indirect | ||
go.uber.org/zap v1.25.0 // indirect | ||
golang.org/x/exp v0.0.0-20220303212507-bbda1eaf7a17 // indirect | ||
) | ||
|
||
// Note on github.com/expectedsh/dig, this is a fork of go.uber.org/dig | ||
// Our fork is needed to add outputs informations for an invoke | ||
// A merge request is opened, waiting for the merge | ||
// When the merge will occur we could remove this fork and use the official dig package | ||
// | ||
// The fork contains two branches : | ||
// - the master branch is the same as the official dig package | ||
// - the expected branch contains the changes we made to add outputs informations for an invoke and replaced go.mod module name | ||
Comment on lines
+16
to
+23
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Our dig is temporary but if the merge request is declined, we can handle that. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,22 @@ | ||
go.uber.org/dig v1.17.0 h1:5Chju+tUvcC+N7N6EV08BJz41UZuO3BmHcN4A287ZLI= | ||
go.uber.org/dig v1.17.0/go.mod h1:rTxpf7l5I0eBTlE6/9RL+lDybC7WFwY2QH55ZSjy1mU= | ||
github.com/benbjohnson/clock v1.3.0 h1:ip6w0uFQkncKQ979AypyG0ER7mqUSBdKLOgAle/AT8A= | ||
github.com/benbjohnson/clock v1.3.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= | ||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= | ||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= | ||
github.com/expectedsh/dig v0.0.1-expected h1:9E1CxIFWjjmkPwslEJgIiMBGW805JNrBTBq1VqiDrMA= | ||
github.com/expectedsh/dig v0.0.1-expected/go.mod h1:TlTW0Xtcx4YY6J6vp9sFGQPDDxCUC7UJIwUOfieEM8g= | ||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= | ||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= | ||
github.com/samber/lo v1.38.1 h1:j2XEAqXKb09Am4ebOg31SpvzUTTs6EN3VfgeLUhPdXM= | ||
github.com/samber/lo v1.38.1/go.mod h1:+m/ZKRl6ClXCE2Lgf3MsQlWfh4bn1bz6CXEOxnEXnEA= | ||
github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= | ||
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= | ||
go.uber.org/goleak v1.2.0 h1:xqgm/S+aQvhWFTtR0XK3Jvg7z8kGV8P4X14IzwN3Eqk= | ||
go.uber.org/goleak v1.2.0/go.mod h1:XJYK+MuIchqpmGmUSAzotztawfKvYLUIgg7guXrwVUo= | ||
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= | ||
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= | ||
go.uber.org/zap v1.25.0 h1:4Hvk6GtkucQ790dqmj7l1eEnRdKm3k3ZUrUMS2d5+5c= | ||
go.uber.org/zap v1.25.0/go.mod h1:JIAUzQIH94IC4fOJQm7gMmBJP5k7wQfdcnYdPoEXJYk= | ||
golang.org/x/exp v0.0.0-20220303212507-bbda1eaf7a17 h1:3MTrJm4PyNL9NBqvYDSj3DHl46qQakyfqfWo4jgfaEM= | ||
golang.org/x/exp v0.0.0-20220303212507-bbda1eaf7a17/go.mod h1:lgLbSvA5ygNOMpwM/9anMpWVlVJ7Z+cHWq/eFuinpGE= | ||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= | ||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,7 @@ | ||
package xweb | ||
|
||
import ( | ||
"fmt" | ||
"github.com/caumette-co/x/xfoundation" | ||
"github.com/go-chi/chi" | ||
"go.uber.org/zap" | ||
|
@@ -21,9 +22,10 @@ func newRouter(app *xfoundation.App) *Router { | |
} | ||
|
||
func (r *Router) Route(method, path string, handler any) { | ||
httpHandler := r.getHttpHandler(handler) | ||
if httpHandler == nil { | ||
httpHandler, err := r.getHttpHandler(handler) | ||
if err != nil { | ||
r.app.Logger.Error("invalid handler", | ||
zap.Error(err), | ||
zap.String("method", method), | ||
zap.String("path", path), | ||
zap.String("handler", reflect.TypeOf(handler).String()), | ||
|
@@ -57,18 +59,18 @@ func (r *Router) Delete(path string, handler any) { | |
r.Route(http.MethodDelete, path, handler) | ||
} | ||
|
||
func (r *Router) getHttpHandler(handler any) http.Handler { | ||
func (r *Router) getHttpHandler(handler any) (http.Handler, error) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Add error return type here |
||
handlerType := reflect.TypeOf(handler) | ||
if handlerType.Kind() != reflect.Func { | ||
return nil | ||
return nil, fmt.Errorf("handler is not a function") | ||
} | ||
|
||
if handlerType.NumOut() == 1 && handlerType.Out(0).Kind() == reflect.Func { | ||
values, err := r.app.Invoke(handler) | ||
if err != nil { | ||
return nil | ||
return nil, fmt.Errorf("invoke: %w", err) | ||
} else if len(values) != 1 { | ||
return nil | ||
return nil, fmt.Errorf("invoke: expected at least 1 value, got %d", len(values)) | ||
} | ||
handler = values[0].Interface() | ||
handlerType = reflect.TypeOf(handler) | ||
|
@@ -80,7 +82,7 @@ func (r *Router) getHttpHandler(handler any) http.Handler { | |
|
||
value, ok := handler.(http.Handler) | ||
if !ok { | ||
return nil | ||
return nil, fmt.Errorf("handler is not a http.Handler") | ||
} | ||
return value | ||
return value, nil | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add type alias string for AppEnv (for convenience)