Optimize matchItemProfileForEvent functions

This commit is contained in:
TeoV
2020-07-06 09:56:41 +03:00
committed by BuildTools
parent adb923ba67
commit 85e7148433
6 changed files with 97 additions and 47 deletions

View File

@@ -166,6 +166,8 @@ func (rpS *RouteService) matchingRouteProfilesForEvent(ev *utils.CGREvent, singl
}
if singleResult {
matchingRPrf = make([]*RouteProfile, 1)
} else {
matchingRPrf = make([]*RouteProfile, 0, len(rPrfIDs))
}
evNm := utils.MapStorage{utils.MetaReq: ev.Event}
for lpID := range rPrfIDs {

View File

@@ -151,12 +151,9 @@ func (sS *StatService) StoreStatQueue(sq *StatQueue) (err error) {
// matchingStatQueuesForEvent returns ordered list of matching resources which are active by the time of the call
func (sS *StatService) matchingStatQueuesForEvent(args *StatsArgsProcessEvent) (sqs StatQueues, err error) {
matchingSQs := make(map[string]*StatQueue)
var sqIDs []string
if len(args.StatIDs) != 0 {
sqIDs = args.StatIDs
} else {
mapIDs, err := MatchingItemIDsForEvent(args.Event,
sqIDs := utils.NewStringSet(args.StatIDs)
if len(sqIDs) == 0 {
sqIDs, err = MatchingItemIDsForEvent(args.Event,
sS.cgrcfg.StatSCfg().StringIndexedFields,
sS.cgrcfg.StatSCfg().PrefixIndexedFields,
sS.dm, utils.CacheStatFilterIndexes, args.Tenant,
@@ -164,12 +161,12 @@ func (sS *StatService) matchingStatQueuesForEvent(args *StatsArgsProcessEvent) (
sS.cgrcfg.StatSCfg().NestedFields,
)
if err != nil {
return nil, err
return
}
sqIDs = mapIDs.AsSlice()
}
evNm := utils.MapStorage{utils.MetaReq: args.Event}
for _, sqID := range sqIDs {
sqs = make(StatQueues, 0, len(sqIDs))
for sqID := range sqIDs {
sqPrfl, err := sS.dm.GetStatQueueProfile(args.Tenant, sqID, true, true, utils.NonTransactional)
if err != nil {
if err == utils.ErrNotFound {
@@ -203,15 +200,12 @@ func (sS *StatService) matchingStatQueuesForEvent(args *StatsArgsProcessEvent) (
sq.ttl = utils.DurationPointer(sqPrfl.TTL)
}
sq.sqPrfl = sqPrfl
matchingSQs[sqPrfl.ID] = sq
sqs = append(sqs, sq)
}
if len(sqs) == 0 {
return nil, utils.ErrNotFound
}
// All good, convert from Map to Slice so we can sort
sqs = make(StatQueues, len(matchingSQs))
i := 0
for _, s := range matchingSQs {
sqs[i] = s
i++
}
sqs.Sort()
for i, s := range sqs {
if s.sqPrfl.Blocker { // blocker will stop processing

View File

@@ -235,12 +235,9 @@ func (tS *ThresholdService) StoreThreshold(t *Threshold) (err error) {
// matchingThresholdsForEvent returns ordered list of matching thresholds which are active for an Event
func (tS *ThresholdService) matchingThresholdsForEvent(args *ArgsProcessEvent) (ts Thresholds, err error) {
matchingTs := make(map[string]*Threshold)
var tIDs []string
if len(args.ThresholdIDs) != 0 {
tIDs = args.ThresholdIDs
} else {
tIDsMap, err := MatchingItemIDsForEvent(args.Event,
tIDs := utils.NewStringSet(args.ThresholdIDs)
if len(tIDs) == 0 {
tIDs, err = MatchingItemIDsForEvent(args.Event,
tS.cgrcfg.ThresholdSCfg().StringIndexedFields,
tS.cgrcfg.ThresholdSCfg().PrefixIndexedFields,
tS.dm, utils.CacheThresholdFilterIndexes, args.Tenant,
@@ -250,12 +247,12 @@ func (tS *ThresholdService) matchingThresholdsForEvent(args *ArgsProcessEvent) (
if err != nil {
return nil, err
}
tIDs = tIDsMap.AsSlice()
}
evNm := utils.MapStorage{
utils.MetaReq: args.Event,
}
for _, tID := range tIDs {
ts = make(Thresholds, 0, len(tIDs))
for tID := range tIDs {
tPrfl, err := tS.dm.GetThresholdProfile(args.Tenant, tID, true, true, utils.NonTransactional)
if err != nil {
if err == utils.ErrNotFound {
@@ -281,14 +278,11 @@ func (tS *ThresholdService) matchingThresholdsForEvent(args *ArgsProcessEvent) (
t.dirty = utils.BoolPointer(false)
}
t.tPrfl = tPrfl
matchingTs[tPrfl.ID] = t
ts = append(ts, t)
}
// All good, convert from Map to Slice so we can sort
ts = make(Thresholds, len(matchingTs))
i := 0
for _, t := range matchingTs {
ts[i] = t
i++
if len(ts) == 0 {
return nil, utils.ErrNotFound
}
ts.Sort()
for i, t := range ts {

View File

@@ -1114,13 +1114,27 @@ func testITIndexRateProfile(t *testing.T) {
ID: "FIRST_GI",
FilterIDs: []string{"*string:~*req.Category:call"},
Weight: 0,
Blocker: false,
IntervalRates: []*IntervalRate{
&IntervalRate{
Value: 0.12,
Unit: time.Duration(1 * time.Minute),
Increment: time.Duration(1 * time.Minute),
},
},
Blocker: false,
},
"SECOND_GI": {
ID: "SECOND_GI",
FilterIDs: []string{"*string:~*req.Category:voice"},
Weight: 10,
Blocker: false,
IntervalRates: []*IntervalRate{
&IntervalRate{
Value: 0.06,
Unit: time.Duration(1 * time.Minute),
Increment: time.Duration(1 * time.Second),
},
},
Blocker: false,
},
},
}
@@ -1161,19 +1175,40 @@ func testITIndexRateProfile(t *testing.T) {
ID: "FIRST_GI",
FilterIDs: []string{"*string:~*req.Category:call"},
Weight: 0,
Blocker: false,
IntervalRates: []*IntervalRate{
&IntervalRate{
Value: 0.12,
Unit: time.Duration(1 * time.Minute),
Increment: time.Duration(1 * time.Minute),
},
},
Blocker: false,
},
"SECOND_GI": {
ID: "SECOND_GI",
FilterIDs: []string{"*string:~*req.Category:voice"},
Weight: 10,
Blocker: false,
IntervalRates: []*IntervalRate{
&IntervalRate{
Value: 0.06,
Unit: time.Duration(1 * time.Minute),
Increment: time.Duration(1 * time.Second),
},
},
Blocker: false,
},
"THIRD_GI": {
ID: "THIRD_GI",
FilterIDs: []string{"*string:~*req.Category:custom"},
Weight: 20,
Blocker: false,
IntervalRates: []*IntervalRate{
&IntervalRate{
Value: 0.06,
Unit: time.Duration(1 * time.Minute),
Increment: time.Duration(1 * time.Second),
},
},
Blocker: false,
},
},
}
@@ -1215,13 +1250,27 @@ func testITIndexRateProfile(t *testing.T) {
ID: "CUSTOM_RATE1",
FilterIDs: []string{"*string:~*req.Subject:1001"},
Weight: 0,
Blocker: false,
IntervalRates: []*IntervalRate{
&IntervalRate{
Value: 0.12,
Unit: time.Duration(1 * time.Minute),
Increment: time.Duration(1 * time.Minute),
},
},
Blocker: false,
},
"CUSTOM_RATE2": {
ID: "CUSTOM_RATE2",
FilterIDs: []string{"*string:~*req.Subject:1001", "*string:~*req.Category:call"},
Weight: 10,
Blocker: false,
IntervalRates: []*IntervalRate{
&IntervalRate{
Value: 0.6,
Unit: time.Duration(1 * time.Minute),
Increment: time.Duration(1 * time.Second),
},
},
Blocker: false,
},
},
}

View File

@@ -2162,13 +2162,27 @@ func testOnStorITRateProfile(t *testing.T) {
ID: "FIRST_GI",
FilterIDs: []string{"*gi:~*req.Usage:0"},
Weight: 0,
Blocker: false,
IntervalRates: []*IntervalRate{
&IntervalRate{
Value: 0.12,
Unit: time.Duration(1 * time.Minute),
Increment: time.Duration(1 * time.Minute),
},
},
Blocker: false,
},
"SECOND_GI": &Rate{
ID: "SECOND_GI",
FilterIDs: []string{"*gi:~*req.Usage:1m"},
Weight: 10,
Blocker: false,
IntervalRates: []*IntervalRate{
&IntervalRate{
Value: 0.06,
Unit: time.Duration(1 * time.Minute),
Increment: time.Duration(1 * time.Second),
},
},
Blocker: false,
},
},
}

View File

@@ -20,7 +20,6 @@ package rates
import (
"fmt"
"sort"
"time"
"github.com/cgrates/cgrates/config"
@@ -89,7 +88,6 @@ func (rS *RateS) matchingRateProfileForEvent(args *ArgsCostForEvent, rPfIDs []st
}
rPfIDs = rPfIDMp.AsSlice()
}
matchingRPfs := make([]*engine.RateProfile, 0, len(rPfIDs))
evNm := utils.MapStorage{utils.MetaReq: args.CGREvent.Event}
var sTime time.Time
if sTime, err = args.StartTime(rS.cfg.GeneralCfg().DefaultTimezone); err != nil {
@@ -115,15 +113,14 @@ func (rS *RateS) matchingRateProfileForEvent(args *ArgsCostForEvent, rPfIDs []st
} else if !pass {
continue
}
matchingRPfs = append(matchingRPfs, rPf)
if rtPfl == nil || rtPfl.Weight < rPf.Weight {
rtPfl = rPf
}
}
if len(matchingRPfs) == 0 {
if rtPfl == nil {
return nil, utils.ErrNotFound
}
sort.Slice(matchingRPfs, func(i, j int) bool {
return matchingRPfs[i].Weight > matchingRPfs[j].Weight
})
rtPfl = matchingRPfs[0]
return
}