From 73552ef89c2ce6a4bab5eb55d2aaeea04850a2e0 Mon Sep 17 00:00:00 2001 From: DanB Date: Wed, 13 Jun 2018 18:34:42 +0200 Subject: [PATCH] NavigableMap with ordered items --- agents/httpagent.go | 11 +++-- agents/libdmt_test.go | 28 ++++++++---- agents/libhttpagent.go | 22 +--------- agents/librad.go | 9 ++-- agents/librad_test.go | 7 +-- engine/attributes.go | 2 +- engine/calldesc.go | 4 +- engine/dataprovider.go | 2 +- engine/filters_test.go | 40 ++++++++--------- engine/navigablemap.go | 88 +++++++++++++++++++++++++++++++++---- engine/navigablemap_test.go | 18 ++++---- engine/resources.go | 2 +- engine/stats.go | 2 +- engine/suppliers.go | 4 +- engine/thresholds.go | 2 +- sessions/sessions.go | 32 +++++++------- 16 files changed, 169 insertions(+), 104 deletions(-) diff --git a/agents/httpagent.go b/agents/httpagent.go index 76c514580..e25d1dae5 100644 --- a/agents/httpagent.go +++ b/agents/httpagent.go @@ -60,7 +60,7 @@ func (ha *HTTPAgent) ServeHTTP(w http.ResponseWriter, req *http.Request) { } var processed bool procVars := make(processorVars) - rpl := newHTTPReplyFields() + rpl := engine.NewNavigableMap(nil) for _, reqProcessor := range ha.reqProcessors { var lclProcessed bool if lclProcessed, err = ha.processRequest(reqProcessor, dcdr, @@ -101,8 +101,7 @@ func (ha *HTTPAgent) ServeHTTP(w http.ResponseWriter, req *http.Request) { // processRequest represents one processor processing the request func (ha *HTTPAgent) processRequest(reqProcessor *config.HttpAgntProcCfg, dP engine.DataProvider, procVars processorVars, - reply *httpReplyFields) (processed bool, err error) { - + reply *engine.NavigableMap) (processed bool, err error) { tnt, err := dP.FieldAsString([]string{utils.Tenant}) if err != nil { return false, err @@ -116,11 +115,11 @@ func (ha *HTTPAgent) processRequest(reqProcessor *config.HttpAgntProcCfg, procVars[k] = strconv.FormatBool(v) } if reqProcessor.DryRun { - utils.Logger.Info(fmt.Sprintf("<%s> DRY_RUN, RADIUS request: %s", utils.RadiusAgent, dP)) - utils.Logger.Info(fmt.Sprintf("<%s> DRY_RUN, process variabiles: %+v", utils.RadiusAgent, procVars)) + utils.Logger.Info(fmt.Sprintf("<%s> DRY_RUN, HTTP request: %s", utils.HTTPAgent, dP)) + utils.Logger.Info(fmt.Sprintf("<%s> DRY_RUN, process variables: %+v", utils.HTTPAgent, procVars)) } /* - cgrEv, err := radReqAsCGREvent(req, procVars, reqProcessor.Flags, reqProcessor.RequestFields) + ev, err := radReqAsCGREvent(req, procVars, reqProcessor.Flags, reqProcessor.RequestFields) if err != nil { return false, err } diff --git a/agents/libdmt_test.go b/agents/libdmt_test.go index 441b14657..8c01e01e7 100644 --- a/agents/libdmt_test.go +++ b/agents/libdmt_test.go @@ -27,7 +27,6 @@ import ( "time" "github.com/cgrates/cgrates/config" - "github.com/cgrates/cgrates/engine" "github.com/cgrates/cgrates/sessions" "github.com/cgrates/cgrates/utils" "github.com/fiorix/go-diameter/diam" @@ -215,24 +214,35 @@ func TestFieldOutVal(t *testing.T) { t.Errorf("Expecting:\n%s\nReceived:\n%s", eOut, fldOut) } // Without groupedAVP, we shoud get the first subscriptionId - cfgFld = &config.CfgCdrField{Tag: "Grouped2", Type: utils.MetaGrouped, FieldId: "Account", - FieldFilter: utils.ParseRSRFieldsMustCompile("Subscription-Id>Subscription-Id-Type(1)", utils.INFIELD_SEP), - Value: utils.ParseRSRFieldsMustCompile("Subscription-Id>Subscription-Id-Data", utils.INFIELD_SEP), Mandatory: true} + cfgFld = &config.CfgCdrField{ + Tag: "Grouped2", + Type: utils.MetaGrouped, FieldId: "Account", + FieldFilter: utils.ParseRSRFieldsMustCompile( + "Subscription-Id>Subscription-Id-Type(1)", utils.INFIELD_SEP), + Value: utils.ParseRSRFieldsMustCompile( + "Subscription-Id>Subscription-Id-Data", utils.INFIELD_SEP), Mandatory: true} eOut = "208708000003" if fldOut, err := fieldOutVal(m, cfgFld, time.Duration(0), nil); err != nil { t.Error(err) } else if fldOut != eOut { t.Errorf("Expecting:\n%s\nReceived:\n%s", eOut, fldOut) } - cfgFld = &config.CfgCdrField{Tag: "TestMultipleFiltersEmptyReply", Type: utils.META_COMPOSED, FieldId: "Account", - FieldFilter: utils.ParseRSRFieldsMustCompile("*cgrReply>Error(^$);*cgrReply>MaxUsage(!300);*cgrReply>MaxUsage(!0)", utils.INFIELD_SEP), - Value: utils.ParseRSRFieldsMustCompile("Subscription-Id>Subscription-Id-Data", utils.INFIELD_SEP), Mandatory: true} + cfgFld = &config.CfgCdrField{ + Tag: "TestMultipleFiltersEmptyReply", + Type: utils.META_COMPOSED, FieldId: "Account", + FieldFilter: utils.ParseRSRFieldsMustCompile( + "*cgrReply>Error(^$);*cgrReply>MaxUsage(!300);*cgrReply>MaxUsage(!0)", + utils.INFIELD_SEP), + Value: utils.ParseRSRFieldsMustCompile( + "Subscription-Id>Subscription-Id-Data", utils.INFIELD_SEP), + Mandatory: true} procVars := processorVars{ - utils.MetaCGRReply: engine.NavigableMap{ + utils.MetaCGRReply: map[string]interface{}{ utils.Error: "RALS_ERROR:NOT_FOUND", }, } - if _, err := fieldOutVal(m, cfgFld, time.Duration(0), procVars); err != ErrFilterNotPassing { + if _, err := fieldOutVal(m, cfgFld, time.Duration(0), + procVars); err != ErrFilterNotPassing { t.Error(err) } } diff --git a/agents/libhttpagent.go b/agents/libhttpagent.go index 76ce5a8c0..0d8bc7f63 100644 --- a/agents/libhttpagent.go +++ b/agents/libhttpagent.go @@ -25,24 +25,6 @@ import ( "github.com/cgrates/cgrates/engine" ) -// httpReplyField is one field written in HTTP reply -type httpReplyField struct { - fldPath string - fldVal string -} - -func newHTTPReplyFields() *httpReplyFields { - return &httpReplyFields{indexed: make(map[string]*httpReplyField), - ordered: make([]*httpReplyField, 0)} -} - -// httpReplyFields is the reply which will be written to HTTP -// both flds and ordered are pointig towards same httpReplyField -type httpReplyFields struct { - indexed map[string]*httpReplyField // map[fldPath]*httpReplyField - ordered []*httpReplyField // keep order for export -} - // newHAReqDecoder produces decoders func newHADataProvider(dpType string, req *http.Request) (dP engine.DataProvider, err error) { @@ -61,8 +43,8 @@ func newHAReplyEncoder(encType string, } } -// httpAgentReplyEncoder will encode fields from httpReplyFields +// httpAgentReplyEncoder will encode []*engine.NMElement // and write content to http writer type httpAgentReplyEncoder interface { - encode(*httpReplyFields) error + encode(*engine.NavigableMap) error } diff --git a/agents/librad.go b/agents/librad.go index f66996330..b1e23ff6c 100644 --- a/agents/librad.go +++ b/agents/librad.go @@ -62,7 +62,7 @@ func (pv processorVars) valAsInterface(fldPath string) (val interface{}, err err err = errors.New("not found") return } - return engine.NavigableMap(pv).FieldAsInterface(strings.Split(fldPath, utils.HIERARCHY_SEP)) + return engine.NewNavigableMap(pv).FieldAsInterface(strings.Split(fldPath, utils.HIERARCHY_SEP)) } // valAsString returns the string value for fldName @@ -75,7 +75,7 @@ func (pv processorVars) valAsString(fldPath string) (val string, err error) { if !pv.hasVar(fldName) { return "", utils.ErrNotFoundNoCaps } - return engine.NavigableMap(pv).FieldAsString(strings.Split(fldPath, utils.HIERARCHY_SEP)) + return engine.NewNavigableMap(pv).FieldAsString(strings.Split(fldPath, utils.HIERARCHY_SEP)) } // asV1AuthorizeArgs returns the arguments needed by SessionSv1.AuthorizeEvent @@ -411,6 +411,7 @@ func NewCGRReply(rply engine.NavigableMapper, if err != nil { return nil, err } - nM[utils.Error] = "" // enforce empty error - return map[string]interface{}(nM), nil // convert from NM to map due to decapsulation later + mp = nM.AsMapStringInterface() + mp[utils.Error] = "" // enforce empty error + return mp, nil } diff --git a/agents/librad_test.go b/agents/librad_test.go index f42df5f92..850ce2456 100644 --- a/agents/librad_test.go +++ b/agents/librad_test.go @@ -428,8 +428,8 @@ func TestRadReplyAppendAttributes(t *testing.T) { type myEv map[string]interface{} -func (ev myEv) AsNavigableMap(tpl []*config.CfgCdrField) (engine.NavigableMap, error) { - return engine.NavigableMap(ev), nil +func (ev myEv) AsNavigableMap(tpl []*config.CfgCdrField) (*engine.NavigableMap, error) { + return engine.NewNavigableMap(ev), nil } func TestNewCGRReply(t *testing.T) { @@ -439,7 +439,8 @@ func TestNewCGRReply(t *testing.T) { if rpl, err := NewCGRReply(nil, errors.New("some")); err != nil { t.Error(err) } else if !reflect.DeepEqual(eCgrRply, rpl) { - t.Errorf("Expecting: %+v, received: %+v", utils.ToJSON(eCgrRply), utils.ToJSON(rpl)) + t.Errorf("Expecting: %+v, received: %+v", + utils.ToJSON(eCgrRply), utils.ToJSON(rpl)) } ev := myEv{ "FirstLevel": map[string]interface{}{ diff --git a/engine/attributes.go b/engine/attributes.go index 9520e5afe..e6b149b47 100644 --- a/engine/attributes.go +++ b/engine/attributes.go @@ -91,7 +91,7 @@ func (alS *AttributeService) matchingAttributeProfilesForEvent(ev *utils.CGREven continue } if pass, err := alS.filterS.Pass(ev.Tenant, aPrfl.FilterIDs, - NavigableMap(ev.Event)); err != nil { + NewNavigableMap(ev.Event)); err != nil { return nil, err } else if !pass { continue diff --git a/engine/calldesc.go b/engine/calldesc.go index a4fc789be..7dced83e0 100644 --- a/engine/calldesc.go +++ b/engine/calldesc.go @@ -1456,6 +1456,6 @@ func (cd *CallDescriptor) String() string { } // AsNavigableMap is part of utils.DataProvider -func (cd *CallDescriptor) AsNavigableMap(tpl []*config.CfgCdrField) (nM NavigableMap, err error) { - return +func (cd *CallDescriptor) AsNavigableMap(tpl []*config.CfgCdrField) (nM *NavigableMap, err error) { + return nil, utils.ErrNotImplemented } diff --git a/engine/dataprovider.go b/engine/dataprovider.go index 6638d3f27..b8c58d9b7 100644 --- a/engine/dataprovider.go +++ b/engine/dataprovider.go @@ -27,5 +27,5 @@ type DataProvider interface { FieldAsInterface(fldPath []string) (interface{}, error) FieldAsString(fldPath []string) (string, error) String() string // printable versin of data - AsNavigableMap(cfgFlds []*config.CfgCdrField) (NavigableMap, error) + AsNavigableMap([]*config.CfgCdrField) (*NavigableMap, error) } diff --git a/engine/filters_test.go b/engine/filters_test.go index 8b4b483e0..e1b7c36f3 100644 --- a/engine/filters_test.go +++ b/engine/filters_test.go @@ -154,16 +154,16 @@ func TestFilterPassGreaterThan(t *testing.T) { if err != nil { t.Error(err) } - ev := NavigableMap{ - "ASR": 20, + ev := &NavigableMap{ + data: map[string]interface{}{"ASR": 20}, } if passes, err := rf.passGreaterThan(ev); err != nil { t.Error(err) } else if !passes { t.Error("not passing") } - ev = map[string]interface{}{ - "ASR": 40, + ev = &NavigableMap{ + data: map[string]interface{}{"ASR": 40}, } if passes, err := rf.passGreaterThan(ev); err != nil { t.Error(err) @@ -188,8 +188,8 @@ func TestFilterPassGreaterThan(t *testing.T) { } else if !passes { t.Error("not passing") } - ev = map[string]interface{}{ - "ASR": 20, + ev = &NavigableMap{ + data: map[string]interface{}{"ASR": 20}, } if passes, err := rf.passGreaterThan(ev); err != nil { t.Error(err) @@ -200,8 +200,8 @@ func TestFilterPassGreaterThan(t *testing.T) { if err != nil { t.Error(err) } - ev = map[string]interface{}{ - "ACD": time.Duration(2 * time.Minute), + ev = &NavigableMap{ + data: map[string]interface{}{"ACD": time.Duration(2 * time.Minute)}, } if passes, err := rf.passGreaterThan(ev); err != nil { t.Error(err) @@ -296,13 +296,13 @@ func TestInlineFilterPassFiltersForEvent(t *testing.T) { t.Errorf(err.Error()) } if pass, err := filterS.Pass("cgrates.org", - []string{"*string:Account:1007"}, NavigableMap(failEvent)); err != nil { + []string{"*string:Account:1007"}, NewNavigableMap(failEvent)); err != nil { t.Errorf(err.Error()) } else if pass { t.Errorf("Expecting: %+v, received: %+v", false, pass) } if pass, err := filterS.Pass("cgrates.org", - []string{"*string:Account:1007"}, NavigableMap(passEvent)); err != nil { + []string{"*string:Account:1007"}, NewNavigableMap(passEvent)); err != nil { t.Errorf(err.Error()) } else if !pass { t.Errorf("Expecting: %+v, received: %+v", true, pass) @@ -314,13 +314,13 @@ func TestInlineFilterPassFiltersForEvent(t *testing.T) { "Account": "1007", } if pass, err := filterS.Pass("cgrates.org", - []string{"*prefix:Account:10"}, NavigableMap(failEvent)); err != nil { + []string{"*prefix:Account:10"}, NewNavigableMap(failEvent)); err != nil { t.Errorf(err.Error()) } else if pass { t.Errorf("Expecting: %+v, received: %+v", false, pass) } if pass, err := filterS.Pass("cgrates.org", - []string{"*prefix:Account:10"}, NavigableMap(passEvent)); err != nil { + []string{"*prefix:Account:10"}, NewNavigableMap(passEvent)); err != nil { t.Errorf(err.Error()) } else if !pass { t.Errorf("Expecting: %+v, received: %+v", true, pass) @@ -332,13 +332,13 @@ func TestInlineFilterPassFiltersForEvent(t *testing.T) { "Tenant": "cgrates.org", } if pass, err := filterS.Pass("cgrates.org", - []string{"*rsr::Tenant(~^cgr.*\\.org$)"}, NavigableMap(failEvent)); err != nil { + []string{"*rsr::Tenant(~^cgr.*\\.org$)"}, NewNavigableMap(failEvent)); err != nil { t.Errorf(err.Error()) } else if pass { t.Errorf("Expecting: %+v, received: %+v", false, pass) } if pass, err := filterS.Pass("cgrates.org", - []string{"*rsr::Tenant(~^cgr.*\\.org$)"}, NavigableMap(passEvent)); err != nil { + []string{"*rsr::Tenant(~^cgr.*\\.org$)"}, NewNavigableMap(passEvent)); err != nil { t.Errorf(err.Error()) } else if !pass { t.Errorf("Expecting: %+v, received: %+v", true, pass) @@ -352,13 +352,13 @@ func TestInlineFilterPassFiltersForEvent(t *testing.T) { utils.Destination: "+4986517174963", } if pass, err := filterS.Pass("cgrates.org", - []string{"*destinations:Destination:EU"}, NavigableMap(failEvent)); err != nil { + []string{"*destinations:Destination:EU"}, NewNavigableMap(failEvent)); err != nil { t.Errorf(err.Error()) } else if pass { t.Errorf("Expecting: %+v, received: %+v", false, pass) } if pass, err := filterS.Pass("cgrates.org", - []string{"*destinations:Destination:EU_LANDLINE"}, NavigableMap(passEvent)); err != nil { + []string{"*destinations:Destination:EU_LANDLINE"}, NewNavigableMap(passEvent)); err != nil { t.Errorf(err.Error()) } else if !pass { t.Errorf("Expecting: %+v, received: %+v", true, pass) @@ -370,13 +370,13 @@ func TestInlineFilterPassFiltersForEvent(t *testing.T) { utils.Weight: 20, } if pass, err := filterS.Pass("cgrates.org", - []string{"*gte:Weight:20"}, NavigableMap(failEvent)); err != nil { + []string{"*gte:Weight:20"}, NewNavigableMap(failEvent)); err != nil { t.Errorf(err.Error()) } else if pass { t.Errorf("Expecting: %+v, received: %+v", false, pass) } if pass, err := filterS.Pass("cgrates.org", - []string{"*gte:Weight:10"}, NavigableMap(passEvent)); err != nil { + []string{"*gte:Weight:10"}, NewNavigableMap(passEvent)); err != nil { t.Errorf(err.Error()) } else if !pass { t.Errorf("Expecting: %+v, received: %+v", true, pass) @@ -404,13 +404,13 @@ func TestPassFiltersForEventWithEmptyFilter(t *testing.T) { utils.Weight: 20, } if pass, err := filterS.Pass("cgrates.org", - []string{}, NavigableMap(passEvent1)); err != nil { + []string{}, NewNavigableMap(passEvent1)); err != nil { t.Errorf(err.Error()) } else if !pass { t.Errorf("Expecting: %+v, received: %+v", false, pass) } if pass, err := filterS.Pass("itsyscom.com", - []string{}, NavigableMap(passEvent2)); err != nil { + []string{}, NewNavigableMap(passEvent2)); err != nil { t.Errorf(err.Error()) } else if !pass { t.Errorf("Expecting: %+v, received: %+v", true, pass) diff --git a/engine/navigablemap.go b/engine/navigablemap.go index 01b5b73d2..08831f046 100644 --- a/engine/navigablemap.go +++ b/engine/navigablemap.go @@ -28,20 +28,50 @@ import ( // CGRReplier is the interface supported by replies convertible to CGRReply type NavigableMapper interface { - AsNavigableMap([]*config.CfgCdrField) (NavigableMap, error) + AsNavigableMap([]*config.CfgCdrField) (*NavigableMap, error) +} + +// NewNavigableMap constructs a NavigableMap +func NewNavigableMap(data map[string]interface{}) *NavigableMap { + if data == nil { + data = make(map[string]interface{}) + } + return &NavigableMap{data: data} } // NavigableMap is a map who's values can be navigated via path -type NavigableMap map[string]interface{} +// data can be retrieved as ordered +// NavigableMap is not thread safe due to performance demands, could come back if needed +type NavigableMap struct { + data map[string]interface{} // layered map + order [][]string // order of field paths +} + +// Add will add items into NavigableMap populating also order +func (nM *NavigableMap) Add(path []string, data interface{}) { + nM.order = append(nM.order) + mp := nM.data + for i, spath := range path { + _, has := mp[spath] + if !has { + if i == len(path)-1 { // last path + mp[spath] = data + return + } + mp[spath] = make(map[string]interface{}) + } + mp = mp[spath].(map[string]interface{}) // so we can check further down + } +} // FieldAsInterface returns the field value as interface{} for the path specified // implements DataProvider -func (nM NavigableMap) FieldAsInterface(fldPath []string) (fldVal interface{}, err error) { +func (nM *NavigableMap) FieldAsInterface(fldPath []string) (fldVal interface{}, err error) { lenPath := len(fldPath) if lenPath == 0 { return nil, errors.New("empty field path") } - lastMp := nM // last map when layered + lastMp := nM.data // last map when layered var canCast bool for i, spath := range fldPath { if i == lenPath-1 { // lastElement @@ -71,7 +101,7 @@ func (nM NavigableMap) FieldAsInterface(fldPath []string) (fldVal interface{}, e // FieldAsString returns the field value as string for the path specified // implements DataProvider -func (nM NavigableMap) FieldAsString(fldPath []string) (fldVal string, err error) { +func (nM *NavigableMap) FieldAsString(fldPath []string) (fldVal string, err error) { var valIface interface{} valIface, err = nM.FieldAsInterface(fldPath) if err != nil { @@ -84,11 +114,51 @@ func (nM NavigableMap) FieldAsString(fldPath []string) (fldVal string, err error return } -func (nM NavigableMap) String() string { - return utils.ToJSON(nM) +func (nM *NavigableMap) String() string { + return utils.ToJSON(nM.data) +} + +// AsMapStringInterface returns the data out of map, ignoring the order part +func (nM *NavigableMap) AsMapStringInterface() map[string]interface{} { + return nM.data +} + +type NMItem struct { + Path []string // path in map + Data interface{} // value of the element +} + +// indexMapElements will recursively go through map and index the element paths into elmns +func indexMapElements(mp map[string]interface{}, path []string, elms *[]*NMItem) { + for k, v := range mp { + vPath := append(path, k) + if mpIface, isMap := v.(map[string]interface{}); isMap { + indexMapElements(mpIface, vPath, elms) + } else { + elmsOut := append(*elms, &NMItem{vPath, v}) + *elms = elmsOut + } + } +} + +// Items returns the items in map, ordered by order information +func (nM *NavigableMap) Items() (itms []*NMItem) { + if len(nM.data) == 0 { + return + } + if len(nM.order) == 0 { + indexMapElements(nM.data, []string{}, &itms) + return + } + itms = make([]*NMItem, len(nM.order)) + for i, path := range nM.order { + val, _ := nM.FieldAsInterface(path) + itms[i] = &NMItem{Data: val, Path: path} + } + return } // AsNavigableMap implements both NavigableMapper as well as DataProvider interfaces -func (nM NavigableMap) AsNavigableMap(tpl []*config.CfgCdrField) (oNM NavigableMap, err error) { - return +func (nM *NavigableMap) AsNavigableMap(tpl []*config.CfgCdrField) (oNM *NavigableMap, err error) { + return nil, utils.ErrNotImplemented } diff --git a/engine/navigablemap_test.go b/engine/navigablemap_test.go index 28e44f962..e0cf6825d 100644 --- a/engine/navigablemap_test.go +++ b/engine/navigablemap_test.go @@ -24,15 +24,17 @@ import ( ) func TestNavMapGetFieldAsString(t *testing.T) { - nM := NavigableMap{ - "FirstLevel": map[string]interface{}{ - "SecondLevel": map[string]interface{}{ - "ThirdLevel": map[string]interface{}{ - "Fld1": "Val1", + nM := &NavigableMap{ + data: map[string]interface{}{ + "FirstLevel": map[string]interface{}{ + "SecondLevel": map[string]interface{}{ + "ThirdLevel": map[string]interface{}{ + "Fld1": "Val1", + }, }, }, + "AnotherFirstLevel": "ValAnotherFirstLevel", }, - "AnotherFirstLevel": "ValAnotherFirstLevel", } eVal := "Val1" if strVal, err := nM.FieldAsString( @@ -57,6 +59,6 @@ func TestNavMapGetFieldAsString(t *testing.T) { type myEv map[string]interface{} -func (ev myEv) AsNavigableMap() (map[string]interface{}, error) { - return NavigableMap(ev), nil +func (ev myEv) AsNavigableMap() (*NavigableMap, error) { + return NewNavigableMap(ev), nil } diff --git a/engine/resources.go b/engine/resources.go index 05ec5ebee..b583cb30f 100644 --- a/engine/resources.go +++ b/engine/resources.go @@ -464,7 +464,7 @@ func (rS *ResourceService) matchingResourcesForEvent(ev *utils.CGREvent, usageTT continue } if pass, err := rS.filterS.Pass(ev.Tenant, rPrf.FilterIDs, - NavigableMap(ev.Event)); err != nil { + NewNavigableMap(ev.Event)); err != nil { return nil, err } else if !pass { continue diff --git a/engine/stats.go b/engine/stats.go index a7be8984f..cb247ae9a 100644 --- a/engine/stats.go +++ b/engine/stats.go @@ -169,7 +169,7 @@ func (sS *StatService) matchingStatQueuesForEvent(ev *utils.CGREvent) (sqs StatQ continue } if pass, err := sS.filterS.Pass(ev.Tenant, sqPrfl.FilterIDs, - NavigableMap(ev.Event)); err != nil { + NewNavigableMap(ev.Event)); err != nil { return nil, err } else if !pass { continue diff --git a/engine/suppliers.go b/engine/suppliers.go index 032ecd0e5..ea37a73f2 100644 --- a/engine/suppliers.go +++ b/engine/suppliers.go @@ -137,7 +137,7 @@ func (spS *SupplierService) matchingSupplierProfilesForEvent(ev *utils.CGREvent) continue } if pass, err := spS.filterS.Pass(ev.Tenant, splPrfl.FilterIDs, - NavigableMap(ev.Event)); err != nil { + NewNavigableMap(ev.Event)); err != nil { return nil, err } else if !pass { continue @@ -277,7 +277,7 @@ func (spS *SupplierService) sortedSuppliersForEvent(args *ArgsGetSuppliers) (sor for _, s := range splPrfl.Suppliers { if len(s.FilterIDs) != 0 { // filters should be applied, check them here if pass, err := spS.filterS.Pass(args.Tenant, s.FilterIDs, - NavigableMap(args.Event)); err != nil { + NewNavigableMap(args.Event)); err != nil { return nil, err } else if !pass { continue diff --git a/engine/thresholds.go b/engine/thresholds.go index 1d0e85dbd..e7505fc4e 100644 --- a/engine/thresholds.go +++ b/engine/thresholds.go @@ -246,7 +246,7 @@ func (tS *ThresholdService) matchingThresholdsForEvent(args *ArgsProcessEvent) ( continue } if pass, err := tS.filterS.Pass(args.Tenant, tPrfl.FilterIDs, - NavigableMap(args.Event)); err != nil { + NewNavigableMap(args.Event)); err != nil { return nil, err } else if !pass { continue diff --git a/sessions/sessions.go b/sessions/sessions.go index 368d10e11..c4f771acb 100644 --- a/sessions/sessions.go +++ b/sessions/sessions.go @@ -1337,8 +1337,9 @@ type V1AuthorizeReply struct { } // AsNavigableMap is part of engine.NavigableMapper interface -func (v1AuthReply *V1AuthorizeReply) AsNavigableMap(ignr []*config.CfgCdrField) (cgrReply engine.NavigableMap, err error) { - cgrReply = make(map[string]interface{}) +func (v1AuthReply *V1AuthorizeReply) AsNavigableMap( + ignr []*config.CfgCdrField) (*engine.NavigableMap, error) { + cgrReply := make(map[string]interface{}) if v1AuthReply.Attributes != nil { attrs := make(map[string]interface{}) for _, fldName := range v1AuthReply.Attributes.AlteredFields { @@ -1363,8 +1364,7 @@ func (v1AuthReply *V1AuthorizeReply) AsNavigableMap(ignr []*config.CfgCdrField) if v1AuthReply.StatQueueIDs != nil { cgrReply[utils.CapStatQueues] = *v1AuthReply.StatQueueIDs } - cgrReply[utils.Error] = "" // so we can compare in filters - return + return engine.NewNavigableMap(cgrReply), nil } // BiRPCV1Authorize performs authorization for CGREvent based on specific components @@ -1552,8 +1552,9 @@ type V1InitSessionReply struct { } // AsNavigableMap is part of engine.NavigableMapper interface -func (v1Rply *V1InitSessionReply) AsNavigableMap(ignr []*config.CfgCdrField) (cgrReply engine.NavigableMap, err error) { - cgrReply = make(map[string]interface{}) +func (v1Rply *V1InitSessionReply) AsNavigableMap( + ignr []*config.CfgCdrField) (*engine.NavigableMap, error) { + cgrReply := make(map[string]interface{}) if v1Rply.Attributes != nil { attrs := make(map[string]interface{}) for _, fldName := range v1Rply.Attributes.AlteredFields { @@ -1575,8 +1576,7 @@ func (v1Rply *V1InitSessionReply) AsNavigableMap(ignr []*config.CfgCdrField) (cg if v1Rply.StatQueueIDs != nil { cgrReply[utils.CapStatQueues] = *v1Rply.StatQueueIDs } - cgrReply[utils.Error] = "" - return + return engine.NewNavigableMap(cgrReply), nil } // BiRPCV2InitiateSession initiates a new session, returns the maximum duration the session can last @@ -1732,8 +1732,9 @@ type V1UpdateSessionReply struct { } // AsNavigableMap is part of engine.NavigableMapper interface -func (v1Rply *V1UpdateSessionReply) AsNavigableMap(ignr []*config.CfgCdrField) (cgrReply engine.NavigableMap, err error) { - cgrReply = make(map[string]interface{}) +func (v1Rply *V1UpdateSessionReply) AsNavigableMap( + ignr []*config.CfgCdrField) (*engine.NavigableMap, error) { + cgrReply := make(map[string]interface{}) if v1Rply.Attributes != nil { attrs := make(map[string]interface{}) for _, fldName := range v1Rply.Attributes.AlteredFields { @@ -1746,8 +1747,7 @@ func (v1Rply *V1UpdateSessionReply) AsNavigableMap(ignr []*config.CfgCdrField) ( if v1Rply.MaxUsage != nil { cgrReply[utils.CapMaxUsage] = *v1Rply.MaxUsage } - cgrReply[utils.Error] = "" - return + return engine.NewNavigableMap(cgrReply), nil } // BiRPCV1UpdateSession updates an existing session, returning the duration which the session can still last @@ -1899,8 +1899,9 @@ type V1ProcessEventReply struct { } // AsNavigableMap is part of engine.NavigableMapper interface -func (v1Rply *V1ProcessEventReply) AsNavigableMap(ignr []*config.CfgCdrField) (cgrReply engine.NavigableMap, err error) { - cgrReply = make(map[string]interface{}) +func (v1Rply *V1ProcessEventReply) AsNavigableMap( + ignr []*config.CfgCdrField) (*engine.NavigableMap, error) { + cgrReply := make(map[string]interface{}) if v1Rply.MaxUsage != nil { cgrReply[utils.CapMaxUsage] = *v1Rply.MaxUsage } @@ -1916,8 +1917,7 @@ func (v1Rply *V1ProcessEventReply) AsNavigableMap(ignr []*config.CfgCdrField) (c } cgrReply[utils.CapAttributes] = attrs } - cgrReply[utils.Error] = "" - return + return engine.NewNavigableMap(cgrReply), nil } // Called on session end, should send the CDR to CDRS