Added *profileIgnoreFilters for attributes

This commit is contained in:
Trial97
2021-10-08 17:04:10 +03:00
committed by Dan Christian Bogos
parent 381070c8f6
commit 869da96a64
15 changed files with 143 additions and 374 deletions

View File

@@ -32,7 +32,7 @@ import (
"github.com/cgrates/cgrates/config"
"github.com/cgrates/cgrates/engine"
"github.com/cgrates/cgrates/utils"
"github.com/shopspring/decimal"
"github.com/ericlagergren/decimal"
)
var (
@@ -165,6 +165,9 @@ func testCfgGetConfig(t *testing.T) {
utils.MetaProfileRunsCfg: map[string]int{
utils.MetaDefault: 0,
},
utils.MetaProfileIgnoreFilters: map[string]bool{
utils.MetaDefault: false,
},
},
},
}
@@ -235,6 +238,9 @@ func testCfgSetGetConfig(t *testing.T) {
utils.MetaProfileRunsCfg: map[string]int{
utils.MetaDefault: 0,
},
utils.MetaProfileIgnoreFilters: map[string]bool{
utils.MetaDefault: false,
},
},
},
}
@@ -346,7 +352,7 @@ func testCfgSetJSONGetJSONConfig(t *testing.T) {
if !reflect.DeepEqual(`"OK"`, utils.ToJSON(reply)) {
t.Errorf("\nExpected <%+v>, \nReceived <%+v>", "OK", utils.ToJSON(reply))
}
expectedGet := `{"attributes":{"accounts_conns":["*internal"],"enabled":true,"indexed_selects":false,"nested_fields":false,"opts":{"*attributeIDs":{"*default":[]},"*processRuns":{"":2,"*default":2},"*profileRuns":{"*default":0}},"prefix_indexed_fields":[],"resources_conns":["*internal"],"stats_conns":["*localhost"],"suffix_indexed_fields":[]}}`
expectedGet := `{"attributes":{"accounts_conns":["*internal"],"enabled":true,"indexed_selects":false,"nested_fields":false,"opts":{"*attributeIDs":{"*default":[]},"*processRuns":{"":2,"*default":2},"*profileIgnoreFilters":{"*default":false},"*profileRuns":{"*default":0}},"prefix_indexed_fields":[],"resources_conns":["*internal"],"stats_conns":["*localhost"],"suffix_indexed_fields":[]}}`
var replyGet string
if err := cfgRPC.Call(context.Background(), utils.ConfigSv1GetConfigAsJSON,
&config.SectionWithAPIOpts{
@@ -525,6 +531,9 @@ func testCfgSetGetConfigStore(t *testing.T) {
utils.MetaProfileRunsCfg: map[string]int{
utils.MetaDefault: 0,
},
utils.MetaProfileIgnoreFilters: map[string]bool{
utils.MetaDefault: false,
},
},
},
}
@@ -631,6 +640,9 @@ func testCfgGetAfterReloadStore(t *testing.T) {
utils.MetaProfileRunsCfg: map[string]int{
utils.MetaDefault: 0,
},
utils.MetaProfileIgnoreFilters: map[string]bool{
utils.MetaDefault: false,
},
},
},
}

View File

@@ -83,6 +83,9 @@ func TestConfigSetGetConfig(t *testing.T) {
utils.MetaProfileRunsCfg: map[string]int{
utils.MetaDefault: 0,
},
utils.MetaProfileIgnoreFilters: map[string]bool{
utils.MetaDefault: false,
},
},
},
}
@@ -158,6 +161,9 @@ func TestConfigSetGetReloadConfig(t *testing.T) {
utils.MetaProfileRunsCfg: map[string]int{
utils.MetaDefault: 0,
},
utils.MetaProfileIgnoreFilters: map[string]bool{
utils.MetaDefault: false,
},
},
},
}
@@ -207,6 +213,9 @@ func TestConfigSetGetReloadConfig(t *testing.T) {
utils.MetaProfileRunsCfg: map[string]int{
utils.MetaDefault: 0,
},
utils.MetaProfileIgnoreFilters: map[string]bool{
utils.MetaDefault: false,
},
},
},
}
@@ -250,7 +259,7 @@ func TestConfigGetSetConfigFromJSONErr(t *testing.T) {
}
var replyGet string
errGet := rlcCfg.GetConfigAsJSON(context.Background(), argsGet, &replyGet)
expectedGet := `{"attributes":{"accounts_conns":["*localhost"],"enabled":true,"indexed_selects":true,"nested_fields":false,"opts":{"*attributeIDs":{"*default":[]},"*processRuns":{"*default":1},"*profileRuns":{"*default":0}},"prefix_indexed_fields":[],"resources_conns":["*localhost"],"stats_conns":["*localhost"],"suffix_indexed_fields":[]}}`
expectedGet := `{"attributes":{"accounts_conns":["*localhost"],"enabled":true,"indexed_selects":true,"nested_fields":false,"opts":{"*attributeIDs":{"*default":[]},"*processRuns":{"*default":1},"*profileIgnoreFilters":{"*default":false},"*profileRuns":{"*default":0}},"prefix_indexed_fields":[],"resources_conns":["*localhost"],"stats_conns":["*localhost"],"suffix_indexed_fields":[]}}`
if err != nil {
t.Errorf("Expected <%+v>, \nReceived <%+v>", nil, errGet)
}

View File

@@ -24,9 +24,10 @@ import (
)
type AttributesOpts struct {
AttributeIDs []*utils.DynamicStringSliceOpt
ProcessRuns []*utils.DynamicIntOpt
ProfileRuns []*utils.DynamicIntOpt
AttributeIDs []*utils.DynamicStringSliceOpt
ProcessRuns []*utils.DynamicIntOpt
ProfileRuns []*utils.DynamicIntOpt
ProfileIgnoreFilters []*utils.DynamicBoolOpt
}
// AttributeSCfg is the configuration of attribute service
@@ -65,6 +66,9 @@ func (attrOpts *AttributesOpts) loadFromJSONCfg(jsnCfg *AttributesOptsJson) {
if jsnCfg.ProfileRuns != nil {
attrOpts.ProfileRuns = append(attrOpts.ProfileRuns, utils.MapToDynamicIntOpts(jsnCfg.ProfileRuns)...)
}
if jsnCfg.ProfileIgnoreFilters != nil {
attrOpts.ProfileIgnoreFilters = append(attrOpts.ProfileIgnoreFilters, utils.MapToDynamicBoolOpts(jsnCfg.ProfileIgnoreFilters)...)
}
}
func (alS *AttributeSCfg) loadFromJSONCfg(jsnCfg *AttributeSJsonCfg) (err error) {
@@ -107,9 +111,10 @@ func (alS *AttributeSCfg) loadFromJSONCfg(jsnCfg *AttributeSJsonCfg) (err error)
// AsMapInterface returns the config as a map[string]interface{}
func (alS AttributeSCfg) AsMapInterface(string) interface{} {
opts := map[string]interface{}{
utils.MetaAttributeIDsCfg: utils.DynamicStringSliceOptsToMap(alS.Opts.AttributeIDs),
utils.MetaProcessRunsCfg: utils.DynamicIntOptsToMap(alS.Opts.ProcessRuns),
utils.MetaProfileRunsCfg: utils.DynamicIntOptsToMap(alS.Opts.ProfileRuns),
utils.MetaAttributeIDsCfg: utils.DynamicStringSliceOptsToMap(alS.Opts.AttributeIDs),
utils.MetaProcessRunsCfg: utils.DynamicIntOptsToMap(alS.Opts.ProcessRuns),
utils.MetaProfileRunsCfg: utils.DynamicIntOptsToMap(alS.Opts.ProfileRuns),
utils.MetaProfileIgnoreFilters: utils.DynamicBoolOptsToMap(alS.Opts.ProfileIgnoreFilters),
}
mp := map[string]interface{}{
utils.EnabledCfg: alS.Enabled,
@@ -152,10 +157,15 @@ func (attrOpts AttributesOpts) Clone() *AttributesOpts {
if attrOpts.ProfileRuns != nil {
profileRuns = utils.CloneDynamicIntOpt(attrOpts.ProfileRuns)
}
var profileIgnoreFilters []*utils.DynamicBoolOpt
if attrOpts.ProfileRuns != nil {
profileIgnoreFilters = utils.CloneDynamicBoolOpt(attrOpts.ProfileIgnoreFilters)
}
return &AttributesOpts{
AttributeIDs: attrIDs,
ProcessRuns: processRuns,
ProfileRuns: profileRuns,
AttributeIDs: attrIDs,
ProcessRuns: processRuns,
ProfileRuns: profileRuns,
ProfileIgnoreFilters: profileIgnoreFilters,
}
}
@@ -193,9 +203,10 @@ func (alS AttributeSCfg) Clone() (cln *AttributeSCfg) {
}
type AttributesOptsJson struct {
AttributeIDs map[string][]string `json:"*attributeIDs"`
ProcessRuns map[string]int `json:"*processRuns"`
ProfileRuns map[string]int `json:"*profileRuns"`
AttributeIDs map[string][]string `json:"*attributeIDs"`
ProcessRuns map[string]int `json:"*processRuns"`
ProfileRuns map[string]int `json:"*profileRuns"`
ProfileIgnoreFilters map[string]bool `json:"*profileIgnoreFilters"`
}
// Attribute service config section
@@ -225,6 +236,9 @@ func diffAttributesOptsJsonCfg(d *AttributesOptsJson, v1, v2 *AttributesOpts) *A
if !utils.DynamicIntOptEqual(v1.ProfileRuns, v2.ProfileRuns) {
d.ProfileRuns = utils.DynamicIntOptsToMap(v2.ProfileRuns)
}
if !utils.DynamicBoolOptEqual(v1.ProfileIgnoreFilters, v2.ProfileIgnoreFilters) {
d.ProfileIgnoreFilters = utils.DynamicBoolOptsToMap(v2.ProfileIgnoreFilters)
}
return d
}

View File

@@ -65,6 +65,12 @@ func TestAttributeSCfgloadFromJsonCfg(t *testing.T) {
Value: 0,
},
},
ProfileIgnoreFilters: []*utils.DynamicBoolOpt{
{
FilterIDs: []string{utils.MetaDefault},
Value: false,
},
},
},
}
jsnCfg := NewDefaultCGRConfig()
@@ -111,6 +117,9 @@ func TestAttributeSCfgAsMapInterface(t *testing.T) {
utils.MetaProfileRunsCfg: map[string]int{
utils.MetaDefault: 0,
},
utils.MetaProfileIgnoreFilters: map[string]bool{
utils.MetaDefault: false,
},
},
}
if cgrCfg, err := NewCGRConfigFromJSONStringWithDefaults(cfgJSONStr); err != nil {
@@ -152,6 +161,9 @@ func TestAttributeSCfgAsMapInterface2(t *testing.T) {
utils.MetaProfileRunsCfg: map[string]int{
utils.MetaDefault: 0,
},
utils.MetaProfileIgnoreFilters: map[string]bool{
utils.MetaDefault: false,
},
},
}
if cgrCfg, err := NewCGRConfigFromJSONStringWithDefaults(cfgJSONStr); err != nil {
@@ -186,6 +198,9 @@ func TestAttributeSCfgAsMapInterface3(t *testing.T) {
utils.MetaProfileRunsCfg: map[string]int{
utils.MetaDefault: 0,
},
utils.MetaProfileIgnoreFilters: map[string]bool{
utils.MetaDefault: false,
},
},
}
if conv, err := NewCGRConfigFromJSONStringWithDefaults(myJSONStr); err != nil {

View File

@@ -701,7 +701,10 @@ const CGRATES_CFG_JSON = `
},
"*profileRuns": { // number of runs a profile will process during the event
"*default": 0,
},
},
"*profileIgnoreFilters": { // if we should check the filters
"*default": false,
}
},
},

View File

@@ -173,6 +173,12 @@ func testCGRConfigReloadAttributeS(t *testing.T) {
Value: 0,
},
},
ProfileIgnoreFilters: []*utils.DynamicBoolOpt{
{
FilterIDs: []string{utils.MetaDefault},
Value: false,
},
},
},
}
if !reflect.DeepEqual(expAttr, cfg.AttributeSCfg()) {
@@ -226,6 +232,12 @@ func testCGRConfigReloadAttributeSWithDB(t *testing.T) {
Value: 0,
},
},
ProfileIgnoreFilters: []*utils.DynamicBoolOpt{
{
FilterIDs: []string{utils.MetaDefault},
Value: false,
},
},
},
}
if !reflect.DeepEqual(expAttr, cfg.AttributeSCfg()) {

View File

@@ -803,6 +803,9 @@ func TestDfAttributeServJsonCfg(t *testing.T) {
ProfileRuns: map[string]int{
utils.MetaDefault: 0,
},
ProfileIgnoreFilters: map[string]bool{
utils.MetaDefault: false,
},
},
}
dfCgrJSONCfg, err := NewCgrJsonCfgFromBytes([]byte(CGRATES_CFG_JSON))

File diff suppressed because one or more lines are too long

View File

@@ -56,7 +56,7 @@ func (alS *AttributeService) Shutdown() {
// attributeProfileForEvent returns the matching attribute
func (alS *AttributeService) attributeProfileForEvent(ctx *context.Context, tnt string, attrsIDs []string,
evNm utils.MapStorage, lastID string, processedPrfNo map[string]int, profileRuns int) (matchAttrPrfl *AttributeProfile, err error) {
evNm utils.MapStorage, lastID string, processedPrfNo map[string]int, profileRuns int, ignoreFilters bool) (matchAttrPrfl *AttributeProfile, err error) {
var attrIDs []string
if len(attrsIDs) != 0 {
attrIDs = attrsIDs
@@ -84,11 +84,13 @@ func (alS *AttributeService) attributeProfileForEvent(ctx *context.Context, tnt
}
tntID := aPrfl.TenantIDInline()
(evNm[utils.MetaVars].(utils.MapStorage))[utils.MetaAttrPrfTenantID] = tntID
if pass, err := alS.filterS.Pass(ctx, tnt, aPrfl.FilterIDs,
evNm); err != nil {
return nil, err
} else if !pass {
continue
if len(attrsIDs) == 0 || !ignoreFilters {
if pass, err := alS.filterS.Pass(ctx, tnt, aPrfl.FilterIDs,
evNm); err != nil {
return nil, err
} else if !pass {
continue
}
}
if (matchAttrPrfl == nil || matchAttrPrfl.Weight < aPrfl.Weight) &&
tntID != lastID &&
@@ -137,8 +139,13 @@ func (alS *AttributeService) processEvent(ctx *context.Context, tnt string, args
utils.OptsAttributesAttributeIDs); err != nil {
return
}
var ignFilters bool
if ignFilters, err = GetBoolOpts(ctx, tnt, args, alS.filterS, alS.cgrcfg.AttributeSCfg().Opts.ProfileIgnoreFilters,
utils.MetaProfileIgnoreFilters); err != nil {
return
}
var attrPrf *AttributeProfile
if attrPrf, err = alS.attributeProfileForEvent(ctx, tnt, attrIDs, evNm, lastID, processedPrfNo, profileRuns); err != nil {
if attrPrf, err = alS.attributeProfileForEvent(ctx, tnt, attrIDs, evNm, lastID, processedPrfNo, profileRuns, ignFilters); err != nil {
return
}
rply = &AttrSProcessEventReply{
@@ -212,13 +219,18 @@ func (alS *AttributeService) V1GetAttributeForEvent(ctx *context.Context, args *
utils.OptsAttributesAttributeIDs); err != nil {
return
}
var ignFilters bool
if ignFilters, err = GetBoolOpts(ctx, tnt, args, alS.filterS, alS.cgrcfg.AttributeSCfg().Opts.ProfileIgnoreFilters,
utils.MetaProfileIgnoreFilters); err != nil {
return
}
attrPrf, err := alS.attributeProfileForEvent(ctx, tnt, attrIDs, utils.MapStorage{
utils.MetaReq: args.Event,
utils.MetaOpts: args.APIOpts,
utils.MetaVars: utils.MapStorage{
utils.OptsAttributesProcessRuns: 0,
},
}, utils.EmptyString, make(map[string]int), 0)
}, utils.EmptyString, make(map[string]int), 0, ignFilters)
if err != nil {
if err != utils.ErrNotFound {
err = utils.NewErrServerError(err)

View File

@@ -432,7 +432,7 @@ func TestAttributesattributeProfileForEventNoDBConn(t *testing.T) {
lastID := ""
alS.dm = nil
if rcv, err := alS.attributeProfileForEvent(context.Background(), tnt, []string{"ATTR_3"}, evNm, lastID, make(map[string]int), 0); err == nil || err != utils.ErrNoDatabaseConn {
if rcv, err := alS.attributeProfileForEvent(context.Background(), tnt, []string{"ATTR_3"}, evNm, lastID, make(map[string]int), 0, false); err == nil || err != utils.ErrNoDatabaseConn {
t.Errorf("\nexpected: <%+v>, \nreceived: <%+v>", utils.ErrNoDatabaseConn, err)
} else if rcv != nil {
t.Errorf("\nexpected: <%+v>, \nreceived: <%+v>", nil, rcv)
@@ -470,7 +470,7 @@ func TestAttributesattributeProfileForEventErrNotFound(t *testing.T) {
}
lastID := ""
if rcv, err := alS.attributeProfileForEvent(context.Background(), tnt, []string{"ATTR_3"}, evNm, lastID, make(map[string]int), 0); err == nil || err != utils.ErrNotFound {
if rcv, err := alS.attributeProfileForEvent(context.Background(), tnt, []string{"ATTR_3"}, evNm, lastID, make(map[string]int), 0, false); err == nil || err != utils.ErrNotFound {
t.Errorf("\nexpected: <%+v>, \nreceived: <%+v>", utils.ErrNotFound, err)
} else if rcv != nil {
t.Errorf("\nexpected: <%+v>, \nreceived: <%+v>", nil, rcv)
@@ -529,7 +529,7 @@ func TestAttributesattributeProfileForEventErrPass(t *testing.T) {
utils.MetaVars: utils.MapStorage{},
}
if rcv, err := alS.attributeProfileForEvent(context.Background(), tnt, []string{"ATTR_1"}, evNm, lastID, make(map[string]int), 0); err == nil || err != utils.ErrWrongPath {
if rcv, err := alS.attributeProfileForEvent(context.Background(), tnt, []string{"ATTR_1"}, evNm, lastID, make(map[string]int), 0, false); err == nil || err != utils.ErrWrongPath {
t.Errorf("\nexpected: <%+v>, \nreceived: <%+v>", utils.ErrWrongPath, err)
} else if rcv != nil {
t.Errorf("\nexpected: <%+v>, \nreceived: <%+v>", nil, rcv)

View File

@@ -229,7 +229,7 @@ func TestAttributeProfileForEvent(t *testing.T) {
utils.MetaVars: utils.MapStorage{
utils.OptsAttributesProcessRuns: 0,
},
}, utils.EmptyString, make(map[string]int), 0)
}, utils.EmptyString, make(map[string]int), 0, false)
if err != nil {
t.Errorf("Error: %+v", err)
}
@@ -248,7 +248,7 @@ func TestAttributeProfileForEvent(t *testing.T) {
utils.MetaVars: utils.MapStorage{
utils.OptsAttributesProcessRuns: 0,
},
}, utils.EmptyString, make(map[string]int), 0)
}, utils.EmptyString, make(map[string]int), 0, false)
if err != nil {
t.Errorf("Error: %+v", err)
}
@@ -267,7 +267,7 @@ func TestAttributeProfileForEvent(t *testing.T) {
utils.MetaVars: utils.MapStorage{
utils.OptsAttributesProcessRuns: 0,
},
}, utils.EmptyString, make(map[string]int), 0)
}, utils.EmptyString, make(map[string]int), 0, false)
if err != nil {
t.Errorf("Error: %+v", err)
}

1
go.mod
View File

@@ -50,7 +50,6 @@ require (
github.com/pierrec/lz4 v2.6.0+incompatible // indirect
github.com/rivo/uniseg v0.2.0 // indirect
github.com/segmentio/kafka-go v0.4.8
github.com/shopspring/decimal v0.0.0-20200227202807-02e2044944cc
github.com/streadway/amqp v1.0.0
github.com/tinylib/msgp v1.1.5 // indirect
github.com/willf/bitset v1.1.11 // indirect

View File

@@ -1678,11 +1678,7 @@ func (sS *SessionS) BiRPCv1AuthorizeEvent(ctx *context.Context,
return
}
if thdS {
var thIDs []string
if thIDs, err = utils.OptAsStringSlice(args.APIOpts, utils.OptsSesThresholdIDs); err != nil {
return
}
tIDs, err := sS.processThreshold(ctx, args, thIDs, true)
tIDs, err := sS.processThreshold(ctx, args, true)
if err != nil && err.Error() != utils.ErrNotFound.Error() {
utils.Logger.Warning(
fmt.Sprintf("<%s> error: %s processing event %+v with ThresholdS.",
@@ -1703,11 +1699,7 @@ func (sS *SessionS) BiRPCv1AuthorizeEvent(ctx *context.Context,
return
}
if stS {
var statIDs []string
if statIDs, err = utils.OptAsStringSlice(args.APIOpts, utils.OptsSesStatIDs); err != nil {
return
}
sIDs, err := sS.processStats(ctx, args, statIDs, false)
sIDs, err := sS.processStats(ctx, args, false)
if err != nil &&
err.Error() != utils.ErrNotFound.Error() {
utils.Logger.Warning(
@@ -1927,11 +1919,7 @@ func (sS *SessionS) BiRPCv1InitiateSession(ctx *context.Context,
return
}
if thdS {
var thIDs []string
if thIDs, err = utils.OptAsStringSlice(args.APIOpts, utils.OptsSesThresholdIDs); err != nil {
return
}
tIDs, err := sS.processThreshold(ctx, args, thIDs, true)
tIDs, err := sS.processThreshold(ctx, args, true)
if err != nil && err.Error() != utils.ErrNotFound.Error() {
utils.Logger.Warning(
fmt.Sprintf("<%s> error: %s processing event %+v with ThresholdS.",
@@ -1952,11 +1940,7 @@ func (sS *SessionS) BiRPCv1InitiateSession(ctx *context.Context,
return
}
if stS {
var statIDs []string
if statIDs, err = utils.OptAsStringSlice(args.APIOpts, utils.OptsSesStatIDs); err != nil {
return
}
sIDs, err := sS.processStats(ctx, args, statIDs, false)
sIDs, err := sS.processStats(ctx, args, false)
if err != nil &&
err.Error() != utils.ErrNotFound.Error() {
utils.Logger.Warning(
@@ -2219,11 +2203,7 @@ func (sS *SessionS) BiRPCv1TerminateSession(ctx *context.Context,
return
}
if thdS {
var thIDs []string
if thIDs, err = utils.OptAsStringSlice(args.APIOpts, utils.OptsSesThresholdIDs); err != nil {
return
}
_, err := sS.processThreshold(ctx, args, thIDs, true)
_, err := sS.processThreshold(ctx, args, true)
if err != nil &&
err.Error() != utils.ErrNotFound.Error() {
utils.Logger.Warning(
@@ -2244,11 +2224,7 @@ func (sS *SessionS) BiRPCv1TerminateSession(ctx *context.Context,
return
}
if stS {
var statIDs []string
if statIDs, err = utils.OptAsStringSlice(args.APIOpts, utils.OptsSesStatIDs); err != nil {
return
}
_, err := sS.processStats(ctx, args, statIDs, false)
_, err := sS.processStats(ctx, args, false)
if err != nil &&
err.Error() != utils.ErrNotFound.Error() {
utils.Logger.Warning(
@@ -2408,11 +2384,7 @@ func (sS *SessionS) BiRPCv1ProcessMessage(ctx *context.Context,
return
}
if thdS {
var thIDs []string
if thIDs, err = utils.OptAsStringSlice(args.APIOpts, utils.OptsSesThresholdIDs); err != nil {
return
}
tIDs, err := sS.processThreshold(ctx, args, thIDs, true)
tIDs, err := sS.processThreshold(ctx, args, true)
if err != nil && err.Error() != utils.ErrNotFound.Error() {
utils.Logger.Warning(
fmt.Sprintf("<%s> error: %s processing event %+v with ThresholdS.",
@@ -2433,11 +2405,7 @@ func (sS *SessionS) BiRPCv1ProcessMessage(ctx *context.Context,
return
}
if stS {
var stIDs []string
if stIDs, err = utils.OptAsStringSlice(args.APIOpts, utils.OptsSesStatIDs); err != nil {
return
}
sIDs, err := sS.processStats(ctx, args, stIDs, false)
sIDs, err := sS.processStats(ctx, args, false)
if err != nil &&
err.Error() != utils.ErrNotFound.Error() {
utils.Logger.Warning(
@@ -2574,12 +2542,8 @@ func (sS *SessionS) BiRPCv1ProcessEvent(ctx *context.Context,
}
if thdS {
rply.ThresholdIDs = make(map[string][]string)
var thIDs []string
if thIDs, err = utils.OptAsStringSlice(args.APIOpts, utils.OptsSesThresholdIDs); err != nil {
return
}
for runID, cgrEv := range getDerivedEvents(events, utils.OptAsBool(args.APIOpts, utils.OptsSesThresholdSDerivedReply)) {
tIDs, err := sS.processThreshold(ctx, cgrEv, thIDs, true)
tIDs, err := sS.processThreshold(ctx, cgrEv, true)
if err != nil && err.Error() != utils.ErrNotFound.Error() {
if blockError {
return utils.NewErrThresholdS(err)
@@ -2607,12 +2571,8 @@ func (sS *SessionS) BiRPCv1ProcessEvent(ctx *context.Context,
}
if stS {
rply.StatQueueIDs = make(map[string][]string)
var stIDs []string
if stIDs, err = utils.OptAsStringSlice(args.APIOpts, utils.OptsSesStatIDs); err != nil {
return
}
for runID, cgrEv := range getDerivedEvents(events, utils.OptAsBool(args.APIOpts, utils.OptsSesStatSDerivedReply)) {
sIDs, err := sS.processStats(ctx, cgrEv, stIDs, true)
sIDs, err := sS.processStats(ctx, cgrEv, true)
if err != nil &&
err.Error() != utils.ErrNotFound.Error() {
if blockError {
@@ -3041,14 +3001,10 @@ func (sS *SessionS) processCDR(ctx *context.Context, cgrEv *utils.CGREvent, rply
}
// processThreshold will receive the event and send it to ThresholdS to be processed
func (sS *SessionS) processThreshold(ctx *context.Context, cgrEv *utils.CGREvent, thIDs []string, clnb bool) (tIDs []string, err error) {
func (sS *SessionS) processThreshold(ctx *context.Context, cgrEv *utils.CGREvent, clnb bool) (tIDs []string, err error) {
if len(sS.cgrCfg.SessionSCfg().ThresholdSConns) == 0 {
return tIDs, utils.NewErrNotConnected(utils.ThresholdS)
}
// check if we have thresholdIDs
if len(thIDs) != 0 {
cgrEv.APIOpts[utils.OptsThresholdsThresholdIDs] = thIDs
}
cgrEv.SetCloneable(clnb)
//initialize the returned variable
err = sS.connMgr.Call(ctx, sS.cgrCfg.SessionSCfg().ThresholdSConns, utils.ThresholdSv1ProcessEvent, cgrEv, &tIDs)
@@ -3056,7 +3012,7 @@ func (sS *SessionS) processThreshold(ctx *context.Context, cgrEv *utils.CGREvent
}
// processStats will receive the event and send it to StatS to be processed
func (sS *SessionS) processStats(ctx *context.Context, cgrEv *utils.CGREvent, stsIDs []string, clnb bool) (sIDs []string, err error) {
func (sS *SessionS) processStats(ctx *context.Context, cgrEv *utils.CGREvent, clnb bool) (sIDs []string, err error) {
if len(sS.cgrCfg.SessionSCfg().StatSConns) == 0 {
return sIDs, utils.NewErrNotConnected(utils.StatS)
}
@@ -3064,10 +3020,6 @@ func (sS *SessionS) processStats(ctx *context.Context, cgrEv *utils.CGREvent, st
statArgs := &engine.StatsArgsProcessEvent{
CGREvent: cgrEv,
}
// check in case we have StatIDs inside flags
if len(stsIDs) != 0 {
cgrEv.APIOpts[utils.OptsStatsStatIDs] = stsIDs
}
statArgs.SetCloneable(clnb)
//initialize the returned variable
err = sS.connMgr.Call(ctx, sS.cgrCfg.SessionSCfg().StatSConns, utils.StatSv1ProcessEvent, statArgs, &sIDs)

View File

@@ -2168,13 +2168,12 @@ var CGROptionsSet = NewStringSet([]string{OptsRatesRateProfileIDs, OptsRatesStar
OptsAttributeS, OptsSesAttributeSDerivedReply, OptsSesBlockerError, OptsRoutesUsage,
OptsCDRs, OptsSesCDRsDerivedReply, OptsChargerS, OptsResourceS, OptsSesResourceSAuthorize,
OptsSesResourceSAlocate, OptsSesResourceSRelease, OptsSesResourceSDerivedReply, OptsRouteS,
OptsSesRouteSDerivedReply, OptsSesRouteSIgnoreErrors, OptsSesRouteSMaxCost, OptsStatS,
OptsSesStatSDerivedReply, OptsSesStatIDs, OptsSesSTIRAuthenticate, OptsSesSTIRDerivedReply,
OptsSesSTIRInitiate, OptsThresholdS, OptsSesThresholdSDerivedReply, OptsSesThresholdIDs,
OptsSesRouteSDerivedReply, OptsStatS, OptsSesStatSDerivedReply, OptsSesSTIRAuthenticate, OptsSesSTIRDerivedReply,
OptsSesSTIRInitiate, OptsThresholdS, OptsSesThresholdSDerivedReply,
OptsSesMaxUsage, OptsSesForceDuration, OptsSesInitiate, OptsSesUpdate, OptsSesTerminate,
OptsSesMessage, OptsAttributeS, OptsChargerS, OptsCDRsExport, OptsCDRsRefund,
OptsCDRsRerate, OptsStatS, OptsCDRsStore, OptsThresholdS, OptsRateS, OptsAccountS,
OptsAccountsUsage, OptsStatsStatIDs, OptsActionsActionProfileIDs})
OptsAccountsUsage, OptsStatsStatIDs, OptsActionsActionProfileIDs, MetaProfileIgnoreFilters})
// Event Opts
const (
@@ -2206,15 +2205,11 @@ const (
OptsSesResourceSRelease = "*sesResourceSRelease"
OptsSesResourceSDerivedReply = "*sesResourceSDerivedReply"
OptsSesRouteSDerivedReply = "*sesRouteSDerivedReply"
OptsSesRouteSIgnoreErrors = "*sesRouteSIgnoreErrors"
OptsSesRouteSMaxCost = "*sesRouteSMaxCost"
OptsSesStatSDerivedReply = "*sesStatSDerivedReply"
OptsSesStatIDs = "*sesStatIDs"
OptsSesSTIRAuthenticate = "*sesSTIRAuthenticate"
OptsSesSTIRDerivedReply = "*sesSTIRDerivedReply"
OptsSesSTIRInitiate = "*sesSTIRInitiate"
OptsSesThresholdSDerivedReply = "*sesThresholdSDerivedReply"
OptsSesThresholdIDs = "*sesThresholdIDs"
OptsSesMaxUsage = "*sesMaxUsage"
OptsSesForceDuration = "*sesForceDuration"
OptsSesInitiate = "*sesInitiate"
@@ -2286,12 +2281,13 @@ const (
OptsStirPrivateKeyPath = "*stirPrivateKeyPath"
// Others
OptsContext = "*context"
Subsys = "*subsys"
MetaMethod = "*reqMethod"
MetaEventType = "*eventType"
EventType = "EventType"
SchedulerInit = "SchedulerInit"
OptsContext = "*context"
Subsys = "*subsys"
MetaMethod = "*reqMethod"
MetaEventType = "*eventType"
EventType = "EventType"
SchedulerInit = "SchedulerInit"
MetaProfileIgnoreFilters = "*profileIgnoreFilters"
RemoteHostOpt = "*rmtHost"
CacheOpt = "*cache"

View File

@@ -25,7 +25,6 @@ import (
"time"
"github.com/cgrates/cron"
"github.com/ericlagergren/decimal"
)
func TestLibratesTenantID(t *testing.T) {
@@ -779,227 +778,6 @@ func TestRateProfileRunTimesPassingActivationTIme(t *testing.T) {
}
}
func TestCostForIntervals(t *testing.T) {
minDecimal, err := NewDecimalFromUsage("1m")
if err != nil {
t.Error(err)
}
secDecimal, err := NewDecimalFromUsage("1s")
if err != nil {
t.Error(err)
}
rt0 := &Rate{
ID: "RATE0",
IntervalRates: []*IntervalRate{
{
IntervalStart: NewDecimal(0, 0),
Unit: minDecimal,
Increment: minDecimal,
RecurrentFee: NewDecimal(24, 1),
},
{
IntervalStart: NewDecimal(int64(60*time.Second), 0),
Unit: minDecimal,
Increment: secDecimal,
RecurrentFee: NewDecimal(24, 1),
},
},
}
rt0.Compile()
rt1 := &Rate{
ID: "RATE1",
IntervalRates: []*IntervalRate{
{
IntervalStart: NewDecimal(0, 0),
Unit: minDecimal,
Increment: secDecimal,
RecurrentFee: NewDecimal(12, 1),
},
{
IntervalStart: NewDecimal(int64(2*time.Minute), 0),
Unit: minDecimal,
Increment: secDecimal,
RecurrentFee: NewDecimal(6, 1),
},
},
}
rt1.Compile()
rtsMap := map[string]*IntervalRate{
"RATE0_0": rt0.IntervalRates[0],
"RATE0_1": rt0.IntervalRates[1],
"RATE1_0": rt1.IntervalRates[0],
"RATE1_1": rt1.IntervalRates[1],
}
rtIvls := []*RateSInterval{
{
IntervalStart: NewDecimal(0, 0),
Increments: []*RateSIncrement{
{
IncrementStart: NewDecimal(0, 0),
Usage: NewDecimal(int64(time.Minute), 0),
RateIntervalIndex: 0,
RateID: "RATE0_0",
CompressFactor: 1,
},
{
IncrementStart: NewDecimal(int64(time.Minute), 0),
Usage: NewDecimal(int64(30*time.Second), 0),
RateIntervalIndex: 1,
RateID: "RATE0_1",
CompressFactor: 30,
},
},
CompressFactor: 1,
},
{
IntervalStart: NewDecimal(int64(90*time.Second), 0),
Increments: []*RateSIncrement{
{
IncrementStart: NewDecimal(int64(90*time.Second), 0),
Usage: NewDecimal(int64(30*time.Second), 0),
RateIntervalIndex: 0,
RateID: "RATE1_0",
CompressFactor: 30,
},
{
IncrementStart: NewDecimal(int64(2*time.Minute), 0),
Usage: NewDecimal(int64(10*time.Minute), 0),
RateIntervalIndex: 1,
RateID: "RATE1_1",
CompressFactor: 10,
},
},
CompressFactor: 1,
},
}
eDcml, _ := new(decimal.Big).SetFloat64(4.3).Float64()
cost := CostForIntervals(rtIvls, rtsMap)
if costFlt, _ := cost.Float64(); costFlt != eDcml {
t.Errorf("eDcml: %f, received: %+v", eDcml, cost)
}
}
func TestCostForIntervalsWIthFixedFee(t *testing.T) {
minDecimal, err := NewDecimalFromUsage("1m")
if err != nil {
t.Error(err)
}
secDecimal, err := NewDecimalFromUsage("1s")
if err != nil {
t.Error(err)
}
rt0 := &Rate{
ID: "RATE0",
IntervalRates: []*IntervalRate{
{
IntervalStart: NewDecimal(0, 0),
FixedFee: NewDecimal(4, 1),
RecurrentFee: NewDecimal(24, 1),
Unit: minDecimal,
Increment: minDecimal,
},
{
IntervalStart: NewDecimal(int64(60*time.Second), 0),
RecurrentFee: NewDecimal(24, 1),
Unit: minDecimal,
Increment: secDecimal,
},
},
}
rt0.Compile()
rt1 := &Rate{
ID: "RATE1",
IntervalRates: []*IntervalRate{
//{},
{
IntervalStart: NewDecimal(0, 0),
FixedFee: NewDecimal(2, 1),
RecurrentFee: NewDecimal(12, 1),
Unit: minDecimal,
Increment: secDecimal,
},
{
IntervalStart: NewDecimal(int64(2*time.Minute), 0),
RecurrentFee: NewDecimal(6, 1),
Unit: minDecimal,
Increment: secDecimal,
},
},
}
rt1.Compile()
rtsMap := map[string]*IntervalRate{
"RATE0_0": rt0.IntervalRates[0],
"RATE0_1": rt0.IntervalRates[1],
"RATE1_0": rt1.IntervalRates[0],
"RATE1_1": rt1.IntervalRates[1],
}
rtIvls := []*RateSInterval{
{
IntervalStart: NewDecimal(0, 0),
Increments: []*RateSIncrement{
{ // cost 0,4
IncrementStart: NewDecimal(0, 0),
RateIntervalIndex: 0,
RateID: "RATE0_0",
CompressFactor: 1,
Usage: NewDecimal(-1, 0),
},
{ // cost 2,4
IncrementStart: NewDecimal(0, 0),
RateIntervalIndex: 0,
RateID: "RATE0_0",
CompressFactor: 1,
Usage: NewDecimal(int64(time.Minute), 0),
},
{ // cost 1,2
IncrementStart: NewDecimal(int64(time.Minute), 0),
RateIntervalIndex: 1,
RateID: "RATE0_1",
CompressFactor: 30,
Usage: NewDecimal(int64(30*time.Second), 0),
},
},
CompressFactor: 1,
},
{
IntervalStart: NewDecimal(int64(90*time.Second), 0),
Increments: []*RateSIncrement{
{ // cost 0,2
IncrementStart: NewDecimal(int64(90*time.Second), 0),
RateIntervalIndex: 0,
RateID: "RATE1_0",
CompressFactor: 1,
Usage: NewDecimal(-1, 0),
},
{ // cost 0,6
IncrementStart: NewDecimal(int64(90*time.Second), 0),
RateIntervalIndex: 0,
RateID: "RATE1_0",
CompressFactor: 30,
Usage: NewDecimal(int64(30*time.Second), 0),
},
{ // cost 0,1
IncrementStart: NewDecimal(int64(2*time.Minute), 0),
RateIntervalIndex: 1,
RateID: "RATE1_1",
CompressFactor: 10,
Usage: NewDecimal(int64(10*time.Second), 0),
},
},
CompressFactor: 1,
},
}
eDcml, _ := new(decimal.Big).SetFloat64(4.9).Float64()
cost := CostForIntervals(rtIvls, rtsMap)
if costFlt, _ := cost.Float64(); costFlt != eDcml {
t.Errorf("eDcml: %f, received: %+v", eDcml, costFlt)
}
}
func TestRateProfileCostCorrectCost(t *testing.T) {
rPrfCost := &RateProfileCost{
ID: "Test1",
@@ -1604,51 +1382,6 @@ func TestAsExtRateSIntervalErrorsCheck(t *testing.T) {
rI.Increments[0].cost = NewDecimal(0, 0).Big
}
func TestCostForIntervalsWithPartialIntervals(t *testing.T) {
rt0 := &Rate{
ID: "RT_2",
IntervalRates: []*IntervalRate{
{
IntervalStart: NewDecimal(0, 0),
RecurrentFee: NewDecimal(2, 2),
Unit: NewDecimal(int64(time.Second), 0),
Increment: NewDecimal(int64(time.Second), 0),
},
{
IntervalStart: NewDecimal(int64(time.Minute), 0),
FixedFee: NewDecimal(2, 2),
Unit: NewDecimal(int64(time.Second), 0),
Increment: NewDecimal(int64(time.Second), 0),
},
},
}
rtsMap := map[string]*IntervalRate{
"RT_2_0": rt0.IntervalRates[0],
"RT_2_1": rt0.IntervalRates[1],
}
rtIvls := []*RateSInterval{
{
IntervalStart: NewDecimal(int64(2*time.Minute), 0),
CompressFactor: 1,
Increments: []*RateSIncrement{
{
IncrementStart: NewDecimal(int64(2*time.Minute), 0),
RateIntervalIndex: 1,
RateID: "RT_2_1",
CompressFactor: 1,
Usage: NewDecimal(-1, 0),
},
},
},
}
if cost := CostForIntervals(rtIvls, rtsMap); cost.Cmp(decimal.New(2, 2)) != 0 {
t.Errorf("received cost: %s", cost)
}
}
func TestRateProfileCostEquals(t *testing.T) {
rtPrfCost := &RateProfileCost{
ID: "RATE_1",