Skip to content
This repository has been archived by the owner on Oct 8, 2024. It is now read-only.

Commit

Permalink
Merge pull request #33 from bancodobrasil/feat/error-handling
Browse files Browse the repository at this point in the history
feat: add error handling
  • Loading branch information
ralphg6 authored Mar 30, 2022
2 parents 33af2ae + 8b59733 commit 1bf7a13
Show file tree
Hide file tree
Showing 5 changed files with 103 additions and 28 deletions.
10 changes: 10 additions & 0 deletions config/config.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package config

import (
"fmt"
"net/http"
"os"
"strings"
Expand All @@ -26,6 +27,8 @@ type Config struct {

var config = &Config{}

var loaded = false

//LoadConfig ...
func LoadConfig() (err error) {
viper.AddConfigPath("./")
Expand Down Expand Up @@ -76,5 +79,12 @@ func LoadConfig() (err error) {

//GetConfig ...
func GetConfig() *Config {
if !loaded {
err := LoadConfig()
loaded = true
if err != nil {
panic(fmt.Sprintf("load config error: %s", err))
}
}
return config
}
8 changes: 6 additions & 2 deletions services/rulles.go
Original file line number Diff line number Diff line change
Expand Up @@ -125,8 +125,12 @@ func (s Eval) Eval(ctx *types.Context, knowledgeBase *ast.KnowledgeBase) (*types
return nil, err
}

log.Print("Context:\n\t", ctx.GetEntries(), "\n\n")
log.Print("Features:\n\t", result.GetFeatures(), "\n\n")
if ctx.Has("errors") && len(ctx.GetMap("errors").GetEntries()) > 0 {
result.Put("errors", ctx.GetMap("errors").GetEntries())
}

log.Debug("Context:\n\t", ctx.GetEntries(), "\n\n")
log.Debug("Features:\n\t", result.GetFeatures(), "\n\n")

evalMutex.Unlock()

Expand Down
29 changes: 23 additions & 6 deletions types/context.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,16 @@ func (c *Context) load(param string) interface{} {
}

func (c *Context) loadImpl(param string) interface{} {
defer func() {
r := recover()
if r == nil {
return
}
if !c.Has("errors") {
c.Put("errors", NewTypedMap())
}
c.GetMap("errors").AddItem(param, r)
}()
remote, ok := c.RemoteLoadeds[param]
if !ok {
panic("The param it's not registry as remote loaded")
Expand Down Expand Up @@ -116,14 +126,15 @@ func (c *Context) GetEntry(param string) interface{} {
}

type resolveInputV1 struct {
Resolver string `json:"resolver"`
Context map[string]interface{} `json:"context"`
Load []string `json:"load"`
Resolver string `json:"resolver,omitempty"`
Context map[string]interface{} `json:"context,omitempty"`
Load []string `json:"load,omitempty"`
}

type resolveOutputV1 struct {
Context map[string]interface{} `json:"context"`
Errors map[string]interface{} `json:"errors"`
Context map[string]interface{} `json:"context,omitempty"`
Errors map[string]interface{} `json:"errors,omitempty"`
Error string `json:"error,omitempty"`
}

func (c *Context) resolve(resolver string, param string) interface{} {
Expand Down Expand Up @@ -155,6 +166,8 @@ func (c *Context) resolveImpl(resolver string, param string) interface{} {
panic("error on encode input")
}

log.Debugf("Resolving with '%s' decoded: %v", url, buf.String())

req, err := http.NewRequest("POST", url, &buf)
if err != nil {
panic("error on create Request")
Expand All @@ -173,7 +186,7 @@ func (c *Context) resolveImpl(resolver string, param string) interface{} {
panic("error on read the body")
}

log.Infof("Resolving with '%s': %v > %s", url, input, string(data))
log.Infof("Resolved with '%s': %v > %s", url, input, string(data))

output := resolveOutputV1{}
err = json.Unmarshal(data, &output)
Expand All @@ -185,5 +198,9 @@ func (c *Context) resolveImpl(resolver string, param string) interface{} {
panic(fmt.Sprintf("%s", output.Errors))
}

if output.Error != "" {
panic(output.Error)
}

return output.Context[param]
}
77 changes: 58 additions & 19 deletions types/context_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,16 +106,15 @@ func TestLoad(t *testing.T) {

// TestLoadPanicNotRemoted start
func TestLoadPanicNotRemoted(t *testing.T) {
defer func() {
r := recover()
if r != "The param it's not registry as remote loaded" {
t.Error("The panic message it's not throwed")
}
}()

ctx := NewContext()
ctx.load("myRemoteParam")

got := ctx.GetMap("errors").GetSlice("myRemoteParam")
expected := []interface{}{"The param it's not registry as remote loaded"}

if !reflect.DeepEqual(got, expected) {
t.Error("The error message it's not throwed")
}
}

// TestLoadPanicNotRemoted stop
Expand Down Expand Up @@ -440,12 +439,6 @@ func (m *MockHTTPClientResponseDecodeMoreThenOneError) Do(req *http.Request) (*h
m.t.Error("The loads dont match each other")
}

output := resolveOutputV1{}
err = json.Unmarshal(data, &output)
if err != nil {
panic(err.Error())
}

stringReader := strings.NewReader(`{
"errors": {
"myparam": "myerror"
Expand Down Expand Up @@ -512,12 +505,6 @@ func (m *MockHTTPClient) Do(req *http.Request) (*http.Response, error) {
m.t.Error("The loads dont match each other")
}

output := resolveOutputV1{}
err = json.Unmarshal(data, &output)
if err != nil {
panic(err.Error())
}

stringReader := strings.NewReader(`{
"context": {
"param_name": "myresult"
Expand Down Expand Up @@ -546,3 +533,55 @@ func TestResolve(t *testing.T) {
}

// TestResolve stop

// TestResolveUnexpectedError start
type MockHTTPClientUnexpectedError struct {
http.Client
t *testing.T
}

func (m *MockHTTPClientUnexpectedError) Do(req *http.Request) (*http.Response, error) {
data, err := io.ReadAll(req.Body)
if err != nil {
panic(err.Error())
}

input := resolveInputV1{}
err = json.Unmarshal(data, &input)
if err != nil {
panic(err.Error())
}

if input.Resolver != "resolver_name" {
m.t.Error("the resolver is wrong")
}

expectedLoad := []string{"param_name"}

if !reflect.DeepEqual(input.Load, expectedLoad) {
m.t.Error("The loads dont match each other")
}

stringReader := strings.NewReader(`{"error":"error message"}`)

return &http.Response{
Body: io.NopCloser(stringReader),
}, nil
}

func TestResolveUnexpectedError(t *testing.T) {
defer func() {
r := recover()
if r != "error message" {
t.Error("The panic message it's not throwed")
}
}()
Client = &MockHTTPClientUnexpectedError{
t: t,
}
ctx := NewContext()

ctx.resolve("resolver_name", "param_name")
}

// TestResolve stop
7 changes: 6 additions & 1 deletion types/typedMap.go
Original file line number Diff line number Diff line change
Expand Up @@ -126,17 +126,22 @@ func (c *TypedMap) GetBool(param string) bool {
func (c *TypedMap) GetMap(param string) *TypedMap {
value := c.Get(param)
if value != nil {
result := NewTypedMap()
v := reflect.ValueOf(value)
kind := v.Kind()
if kind == reflect.Map {
result := NewTypedMap()
for _, key := range v.MapKeys() {
strct := v.MapIndex(key)
result.Put(key.String(), strct.Interface())
}
return result
}

tp, ok := value.(*TypedMap)
if ok {
return tp
}

panic("This param it's not a map")
}
return nil
Expand Down

0 comments on commit 1bf7a13

Please sign in to comment.