Skip to content

Commit

Permalink
minor changes to MVC, see HISTORY.md#Next for more
Browse files Browse the repository at this point in the history
  • Loading branch information
kataras committed Aug 21, 2023
1 parent 79404f9 commit 9f53d15
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 4 deletions.
6 changes: 6 additions & 0 deletions HISTORY.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,12 @@ Developers are not forced to upgrade if they don't really need it. Upgrade whene

Changes apply to `main` branch.

- Add optional `Singleton() bool` method to controllers to mark them as singleton, will panic with a specific error if a controller expects dynamic dependencies. This behavior is idendical to the app-driven `app.EnsureStaticBindings()`.

- Non-zero fields of a controller that are marked as ignored, with `ignore:"true"` field tag, they are not included in the dependencies at all now.

- Re-add error log on context rich write (e.g. JSON) failures when the application is running under debug mode (with `app.Logger().SetLevel("debug")`) and there is no a registered context error handler at place.

- `master` branch finally renamed to `main`. Don't worry GitHub will still navigate any `master` request to `main` automatically. Examples, Documentation and other Pages are refactored too.

# Sat, 12 Aug 2023 | v12.2.4
Expand Down
7 changes: 5 additions & 2 deletions context/context.go
Original file line number Diff line number Diff line change
Expand Up @@ -4213,6 +4213,9 @@ func (ctx *Context) handleContextError(err error) {
if errHandler := ctx.app.GetContextErrorHandler(); errHandler != nil {
errHandler.HandleContextError(ctx, err)
} else {
if ctx.IsDebug() {
ctx.app.Logger().Error(err)
}
ctx.StatusCode(http.StatusInternalServerError)
}

Expand Down Expand Up @@ -4258,8 +4261,8 @@ func (ctx *Context) JSON(v interface{}, opts ...JSON) (err error) {
}

if err = ctx.writeJSON(v, options); err != nil {
// if no options are given or OmitErrorHandler is true
// then do call the error handler (which may lead to a cycle).
// if no options are given or OmitErrorHandler is false
// then call the error handler (which may lead to a cycle if the error handler fails to write JSON too).
if !options.OmitErrorHandler {
ctx.handleContextError(err)
}
Expand Down
3 changes: 3 additions & 0 deletions hero/reflect.go
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,9 @@ func lookupFields(elem reflect.Value, skipUnexported bool, onlyZeros bool, paren
func lookupNonZeroFieldValues(elem reflect.Value) (nonZeroFields []reflect.StructField) {
fields, _ := lookupFields(elem, true, false, nil)
for _, f := range fields {
if structFieldIgnored(f) {
continue // re-check here for ignored struct fields so we don't include them on dependencies. Non-zeroes fields can be static, even if they are functions.
}
if fieldVal := elem.FieldByIndex(f.Index); goodVal(fieldVal) && !isZero(fieldVal) {
/* && f.Type.Kind() == reflect.Ptr &&*/
nonZeroFields = append(nonZeroFields, f)
Expand Down
31 changes: 29 additions & 2 deletions hero/struct.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,15 +43,38 @@ type Struct struct {
Singleton bool
}

type singletonStruct interface {
Singleton() bool
}

func isMarkedAsSingleton(structPtr any) bool {
if sing, ok := structPtr.(singletonStruct); ok && sing.Singleton() {
return true
}

return false
}

func makeStruct(structPtr interface{}, c *Container, partyParamsCount int) *Struct {
v := valueOf(structPtr)
typ := v.Type()
if typ.Kind() != reflect.Ptr || indirectType(typ).Kind() != reflect.Struct {
panic("binder: struct: should be a pointer to a struct value")
}

isSingleton := isMarkedAsSingleton(structPtr)

disablePayloadAutoBinding := c.DisablePayloadAutoBinding
enableStructDependents := c.EnableStructDependents
disableStructDynamicBindings := c.DisableStructDynamicBindings
if isSingleton {
disablePayloadAutoBinding = true
enableStructDependents = false
disableStructDynamicBindings = true
}

// get struct's fields bindings.
bindings := getBindingsForStruct(v, c.Dependencies, c.MarkExportedFieldsAsRequired, c.DisablePayloadAutoBinding, c.EnableStructDependents, c.DependencyMatcher, partyParamsCount, c.Sorter)
bindings := getBindingsForStruct(v, c.Dependencies, c.MarkExportedFieldsAsRequired, disablePayloadAutoBinding, enableStructDependents, c.DependencyMatcher, partyParamsCount, c.Sorter)

// length bindings of 0, means that it has no fields or all mapped deps are static.
// If static then Struct.Acquire will return the same "value" instance, otherwise it will create a new one.
Expand All @@ -73,14 +96,18 @@ func makeStruct(structPtr interface{}, c *Container, partyParamsCount int) *Stru

elem.FieldByIndex(b.Input.StructFieldIndex).Set(input)
} else if !b.Dependency.Static {
if c.DisableStructDynamicBindings {
if disableStructDynamicBindings {
panic(fmt.Sprintf("binder: DisableStructDynamicBindings setting is set to true: dynamic binding found: %s", b.String()))
}

singleton = false
}
}

if isSingleton && !singleton {
panic(fmt.Sprintf("binder: Singleton setting is set to true but struct has dynamic bindings: %s", typ))
}

s := &Struct{
ptrValue: v,
ptrType: typ,
Expand Down

0 comments on commit 9f53d15

Please sign in to comment.