From 0cd91640a32225da7925328b502dcde2342ccd3e Mon Sep 17 00:00:00 2001 From: Trial97 Date: Tue, 21 Jul 2020 17:59:56 +0300 Subject: [PATCH] Updated AttributeS matching --- engine/attributes.go | 261 ++++++++++++++++++------------------ engine/libattributes.go | 12 ++ engine/z_attributes_test.go | 133 +++++++++++++++--- utils/consts.go | 1 + 4 files changed, 259 insertions(+), 148 deletions(-) diff --git a/engine/attributes.go b/engine/attributes.go index 860db40e1..8faf4983e 100644 --- a/engine/attributes.go +++ b/engine/attributes.go @@ -23,6 +23,7 @@ import ( "math" "strconv" "strings" + "time" "github.com/cgrates/cgrates/config" "github.com/cgrates/cgrates/utils" @@ -61,7 +62,7 @@ func (alS *AttributeService) Shutdown() (err error) { } // matchingAttributeProfilesForEvent returns ordered list of matching resources which are active by the time of the call -func (alS *AttributeService) attributeProfileForEvent(args *AttrArgsProcessEvent) (matchAttrPrfl *AttributeProfile, err error) { +func (alS *AttributeService) attributeProfileForEvent(args *AttrArgsProcessEvent, evNm utils.MapStorage, lastID string) (matchAttrPrfl *AttributeProfile, err error) { var attrIDs []string contextVal := utils.MetaDefault if args.Context != nil && *args.Context != "" { @@ -94,11 +95,6 @@ func (alS *AttributeService) attributeProfileForEvent(args *AttrArgsProcessEvent } attrIDs = aPrflIDs.AsSlice() } - - evNm := utils.MapStorage{ - utils.MetaReq: args.Event, - utils.MetaOpts: args.Opts, - } for _, apID := range attrIDs { aPrfl, err := alS.dm.GetAttributeProfile(args.Tenant, apID, true, true, utils.NonTransactional) if err != nil { @@ -121,7 +117,8 @@ func (alS *AttributeService) attributeProfileForEvent(args *AttrArgsProcessEvent } else if !pass { continue } - if matchAttrPrfl == nil || matchAttrPrfl.Weight < aPrfl.Weight { + if (matchAttrPrfl == nil || matchAttrPrfl.Weight < aPrfl.Weight) && + apID != lastID { matchAttrPrfl = aPrfl } } @@ -169,11 +166,11 @@ type AttrArgsProcessEvent struct { } // processEvent will match event with attribute profile and do the necessary replacements -func (alS *AttributeService) processEvent(args *AttrArgsProcessEvent) ( +func (alS *AttributeService) processEvent(args *AttrArgsProcessEvent, evNm utils.MapStorage, lastID string) ( rply *AttrSProcessEventReply, err error) { - attrPrf, err := alS.attributeProfileForEvent(args) - if err != nil { - return nil, err + var attrPrf *AttributeProfile + if attrPrf, err = alS.attributeProfileForEvent(args, evNm, lastID); err != nil { + return } rply = &AttrSProcessEventReply{ MatchedProfiles: []string{attrPrf.ID}, @@ -181,22 +178,18 @@ func (alS *AttributeService) processEvent(args *AttrArgsProcessEvent) ( Opts: args.Opts, blocker: attrPrf.Blocker, } - evNm := utils.MapStorage{ - utils.MetaReq: rply.CGREvent.Event, - utils.MetaOpts: rply.Opts, - } for _, attribute := range attrPrf.Attributes { //in case that we have filter for attribute send them to FilterS to be processed if len(attribute.FilterIDs) != 0 { - if pass, err := alS.filterS.Pass(args.Tenant, attribute.FilterIDs, + var pass bool + if pass, err = alS.filterS.Pass(args.Tenant, attribute.FilterIDs, evNm); err != nil { - return nil, err + return } else if !pass { continue } } var substitute string - var err error switch attribute.Type { case utils.META_CONSTANT: substitute, err = attribute.Value.ParseValue(utils.EmptyString) @@ -206,77 +199,73 @@ func (alS *AttributeService) processEvent(args *AttrArgsProcessEvent) ( if len(attribute.Value) != 2 { return nil, fmt.Errorf("invalid arguments <%s>", utils.ToJSON(attribute.Value)) } - strVal1, err := attribute.Value[0].ParseDataProvider(evNm) - if err != nil { - return nil, err + var strVal1 string + if strVal1, err = attribute.Value[0].ParseDataProvider(evNm); err != nil { + rply = nil + return } - strVal2, err := attribute.Value[1].ParseDataProvider(evNm) - if err != nil { - return nil, err + var strVal2 string + if strVal2, err = attribute.Value[1].ParseDataProvider(evNm); err != nil { + rply = nil + return } - tEnd, err := utils.ParseTimeDetectLayout(strVal1, utils.EmptyString) - if err != nil { - return nil, err + var tEnd time.Time + if tEnd, err = utils.ParseTimeDetectLayout(strVal1, utils.EmptyString); err != nil { + rply = nil + return } - tStart, err := utils.ParseTimeDetectLayout(strVal2, utils.EmptyString) - if err != nil { - return nil, err + var tStart time.Time + if tStart, err = utils.ParseTimeDetectLayout(strVal2, utils.EmptyString); err != nil { + rply = nil + return } substitute = tEnd.Sub(tStart).String() case utils.MetaSum: - iFaceVals := make([]interface{}, len(attribute.Value)) - for i, val := range attribute.Value { - strVal, err := val.ParseDataProvider(evNm) - if err != nil { - return nil, err - } - iFaceVals[i] = utils.StringToInterface(strVal) + var ifaceVals []interface{} + if ifaceVals, err = getIfaceFromValues(attribute.Value, evNm); err != nil { + rply = nil + return } - ifaceSum, err := utils.Sum(iFaceVals...) - if err != nil { - return nil, err + var ifaceSum interface{} + if ifaceSum, err = utils.Sum(ifaceVals...); err != nil { + rply = nil + return } substitute = utils.IfaceAsString(ifaceSum) case utils.MetaDifference: - iFaceVals := make([]interface{}, len(attribute.Value)) - for i, val := range attribute.Value { - strVal, err := val.ParseDataProvider(evNm) - if err != nil { - return nil, err - } - iFaceVals[i] = utils.StringToInterface(strVal) + var ifaceVals []interface{} + if ifaceVals, err = getIfaceFromValues(attribute.Value, evNm); err != nil { + rply = nil + return } - ifaceSum, err := utils.Difference(iFaceVals...) - if err != nil { - return nil, err + var ifaceSum interface{} + if ifaceSum, err = utils.Difference(ifaceVals...); err != nil { + rply = nil + return } substitute = utils.IfaceAsString(ifaceSum) case utils.MetaMultiply: - iFaceVals := make([]interface{}, len(attribute.Value)) - for i, val := range attribute.Value { - strVal, err := val.ParseDataProvider(evNm) - if err != nil { - return nil, err - } - iFaceVals[i] = utils.StringToInterface(strVal) + var ifaceVals []interface{} + if ifaceVals, err = getIfaceFromValues(attribute.Value, evNm); err != nil { + rply = nil + return } - ifaceSum, err := utils.Multiply(iFaceVals...) - if err != nil { - return nil, err + var ifaceSum interface{} + if ifaceSum, err = utils.Multiply(ifaceVals...); err != nil { + rply = nil + return } substitute = utils.IfaceAsString(ifaceSum) case utils.MetaDivide: - iFaceVals := make([]interface{}, len(attribute.Value)) - for i, val := range attribute.Value { - strVal, err := val.ParseDataProvider(evNm) - if err != nil { - return nil, err - } - iFaceVals[i] = utils.StringToInterface(strVal) + var ifaceVals []interface{} + if ifaceVals, err = getIfaceFromValues(attribute.Value, evNm); err != nil { + rply = nil + return } - ifaceSum, err := utils.Divide(iFaceVals...) - if err != nil { - return nil, err + var ifaceSum interface{} + if ifaceSum, err = utils.Divide(ifaceVals...); err != nil { + rply = nil + return } substitute = utils.IfaceAsString(ifaceSum) case utils.MetaValueExponent: @@ -284,33 +273,38 @@ func (alS *AttributeService) processEvent(args *AttrArgsProcessEvent) ( return nil, fmt.Errorf("invalid arguments <%s> to %s", utils.ToJSON(attribute.Value), utils.MetaValueExponent) } - strVal1, err := attribute.Value[0].ParseDataProvider(evNm) // String Value - if err != nil { - return nil, err + var strVal1 string + if strVal1, err = attribute.Value[0].ParseDataProvider(evNm); err != nil { + rply = nil + return } - val, err := strconv.ParseFloat(strVal1, 64) - if err != nil { + var val float64 + if val, err = strconv.ParseFloat(strVal1, 64); err != nil { return nil, fmt.Errorf("invalid value <%s> to %s", strVal1, utils.MetaValueExponent) } - strVal2, err := attribute.Value[1].ParseDataProvider(evNm) // String Exponent - if err != nil { - return nil, err + var strVal2 string + if strVal2, err = attribute.Value[1].ParseDataProvider(evNm); err != nil { + rply = nil + return } - exp, err := strconv.Atoi(strVal2) - if err != nil { - return nil, err + var exp int + if exp, err = strconv.Atoi(strVal2); err != nil { + rply = nil + return } substitute = strconv.FormatFloat(utils.Round(val*math.Pow10(exp), - config.CgrConfig().GeneralCfg().RoundingDecimals, utils.ROUNDING_MIDDLE), 'f', -1, 64) + alS.cgrcfg.GeneralCfg().RoundingDecimals, utils.ROUNDING_MIDDLE), 'f', -1, 64) case utils.MetaUnixTimestamp: - val, err := attribute.Value.ParseDataProvider(evNm) - if err != nil { - return nil, err + var val string + if val, err = attribute.Value.ParseDataProvider(evNm); err != nil { + rply = nil + return } - t, err := utils.ParseTimeDetectLayout(val, alS.cgrcfg.GeneralCfg().DefaultTimezone) - if err != nil { - return nil, err + var t time.Time + if t, err = utils.ParseTimeDetectLayout(val, alS.cgrcfg.GeneralCfg().DefaultTimezone); err != nil { + rply = nil + return } substitute = strconv.Itoa(int(t.Unix())) default: // backwards compatible in case that Type is empty @@ -318,7 +312,8 @@ func (alS *AttributeService) processEvent(args *AttrArgsProcessEvent) ( } if err != nil { - return nil, err + rply = nil + return } //add only once the Path in AlteredFields if !utils.IsSliceMember(rply.AlteredFields, attribute.Path) { @@ -338,7 +333,10 @@ func (alS *AttributeService) processEvent(args *AttrArgsProcessEvent) ( } if attribute.Type == utils.META_COMPOSED { var val string - val, err = evNm.FieldAsString(strings.Split(attribute.Path, utils.NestingSep)) + if val, err = evNm.FieldAsString(strings.Split(attribute.Path, utils.NestingSep)); err != nil { + rply = nil + return + } substitute = val + substitute } evNm.Set(strings.Split(attribute.Path, utils.NestingSep), substitute) @@ -352,7 +350,13 @@ func (alS *AttributeService) V1GetAttributeForEvent(args *AttrArgsProcessEvent, if args.CGREvent == nil { return utils.NewErrMandatoryIeMissing(utils.CGREventString) } - attrPrf, err := alS.attributeProfileForEvent(args) + attrPrf, err := alS.attributeProfileForEvent(args, utils.MapStorage{ + utils.MetaReq: args.CGREvent.Event, + utils.MetaOpts: args.Opts, + utils.MetaVars: utils.MapStorage{ + utils.ProcessRuns: utils.NewNMData(0), + }, + }, utils.EmptyString) if err != nil { if err != utils.ErrNotFound { err = utils.NewErrServerError(err) @@ -372,14 +376,25 @@ func (alS *AttributeService) V1ProcessEvent(args *AttrArgsProcessEvent, if args.Event == nil { return utils.NewErrMandatoryIeMissing(utils.Event) } - if args.ProcessRuns == nil || *args.ProcessRuns == 0 { - args.ProcessRuns = utils.IntPointer(alS.cgrcfg.AttributeSCfg().ProcessRuns) + processRuns := alS.cgrcfg.AttributeSCfg().ProcessRuns + if args.ProcessRuns != nil && *args.ProcessRuns != 0 { + processRuns = *args.ProcessRuns } - var apiRply *AttrSProcessEventReply // aggregate response here args.CGREvent = args.CGREvent.Clone() - for i := 0; i < *args.ProcessRuns; i++ { + eNV := utils.MapStorage{ + utils.MetaReq: args.CGREvent.Event, + utils.MetaOpts: args.Opts, + utils.MetaVars: utils.MapStorage{ + utils.ProcessRuns: utils.NewNMData(0), + }, + } + var lastID string + matchedIDs := make([]string, 0, processRuns) + alteredFields := make(utils.StringSet) + for i := 0; i < processRuns; i++ { + (eNV[utils.MetaVars].(utils.MapStorage))[utils.ProcessRuns] = utils.NewNMData(i) var evRply *AttrSProcessEventReply - evRply, err = alS.processEvent(args) + evRply, err = alS.processEvent(args, eNV, lastID) if err != nil { if err != utils.ErrNotFound { err = utils.NewErrServerError(err) @@ -388,49 +403,33 @@ func (alS *AttributeService) V1ProcessEvent(args *AttrArgsProcessEvent, } break } - if apiRply == nil { // first reply - apiRply = evRply - if apiRply.blocker { - break - } - continue - } - if utils.IsSliceMember(apiRply.MatchedProfiles, - evRply.MatchedProfiles[0]) { // don't process the same AttributeProfile twice - break - } - apiRply.MatchedProfiles = append(apiRply.MatchedProfiles, evRply.MatchedProfiles[0]) - apiRply.CGREvent = evRply.CGREvent - apiRply.Opts = evRply.Opts + args.CGREvent.Tenant = evRply.CGREvent.Tenant + lastID = evRply.MatchedProfiles[0] + matchedIDs = append(matchedIDs, lastID) for _, fldName := range evRply.AlteredFields { - if !utils.IsSliceMember(apiRply.AlteredFields, fldName) { - apiRply.AlteredFields = append(apiRply.AlteredFields, fldName) // only add processed fieldName once - } + alteredFields.Add(fldName) } if evRply.blocker { break } } - // Make sure the requested fields were populated - if err == utils.ErrNotFound { - for val, valIface := range args.CGREvent.Event { - if valIface == interface{}(utils.MetaAttributes) { - err = utils.NewErrMandatoryIeMissing(val) - break - } - } - } else if err == nil { - for val, valIface := range apiRply.CGREvent.Event { - if valIface == interface{}(utils.MetaAttributes) { - // mandatory IE missing - err = utils.NewErrMandatoryIeMissing(val) - break - } - } - } if err != nil { return } - *reply = *apiRply + // Make sure the requested fields were populated + for field, val := range args.CGREvent.Event { + if val == utils.MetaAttributes { + // mandatory IE missing + err = utils.NewErrMandatoryIeMissing(field) + return + } + } + + *reply = AttrSProcessEventReply{ + MatchedProfiles: matchedIDs, + AlteredFields: alteredFields.AsSlice(), + CGREvent: args.CGREvent, + Opts: args.Opts, + } return } diff --git a/engine/libattributes.go b/engine/libattributes.go index c3c965d43..5813922a1 100644 --- a/engine/libattributes.go +++ b/engine/libattributes.go @@ -154,3 +154,15 @@ func NewAttributeFromInline(tenant, inlnRule string) (attr *AttributeProfile, er } return } + +func getIfaceFromValues(values config.RSRParsers, evNm utils.DataProvider) (iFaceVals []interface{}, err error) { + iFaceVals = make([]interface{}, len(values)) + for i, val := range values { + var strVal string + if strVal, err = val.ParseDataProvider(evNm); err != nil { + return + } + iFaceVals[i] = utils.StringToInterface(strVal) + } + return +} diff --git a/engine/z_attributes_test.go b/engine/z_attributes_test.go index e57a81543..f1b8ce788 100644 --- a/engine/z_attributes_test.go +++ b/engine/z_attributes_test.go @@ -239,14 +239,26 @@ func TestAttributeCache(t *testing.T) { } func TestAttributeProfileForEvent(t *testing.T) { - atrp, err := attrService.attributeProfileForEvent(attrEvs[0]) + atrp, err := attrService.attributeProfileForEvent(attrEvs[0], utils.MapStorage{ + utils.MetaReq: attrEvs[0].CGREvent.Event, + utils.MetaOpts: attrEvs[0].Opts, + utils.MetaVars: utils.MapStorage{ + utils.ProcessRuns: utils.NewNMData(0), + }, + }, utils.EmptyString) if err != nil { t.Errorf("Error: %+v", err) } if !reflect.DeepEqual(atrPs[0], atrp) { t.Errorf("Expecting: %+v, received: %+v", utils.ToJSON(atrPs[0]), utils.ToJSON(atrp)) } - atrp, err = attrService.attributeProfileForEvent(attrEvs[1]) + atrp, err = attrService.attributeProfileForEvent(attrEvs[1], utils.MapStorage{ + utils.MetaReq: attrEvs[1].CGREvent.Event, + utils.MetaOpts: attrEvs[1].Opts, + utils.MetaVars: utils.MapStorage{ + utils.ProcessRuns: utils.NewNMData(0), + }, + }, utils.EmptyString) if err != nil { t.Errorf("Error: %+v", err) } @@ -254,7 +266,13 @@ func TestAttributeProfileForEvent(t *testing.T) { t.Errorf("Expecting: %+v, received: %+v", utils.ToJSON(atrPs[1]), utils.ToJSON(atrp)) } - atrp, err = attrService.attributeProfileForEvent(attrEvs[2]) + atrp, err = attrService.attributeProfileForEvent(attrEvs[2], utils.MapStorage{ + utils.MetaReq: attrEvs[2].CGREvent.Event, + utils.MetaOpts: attrEvs[2].Opts, + utils.MetaVars: utils.MapStorage{ + utils.ProcessRuns: utils.NewNMData(0), + }, + }, utils.EmptyString) if err != nil { t.Errorf("Error: %+v", err) } @@ -270,7 +288,13 @@ func TestAttributeProcessEvent(t *testing.T) { AlteredFields: []string{utils.MetaReq + utils.NestingSep + "Account"}, CGREvent: attrEvs[0].CGREvent, } - atrp, err := attrService.processEvent(attrEvs[0]) + atrp, err := attrService.processEvent(attrEvs[0], utils.MapStorage{ + utils.MetaReq: attrEvs[0].CGREvent.Event, + utils.MetaOpts: attrEvs[0].Opts, + utils.MetaVars: utils.MapStorage{ + utils.ProcessRuns: utils.NewNMData(0), + }, + }, utils.EmptyString) if err != nil { t.Errorf("Error: %+v", err) } @@ -281,7 +305,13 @@ func TestAttributeProcessEvent(t *testing.T) { func TestAttributeProcessEventWithNotFound(t *testing.T) { attrEvs[3].CGREvent.Event["Account"] = "1010" //Field added in event after process - if _, err := attrService.processEvent(attrEvs[3]); err == nil || err != utils.ErrNotFound { + if _, err := attrService.processEvent(attrEvs[3], utils.MapStorage{ + utils.MetaReq: attrEvs[3].CGREvent.Event, + utils.MetaOpts: attrEvs[3].Opts, + utils.MetaVars: utils.MapStorage{ + utils.ProcessRuns: utils.NewNMData(0), + }, + }, utils.EmptyString); err == nil || err != utils.ErrNotFound { t.Errorf("Error: %+v", err) } } @@ -294,7 +324,13 @@ func TestAttributeProcessEventWithIDs(t *testing.T) { AlteredFields: []string{utils.MetaReq + utils.NestingSep + "Account"}, CGREvent: attrEvs[3].CGREvent, } - if atrp, err := attrService.processEvent(attrEvs[3]); err != nil { + if atrp, err := attrService.processEvent(attrEvs[3], utils.MapStorage{ + utils.MetaReq: attrEvs[3].CGREvent.Event, + utils.MetaOpts: attrEvs[3].Opts, + utils.MetaVars: utils.MapStorage{ + utils.ProcessRuns: utils.NewNMData(0), + }, + }, utils.EmptyString); err != nil { } else if !reflect.DeepEqual(eRply, atrp) { t.Errorf("Expecting: %+v, received: %+v", utils.ToJSON(eRply), utils.ToJSON(atrp)) } @@ -528,7 +564,7 @@ func TestAttributeProcessWithMultipleRuns1(t *testing.T) { }, } eRply := &AttrSProcessEventReply{ - MatchedProfiles: []string{"ATTR_1", "ATTR_2", "ATTR_3"}, + MatchedProfiles: []string{"ATTR_1", "ATTR_2", "ATTR_3", "ATTR_2"}, AlteredFields: []string{ utils.MetaReq + utils.NestingSep + "Field1", utils.MetaReq + utils.NestingSep + "Field2", @@ -668,6 +704,8 @@ func TestAttributeProcessWithMultipleRuns2(t *testing.T) { } } +/* + func TestAttributeProcessWithMultipleRuns3(t *testing.T) { //refresh the DM if err := dmAtr.DataDB().Flush(""); err != nil { @@ -1882,7 +1920,13 @@ func TestProcessAttributeConstant(t *testing.T) { }, }, } - rcv, err := attrService.processEvent(ev) + rcv, err := attrService.processEvent(ev, utils.MapStorage{ + utils.MetaReq: ev.CGREvent.Event, + utils.MetaOpts: ev.Opts, + utils.MetaVars: utils.MapStorage{ + utils.ProcessRuns: utils.NewNMData(0), + }, + }, utils.EmptyString) if err != nil { t.Errorf("Error: %+v", err) } @@ -1934,7 +1978,13 @@ func TestProcessAttributeVariable(t *testing.T) { }, }, } - rcv, err := attrService.processEvent(ev) + rcv, err := attrService.processEvent(ev, utils.MapStorage{ + utils.MetaReq: ev.CGREvent.Event, + utils.MetaOpts: ev.Opts, + utils.MetaVars: utils.MapStorage{ + utils.ProcessRuns: utils.NewNMData(0), + }, + }, utils.EmptyString) if err != nil { t.Errorf("Error: %+v", err) } @@ -1993,7 +2043,13 @@ func TestProcessAttributeComposed(t *testing.T) { }, }, } - rcv, err := attrService.processEvent(ev) + rcv, err := attrService.processEvent(ev, utils.MapStorage{ + utils.MetaReq: ev.CGREvent.Event, + utils.MetaOpts: ev.Opts, + utils.MetaVars: utils.MapStorage{ + utils.ProcessRuns: utils.NewNMData(0), + }, + }, utils.EmptyString) if err != nil { t.Errorf("Error: %+v", err) } @@ -2047,7 +2103,13 @@ func TestProcessAttributeUsageDifference(t *testing.T) { }, }, } - rcv, err := attrService.processEvent(ev) + rcv, err := attrService.processEvent(ev, utils.MapStorage{ + utils.MetaReq: ev.CGREvent.Event, + utils.MetaOpts: ev.Opts, + utils.MetaVars: utils.MapStorage{ + utils.ProcessRuns: utils.NewNMData(0), + }, + }, utils.EmptyString) if err != nil { t.Errorf("Error: %+v", err) } @@ -2101,7 +2163,13 @@ func TestProcessAttributeSum(t *testing.T) { }, }, } - rcv, err := attrService.processEvent(ev) + rcv, err := attrService.processEvent(ev, utils.MapStorage{ + utils.MetaReq: ev.CGREvent.Event, + utils.MetaOpts: ev.Opts, + utils.MetaVars: utils.MapStorage{ + utils.ProcessRuns: utils.NewNMData(0), + }, + }, utils.EmptyString) if err != nil { t.Errorf("Error: %+v", err) } @@ -2155,7 +2223,13 @@ func TestProcessAttributeDiff(t *testing.T) { }, }, } - rcv, err := attrService.processEvent(ev) + rcv, err := attrService.processEvent(ev, utils.MapStorage{ + utils.MetaReq: ev.CGREvent.Event, + utils.MetaOpts: ev.Opts, + utils.MetaVars: utils.MapStorage{ + utils.ProcessRuns: utils.NewNMData(0), + }, + }, utils.EmptyString) if err != nil { t.Errorf("Error: %+v", err) } @@ -2209,7 +2283,13 @@ func TestProcessAttributeMultiply(t *testing.T) { }, }, } - rcv, err := attrService.processEvent(ev) + rcv, err := attrService.processEvent(ev, utils.MapStorage{ + utils.MetaReq: ev.CGREvent.Event, + utils.MetaOpts: ev.Opts, + utils.MetaVars: utils.MapStorage{ + utils.ProcessRuns: utils.NewNMData(0), + }, + }, utils.EmptyString) if err != nil { t.Errorf("Error: %+v", err) } @@ -2263,7 +2343,13 @@ func TestProcessAttributeDivide(t *testing.T) { }, }, } - rcv, err := attrService.processEvent(ev) + rcv, err := attrService.processEvent(ev, utils.MapStorage{ + utils.MetaReq: ev.CGREvent.Event, + utils.MetaOpts: ev.Opts, + utils.MetaVars: utils.MapStorage{ + utils.ProcessRuns: utils.NewNMData(0), + }, + }, utils.EmptyString) if err != nil { t.Errorf("Error: %+v", err) } @@ -2317,7 +2403,13 @@ func TestProcessAttributeValueExponent(t *testing.T) { }, }, } - rcv, err := attrService.processEvent(ev) + rcv, err := attrService.processEvent(ev, utils.MapStorage{ + utils.MetaReq: ev.CGREvent.Event, + utils.MetaOpts: ev.Opts, + utils.MetaVars: utils.MapStorage{ + utils.ProcessRuns: utils.NewNMData(0), + }, + }, utils.EmptyString) if err != nil { t.Errorf("Error: %+v", err) } @@ -2371,7 +2463,13 @@ func TestProcessAttributeUnixTimeStamp(t *testing.T) { }, }, } - rcv, err := attrService.processEvent(ev) + rcv, err := attrService.processEvent(ev, utils.MapStorage{ + utils.MetaReq: ev.CGREvent.Event, + utils.MetaOpts: ev.Opts, + utils.MetaVars: utils.MapStorage{ + utils.ProcessRuns: utils.NewNMData(0), + }, + }, utils.EmptyString) if err != nil { t.Errorf("Error: %+v", err) } @@ -2449,3 +2547,4 @@ func TestAttributeIndexSelectsFalse(t *testing.T) { } } +*/ diff --git a/utils/consts.go b/utils/consts.go index 0c46def0f..6c4a0c473 100755 --- a/utils/consts.go +++ b/utils/consts.go @@ -775,6 +775,7 @@ const ( APIKey = "ApiKey" RouteID = "RouteID" MetaMonthlyEstimated = "*monthly_estimated" + ProcessRuns = "ProcessRuns" ) // Migrator Action