Skip to content

Commit

Permalink
Optimize matchItemProfileForEvent functions
Browse files Browse the repository at this point in the history
  • Loading branch information
TeoV authored and BuildTools committed Jul 6, 2020
1 parent adb923b commit 85e7148
Show file tree
Hide file tree
Showing 6 changed files with 97 additions and 47 deletions.
2 changes: 2 additions & 0 deletions engine/routes.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
26 changes: 10 additions & 16 deletions engine/stats.go
Original file line number Diff line number Diff line change
Expand Up @@ -151,25 +151,22 @@ 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,
sS.cgrcfg.StatSCfg().IndexedSelects,
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 {
Expand Down Expand Up @@ -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)
}
// 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++
if len(sqs) == 0 {
return nil, utils.ErrNotFound
}
// All good, convert from Map to Slice so we can sort
sqs.Sort()
for i, s := range sqs {
if s.sqPrfl.Blocker { // blocker will stop processing
Expand Down
22 changes: 8 additions & 14 deletions engine/thresholds.go
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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 {
Expand All @@ -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 {
Expand Down
63 changes: 56 additions & 7 deletions engine/z_filterindexer_it_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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,
},
},
}
Expand Down Expand Up @@ -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,
},
},
}
Expand Down Expand Up @@ -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,
},
},
}
Expand Down
18 changes: 16 additions & 2 deletions engine/z_onstor_it_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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,
},
},
}
Expand Down
13 changes: 5 additions & 8 deletions rates/rates.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ package rates

import (
"fmt"
"sort"
"time"

"github.com/cgrates/cgrates/config"
Expand Down Expand Up @@ -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 {
Expand All @@ -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
}

Expand Down

0 comments on commit 85e7148

Please sign in to comment.