From 2a77a1036c73ec4c82d94e21e7c7bee509b8f45f Mon Sep 17 00:00:00 2001 From: TeoV Date: Mon, 25 Feb 2019 15:02:32 +0200 Subject: [PATCH] Update QOS strategy for SupplierS ( consider the worst value for stats) --- apier/v1/resourcesv1.go | 2 + engine/filters.go | 39 +- engine/filters_test.go | 38 +- engine/libsuppliers.go | 71 +--- engine/libsuppliers_test.go | 799 ++++++++++++++---------------------- engine/suppliers.go | 9 +- 6 files changed, 374 insertions(+), 584 deletions(-) diff --git a/apier/v1/resourcesv1.go b/apier/v1/resourcesv1.go index 70c88879b..427f600d8 100644 --- a/apier/v1/resourcesv1.go +++ b/apier/v1/resourcesv1.go @@ -57,6 +57,8 @@ func (rsv1 *ResourceSv1) ReleaseResources(args utils.ArgRSv1ResourceUsage, reply return rsv1.rls.V1ReleaseResource(args, reply) } +//func for getResource + // GetResourceProfile returns a resource configuration func (apierV1 *ApierV1) GetResourceProfile(arg utils.TenantID, reply *engine.ResourceProfile) error { if missing := utils.MissingStructFields(&arg, []string{"Tenant", "ID"}); len(missing) != 0 { //Params missing diff --git a/engine/filters.go b/engine/filters.go index ea87fc081..65a796410 100644 --- a/engine/filters.go +++ b/engine/filters.go @@ -46,6 +46,7 @@ const ( MetaLessOrEqual = "*lte" MetaGreaterThan = "*gt" MetaGreaterOrEqual = "*gte" + MetaResources = "*resources" MetaNotString = "*notstring" MetaNotPrefix = "*notprefix" @@ -62,6 +63,7 @@ const ( MetaNotLessOrEqual = "*notlte" MetaNotGreaterThan = "*notgt" MetaNotGreaterOrEqual = "*notgte" + MetaNotResources = "*notresources" ) func NewFilterS(cfg *config.CGRConfig, @@ -204,8 +206,9 @@ func NewFilterRule(rfType, fieldName string, vals []string) (*FilterRule, error) negative = true } if !utils.IsSliceMember([]string{MetaString, MetaPrefix, MetaSuffix, - MetaTimings, MetaRSR, MetaStatS, MetaDestinations, MetaEmpty, MetaExists, - MetaLessThan, MetaLessOrEqual, MetaGreaterThan, MetaGreaterOrEqual}, rType) { + MetaTimings, MetaRSR, MetaStatS, MetaDestinations, MetaEmpty, + MetaExists, MetaLessThan, MetaLessOrEqual, MetaGreaterThan, + MetaGreaterOrEqual, MetaResources}, rType) { return nil, fmt.Errorf("Unsupported filter Type: %s", rfType) } if fieldName == "" && utils.IsSliceMember([]string{MetaString, MetaPrefix, MetaSuffix, @@ -307,6 +310,8 @@ func (fltr *FilterRule) Pass(dP config.DataProvider, case MetaLessThan, MetaLessOrEqual, MetaGreaterThan, MetaGreaterOrEqual, MetaNotLessThan, MetaNotLessOrEqual, MetaNotGreaterThan, MetaNotGreaterOrEqual: result, err = fltr.passGreaterThan(dP) + case MetaResources, MetaNotResources: + result, err = fltr.passResourceS(dP, rpcClnt, tenant) default: err = utils.ErrPrefixNotErrNotImplemented(fltr.Type) } @@ -495,3 +500,33 @@ func (fltr *FilterRule) passGreaterThan(dP config.DataProvider) (bool, error) { } return false, nil } + +// +//Type *resources +//FieldName +//Value ResourceID: + +func (fltr *FilterRule) passResourceS(dP config.DataProvider, + resourceS rpcclient.RpcClientConnection, tenant string) (bool, error) { + // if resourceS == nil || reflect.ValueOf(resourceS).IsNil() { + // return false, errors.New("Missing ResourceS information") + // } + // for _, threshold := range fltr.statSThresholds { + // statValues := make(map[string]float64) + // if err := resourceS.Call(utils.StatSv1GetQueueFloatMetrics, &utils.TenantID{Tenant: tenant, ID: threshold.QueueID}, &statValues); err != nil { + // return false, err + // } + // val, hasIt := statValues[utils.Meta+threshold.ThresholdType[len(MetaMinCapPrefix):]] + // if !hasIt { + // continue + // } + // if strings.HasPrefix(threshold.ThresholdType, MetaMinCapPrefix) && + // val >= threshold.ThresholdValue { + // return true, nil + // } else if strings.HasPrefix(threshold.ThresholdType, MetaMaxCapPrefix) && + // val < threshold.ThresholdValue { + // return true, nil + // } + // } + return false, nil +} diff --git a/engine/filters_test.go b/engine/filters_test.go index 09195d70e..1b8345378 100644 --- a/engine/filters_test.go +++ b/engine/filters_test.go @@ -921,23 +921,18 @@ func TestPassFilterNavigableMap(t *testing.T) { dm: dmFilterPass, } - //ev1 simulate event ev1 := map[string]interface{}{ - "sampleField": "sampleValue", + "test": "call", } //ev2 simulate sortingData ev2 := map[string]interface{}{ + utils.Cost: 12.45, utils.MetaACD: SplStatMetrics{ &SplStatMetric{ StatID: utils.META_NONE, metricType: utils.MetaACD, - MetricValue: 10.0}, - }, - } - //ev3 simulate sortingData - ev3 := map[string]SplStatMetrics{ - utils.MetaACD: SplStatMetrics{ + MetricValue: 9.0}, &SplStatMetric{ StatID: utils.META_NONE, metricType: utils.MetaACD, @@ -948,27 +943,34 @@ func TestPassFilterNavigableMap(t *testing.T) { //nM simulate the DP sent to filterS in SupplierS nM := config.NewNavigableMap(nil) nM.Set([]string{utils.MetaReq}, ev1, false, false) - nM.Set([]string{utils.MetaVars}, ev2, false, false) - nM.Set([]string{"*metrics"}, newSplStsDP(ev3), false, false) + nM.Set([]string{utils.MetaVars}, convertSortingData(ev2), false, false) if pass, err := filterS.Pass("cgrates.org", - []string{"*string:*req.sampleField:sampleValue"}, nM); err != nil { + []string{"*string:*req.test:call"}, nM); err != nil { t.Errorf(err.Error()) } else if !pass { t.Errorf("Expecting: true , received: %+v", pass) } if pass, err := filterS.Pass("cgrates.org", - []string{"*gte:*metrics.*acd:10"}, nM); err != nil { + []string{"*gte:*vars.Cost:10.0"}, nM); err != nil { + t.Errorf(err.Error()) + } else if !pass { + t.Errorf("Expecting: true , received: %+v", pass) + } + + if pass, err := filterS.Pass("cgrates.org", + []string{"*gte:*vars.*acd:10.0"}, nM); err != nil { + t.Errorf(err.Error()) + } else if pass { + t.Errorf("Expecting: false , received: %+v", pass) + } + + if pass, err := filterS.Pass("cgrates.org", + []string{"*gte:*vars.*acd:9.0"}, nM); err != nil { t.Errorf(err.Error()) } else if !pass { t.Errorf("Expecting: true , received: %+v", pass) } - // if pass, err := filterS.Pass("cgrates.org", - // []string{"*gte:*vars.*acd:10"}, nM); err != nil { - // t.Errorf(err.Error()) - // } else if !pass { - // t.Errorf("Expecting: true , received: %+v", pass) - // } } diff --git a/engine/libsuppliers.go b/engine/libsuppliers.go index bfe79841a..ed54a4b5c 100644 --- a/engine/libsuppliers.go +++ b/engine/libsuppliers.go @@ -20,11 +20,9 @@ package engine import ( "fmt" - "net" "sort" "strings" - "github.com/cgrates/cgrates/config" "github.com/cgrates/cgrates/utils" ) @@ -94,15 +92,11 @@ func (sSpls *SortedSuppliers) SortHighestCost() { // SortQOS is part of sort interface, // sort based on Stats - -//map[*acd][]float64{10,20} => 10 -//map[*tcd][]float64{40,50} => 40 -//map[*pdd][]float64{40,50} => 50 func (sSpls *SortedSuppliers) SortQOS(params []string) { //sort the metrics before sorting the suppliers for _, val := range sSpls.SortedSuppliers { for _, iface := range val.SortingData { - if castedVal, canCast := iface.(SplStatMetrics); !canCast { + if castedVal, canCast := iface.(SplStatMetrics); canCast { castedVal.Sort() } } @@ -195,60 +189,17 @@ func (sm SplStatMetrics) Sort() { }) } -// newRADataProvider constructs a DataProvider -func newSplStsDP(req map[string]SplStatMetrics) (dP config.DataProvider) { - for key, _ := range req { - req[key].Sort() - } - dP = &splStsDP{req: req, cache: config.NewNavigableMap(nil)} - return -} - -type splStsDP struct { - req map[string]SplStatMetrics - cache *config.NavigableMap -} - -// String is part of engine.DataProvider interface -// when called, it will display the already parsed values out of cache -func (sm *splStsDP) String() string { - return "" -} - -// FieldAsInterface is part of engine.DataProvider interface -func (sm *splStsDP) FieldAsInterface(fldPath []string) (data interface{}, err error) { - fmt.Println("enter here ??? ") - if data, err = sm.cache.FieldAsInterface(fldPath); err != nil { - if err != utils.ErrNotFound { // item found in cache - return +// convert SortingData to map[string]interface{} with the worst value in case of stats +func convertSortingData(req map[string]interface{}) (reply map[string]interface{}) { + reply = make(map[string]interface{}) + // in case that we have metrics sort them + for key, iface := range req { + if castedVal, canCast := iface.(SplStatMetrics); canCast { + castedVal.Sort() + reply[key] = castedVal[0].MetricValue + } else { + reply[key] = iface } - err = nil // cancel previous err - } else { - return // data found in cache } - data = sm.req[fldPath[0]][0].MetricValue - sm.cache.Set(fldPath, data, false, false) return } - -// FieldAsString is part of engine.DataProvider interface -func (sm *splStsDP) FieldAsString(fldPath []string) (data string, err error) { - var valIface interface{} - valIface, err = sm.FieldAsInterface(fldPath) - if err != nil { - return - } - data, err = utils.IfaceAsString(valIface) - return -} - -// AsNavigableMap is part of engine.DataProvider interface -func (sm *splStsDP) AsNavigableMap([]*config.FCTemplate) ( - nm *config.NavigableMap, err error) { - return nil, utils.ErrNotImplemented -} - -// RemoteHost is part of engine.DataProvider interface -func (sm *splStsDP) RemoteHost() net.Addr { - return nil -} diff --git a/engine/libsuppliers_test.go b/engine/libsuppliers_test.go index dc136b16e..135d5030f 100644 --- a/engine/libsuppliers_test.go +++ b/engine/libsuppliers_test.go @@ -339,6 +339,71 @@ func TestLibSuppliersStatMetricSort2(t *testing.T) { } } +func TestLibSuppliersConvertSortingData(t *testing.T) { + //simulatedData simulate sortingData + simulatedData := map[string]interface{}{ + utils.Cost: 12.45, + utils.MetaACD: SplStatMetrics{ + &SplStatMetric{ + StatID: utils.META_NONE, + metricType: utils.MetaACD, + MetricValue: 9.0}, + &SplStatMetric{ + StatID: utils.META_NONE, + metricType: utils.MetaACD, + MetricValue: 10.0}, + }, + } + rcv := convertSortingData(simulatedData) + expected := map[string]interface{}{ + utils.Cost: 12.45, + utils.MetaACD: 9.0, + } + if !reflect.DeepEqual(expected, rcv) { + t.Errorf("Expecting: %s, received: %s", + expected, rcv) + } +} + +func TestLibSuppliersConvertSortingData2(t *testing.T) { + //simulatedData simulate sortingData + simulatedData := map[string]interface{}{ + utils.Cost: 12.45, + utils.Weight: 12.0, + utils.MetaACD: SplStatMetrics{ + &SplStatMetric{ + StatID: utils.META_NONE, + metricType: utils.MetaACD, + MetricValue: 19.0}, + &SplStatMetric{ + StatID: utils.META_NONE, + metricType: utils.MetaACD, + MetricValue: 10.0}, + }, + utils.MetaPDD: SplStatMetrics{ + &SplStatMetric{ + StatID: utils.META_NONE, + metricType: utils.MetaPDD, + MetricValue: 12.0}, + &SplStatMetric{ + StatID: utils.META_NONE, + metricType: utils.MetaPDD, + MetricValue: 5.0}, + }, + } + rcv := convertSortingData(simulatedData) + expected := map[string]interface{}{ + utils.Cost: 12.45, + utils.MetaACD: 10.0, + utils.MetaPDD: 12.0, + utils.Weight: 12.0, + } + if !reflect.DeepEqual(expected, rcv) { + t.Errorf("Expecting: %+v, received: %+v", + expected, rcv) + } +} + //sort based on *acd and *tcd func TestLibSuppliersSortQOS(t *testing.T) { sSpls := &SortedSuppliers{ @@ -429,92 +494,15 @@ func TestLibSuppliersSortQOS(t *testing.T) { //sort base on *acd and *tcd sSpls.SortQOS([]string{utils.MetaACD, utils.MetaTCD}) + rcv := make([]string, len(sSpls.SortedSuppliers)) + eIds := []string{"supplier2", "supplier1", "supplier3"} + for i, spl := range sSpls.SortedSuppliers { + rcv[i] = spl.SupplierID - eOrderedSpls := &SortedSuppliers{ - SortedSuppliers: []*SortedSupplier{ - &SortedSupplier{ - SupplierID: "supplier2", - SortingData: map[string]interface{}{ - utils.Cost: 0.1, - utils.Weight: 15.0, - utils.MetaACD: SplStatMetrics{ - &SplStatMetric{StatID: "SampleStat", - metricType: utils.MetaACD, - MetricValue: 1.1}, - &SplStatMetric{StatID: "SampleStat2", - metricType: utils.MetaACD, - MetricValue: 12.1}, - &SplStatMetric{StatID: "SampleStat3", - metricType: utils.MetaACD, - MetricValue: 0.5}, - }, - utils.MetaTCD: SplStatMetrics{ - &SplStatMetric{StatID: "SampleStat", - metricType: utils.MetaTCD, - MetricValue: 12.1}, - &SplStatMetric{StatID: "SampleStat2", - metricType: utils.MetaTCD, - MetricValue: 4.1}, - }, - }, - }, - &SortedSupplier{ - SupplierID: "supplier1", - SortingData: map[string]interface{}{ - utils.Cost: 0.5, - utils.Weight: 10.0, - utils.MetaACD: SplStatMetrics{ - &SplStatMetric{StatID: "SampleStat", - metricType: utils.MetaACD, - MetricValue: 0.5}, - &SplStatMetric{StatID: "SampleStat2", - metricType: utils.MetaACD, - MetricValue: 23.1}, - &SplStatMetric{StatID: "SampleStat3", - metricType: utils.MetaACD, - MetricValue: 10.0}, - }, - utils.MetaTCD: SplStatMetrics{ - &SplStatMetric{StatID: "SampleStat", - metricType: utils.MetaTCD, - MetricValue: 1.1}, - &SplStatMetric{StatID: "SampleStat2", - metricType: utils.MetaTCD, - MetricValue: 12.1}, - }, - }, - }, - &SortedSupplier{ - SupplierID: "supplier3", - SortingData: map[string]interface{}{ - utils.Cost: 1.1, - utils.Weight: 17.8, - utils.MetaACD: SplStatMetrics{ - &SplStatMetric{StatID: "SampleStat", - metricType: utils.MetaACD, - MetricValue: 0.4}, - &SplStatMetric{StatID: "SampleStat2", - metricType: utils.MetaACD, - MetricValue: 2.1}, - &SplStatMetric{StatID: "SampleStat3", - metricType: utils.MetaACD, - MetricValue: 0.5}, - }, - utils.MetaTCD: SplStatMetrics{ - &SplStatMetric{StatID: "SampleStat", - metricType: utils.MetaTCD, - MetricValue: 6.1}, - &SplStatMetric{StatID: "SampleStat2", - metricType: utils.MetaTCD, - MetricValue: 5.1}, - }, - }, - }, - }, } - if !reflect.DeepEqual(eOrderedSpls, sSpls) { - t.Errorf("Expecting: %s, \n received: %s", - utils.ToJSON(eOrderedSpls), utils.ToJSON(sSpls)) + if !reflect.DeepEqual(eIds, rcv) { + t.Errorf("Expecting: %+v, \n received: %+v", + eIds, rcv) } } @@ -603,86 +591,15 @@ func TestLibSuppliersSortQOS2(t *testing.T) { }, } sSpls.SortQOS([]string{utils.MetaACD, utils.MetaTCD}) - eOrderedSpls := &SortedSuppliers{ - SortedSuppliers: []*SortedSupplier{ - &SortedSupplier{ - SupplierID: "supplier3", - SortingData: map[string]interface{}{ - utils.Cost: 0.5, - utils.Weight: 10.0, - utils.MetaACD: SplStatMetrics{ - &SplStatMetric{StatID: "SampleStat", - metricType: utils.MetaACD, - MetricValue: 0.5}, - &SplStatMetric{StatID: "SampleStat2", - metricType: utils.MetaACD, - MetricValue: 0.5}, - &SplStatMetric{StatID: "SampleStat3", - metricType: utils.MetaACD, - MetricValue: 0.5}, - }, - utils.MetaTCD: SplStatMetrics{ - &SplStatMetric{StatID: "SampleStat", - metricType: utils.MetaTCD, - MetricValue: 1.2}, - }, - }, - }, - &SortedSupplier{ - SupplierID: "supplier2", - SortingData: map[string]interface{}{ - utils.Weight: 17.0, - utils.MetaACD: SplStatMetrics{ - &SplStatMetric{StatID: "SampleStat", - metricType: utils.MetaACD, - MetricValue: 0.5}, - &SplStatMetric{StatID: "SampleStat2", - metricType: utils.MetaACD, - MetricValue: 0.5}, - &SplStatMetric{StatID: "SampleStat3", - metricType: utils.MetaACD, - MetricValue: 0.5}, - }, - utils.MetaTCD: SplStatMetrics{ - &SplStatMetric{StatID: "SampleStat", - metricType: utils.MetaTCD, - MetricValue: 1.1}, - &SplStatMetric{StatID: "SampleStat2", - metricType: utils.MetaTCD, - MetricValue: 12.1}, - }, - }, - }, - &SortedSupplier{ - SupplierID: "supplier1", - SortingData: map[string]interface{}{ - utils.Weight: 10.0, - utils.MetaACD: SplStatMetrics{ - &SplStatMetric{StatID: "SampleStat", - metricType: utils.MetaACD, - MetricValue: 0.5}, - &SplStatMetric{StatID: "SampleStat2", - metricType: utils.MetaACD, - MetricValue: 0.7}, - &SplStatMetric{StatID: "SampleStat3", - metricType: utils.MetaACD, - MetricValue: 0.6}, - }, - utils.MetaTCD: SplStatMetrics{ - &SplStatMetric{StatID: "SampleStat", - metricType: utils.MetaTCD, - MetricValue: 1.1}, - &SplStatMetric{StatID: "SampleStat2", - metricType: utils.MetaTCD, - MetricValue: 12.1}, - }, - }, - }, - }, + rcv := make([]string, len(sSpls.SortedSuppliers)) + eIds := []string{"supplier3", "supplier2", "supplier1"} + for i, spl := range sSpls.SortedSuppliers { + rcv[i] = spl.SupplierID + } - if !reflect.DeepEqual(eOrderedSpls, sSpls) { - t.Errorf("Expecting: %s, received: %s", - utils.ToJSON(eOrderedSpls), utils.ToJSON(sSpls)) + if !reflect.DeepEqual(eIds, rcv) { + t.Errorf("Expecting: %+v, \n received: %+v", + eIds, rcv) } } @@ -755,143 +672,15 @@ func TestLibSuppliersSortQOS3(t *testing.T) { }, } sSpls.SortQOS([]string{utils.MetaPDD}) - eOrderedSpls := &SortedSuppliers{ - SortedSuppliers: []*SortedSupplier{ - &SortedSupplier{ - SupplierID: "supplier1", - SortingData: map[string]interface{}{ - utils.Weight: 15.0, - utils.MetaPDD: SplStatMetrics{ - &SplStatMetric{StatID: "SampleStat", - metricType: utils.MetaPDD, - MetricValue: 0.5}, - &SplStatMetric{StatID: "SampleStat2", - metricType: utils.MetaACD, - MetricValue: 0.7}, - }, - utils.MetaTCD: SplStatMetrics{ - &SplStatMetric{StatID: "SampleStat", - metricType: utils.MetaTCD, - MetricValue: 1.1}, - &SplStatMetric{StatID: "SampleStat2", - metricType: utils.MetaTCD, - MetricValue: 12.1}, - }, - }, - }, - &SortedSupplier{ - SupplierID: "supplier3", - SortingData: map[string]interface{}{ - utils.Weight: 10.0, - utils.MetaPDD: SplStatMetrics{ - &SplStatMetric{StatID: "SampleStat", - metricType: utils.MetaPDD, - MetricValue: 0.7}, - }, - utils.MetaTCD: SplStatMetrics{ - &SplStatMetric{StatID: "SampleStat", - metricType: utils.MetaTCD, - MetricValue: 10.1}, - }, - }, - }, - &SortedSupplier{ - SupplierID: "supplier2", - SortingData: map[string]interface{}{ - utils.Weight: 10.0, - utils.MetaPDD: SplStatMetrics{ - &SplStatMetric{StatID: "SampleStat", - metricType: utils.MetaPDD, - MetricValue: 0.9}, - &SplStatMetric{StatID: "SampleStat2", - metricType: utils.MetaACD, - MetricValue: 1.2}, - }, - utils.MetaTCD: SplStatMetrics{ - &SplStatMetric{StatID: "SampleStat", - metricType: utils.MetaTCD, - MetricValue: 1.1}, - }, - }, - }, - }, - } - if !reflect.DeepEqual(eOrderedSpls, sSpls) { - t.Errorf("Expecting: %s, received: %s", - utils.ToJSON(eOrderedSpls), utils.ToJSON(sSpls)) - } -} + rcv := make([]string, len(sSpls.SortedSuppliers)) + eIds := []string{"supplier1", "supplier3", "supplier2"} + for i, spl := range sSpls.SortedSuppliers { + rcv[i] = spl.SupplierID -//Modify the rest of the test -//to cover multiple cases -/* -func TestLibSuppliersSortQOS3(t *testing.T) { - sSpls := &SortedSuppliers{ - SortedSuppliers: []*SortedSupplier{ - &SortedSupplier{ - SupplierID: "supplier1", - globalStats: map[string]float64{ - utils.MetaACD: 0.2, - utils.MetaTCD: 15.0, - utils.MetaASR: 1.2, - }, - SupplierParameters: "param1", - }, - &SortedSupplier{ - SupplierID: "supplier2", - globalStats: map[string]float64{ - utils.MetaACD: 0.2, - utils.MetaTCD: 20.0, - utils.MetaASR: -1.0, - }, - SupplierParameters: "param2", - }, - &SortedSupplier{ - SupplierID: "supplier3", - globalStats: map[string]float64{ - utils.MetaACD: 0.1, - utils.MetaTCD: 10.0, - utils.MetaASR: 1.2, - }, - SupplierParameters: "param3", - }, - }, } - sSpls.SortQOS([]string{utils.MetaASR, utils.MetaACD, utils.MetaTCD}) - eOrderedSpls := &SortedSuppliers{ - SortedSuppliers: []*SortedSupplier{ - &SortedSupplier{ - SupplierID: "supplier1", - globalStats: map[string]float64{ - utils.MetaACD: 0.2, - utils.MetaTCD: 15.0, - utils.MetaASR: 1.2, - }, - SupplierParameters: "param1", - }, - &SortedSupplier{ - SupplierID: "supplier3", - globalStats: map[string]float64{ - utils.MetaACD: 0.1, - utils.MetaTCD: 10.0, - utils.MetaASR: 1.2, - }, - SupplierParameters: "param3", - }, - &SortedSupplier{ - SupplierID: "supplier2", - globalStats: map[string]float64{ - utils.MetaACD: 0.2, - utils.MetaTCD: 20.0, - utils.MetaASR: -1.0, - }, - SupplierParameters: "param2", - }, - }, - } - if !reflect.DeepEqual(eOrderedSpls, sSpls) { - t.Errorf("Expecting: %s, received: %s", - utils.ToJSON(eOrderedSpls), utils.ToJSON(sSpls)) + if !reflect.DeepEqual(eIds, rcv) { + t.Errorf("Expecting: %+v, \n received: %+v", + eIds, rcv) } } @@ -900,74 +689,169 @@ func TestLibSuppliersSortQOS4(t *testing.T) { SortedSuppliers: []*SortedSupplier{ &SortedSupplier{ SupplierID: "supplier1", - globalStats: map[string]float64{ - utils.MetaACD: 0.2, - utils.MetaTCD: 15.0, - utils.MetaASR: -1.0, - utils.MetaTCC: 10.1, + SortingData: map[string]interface{}{ + utils.MetaACD: SplStatMetrics{ + &SplStatMetric{StatID: "SampleStat", + metricType: utils.MetaACD, + MetricValue: 0.2}, + }, + utils.MetaTCD: SplStatMetrics{ + &SplStatMetric{StatID: "SampleStat", + metricType: utils.MetaTCD, + MetricValue: 15.0}, + }, + utils.MetaASR: SplStatMetrics{ + &SplStatMetric{StatID: "SampleStat", + metricType: utils.MetaASR, + MetricValue: 1.2}, + }, }, - SupplierParameters: "param1", }, &SortedSupplier{ SupplierID: "supplier2", - globalStats: map[string]float64{ - utils.MetaACD: 0.2, - utils.MetaTCD: 20.0, - utils.MetaASR: 1.2, - utils.MetaTCC: 10.1, + SortingData: map[string]interface{}{ + utils.MetaACD: SplStatMetrics{ + &SplStatMetric{StatID: "SampleStat", + metricType: utils.MetaACD, + MetricValue: 0.2}, + }, + utils.MetaTCD: SplStatMetrics{ + &SplStatMetric{StatID: "SampleStat", + metricType: utils.MetaTCD, + MetricValue: 20.0}, + }, + utils.MetaASR: SplStatMetrics{ + &SplStatMetric{StatID: "SampleStat", + metricType: utils.MetaASR, + MetricValue: -1.0}, + }, }, - SupplierParameters: "param2", }, &SortedSupplier{ SupplierID: "supplier3", - globalStats: map[string]float64{ - utils.MetaACD: 0.1, - utils.MetaTCD: 10.0, - utils.MetaASR: 1.2, - utils.MetaTCC: 10.1, + SortingData: map[string]interface{}{ + utils.MetaACD: SplStatMetrics{ + &SplStatMetric{StatID: "SampleStat", + metricType: utils.MetaACD, + MetricValue: 0.1}, + }, + utils.MetaTCD: SplStatMetrics{ + &SplStatMetric{StatID: "SampleStat", + metricType: utils.MetaTCD, + MetricValue: 10.0}, + }, + utils.MetaASR: SplStatMetrics{ + &SplStatMetric{StatID: "SampleStat", + metricType: utils.MetaASR, + MetricValue: 1.2}, + }, + }, + }, + }, + } + sSpls.SortQOS([]string{utils.MetaASR, utils.MetaACD, utils.MetaTCD}) + rcv := make([]string, len(sSpls.SortedSuppliers)) + eIds := []string{"supplier1", "supplier3", "supplier2"} + for i, spl := range sSpls.SortedSuppliers { + rcv[i] = spl.SupplierID + + } + if !reflect.DeepEqual(eIds, rcv) { + t.Errorf("Expecting: %+v, \n received: %+v", + eIds, rcv) + } +} + +func TestLibSuppliersSortQOS5(t *testing.T) { + sSpls := &SortedSuppliers{ + SortedSuppliers: []*SortedSupplier{ + &SortedSupplier{ + SupplierID: "supplier1", + SortingData: map[string]interface{}{ + utils.MetaACD: SplStatMetrics{ + &SplStatMetric{StatID: "SampleStat", + metricType: utils.MetaACD, + MetricValue: 0.2}, + }, + utils.MetaTCD: SplStatMetrics{ + &SplStatMetric{StatID: "SampleStat", + metricType: utils.MetaTCD, + MetricValue: 15.0}, + }, + utils.MetaASR: SplStatMetrics{ + &SplStatMetric{StatID: "SampleStat", + metricType: utils.MetaASR, + MetricValue: -1.0}, + }, + utils.MetaTCC: SplStatMetrics{ + &SplStatMetric{StatID: "SampleStat", + metricType: utils.MetaTCC, + MetricValue: 10.1}, + }, + }, + }, + &SortedSupplier{ + SupplierID: "supplier2", + SortingData: map[string]interface{}{ + utils.MetaACD: SplStatMetrics{ + &SplStatMetric{StatID: "SampleStat", + metricType: utils.MetaACD, + MetricValue: 0.2}, + }, + utils.MetaTCD: SplStatMetrics{ + &SplStatMetric{StatID: "SampleStat", + metricType: utils.MetaTCD, + MetricValue: 20.0}, + }, + utils.MetaASR: SplStatMetrics{ + &SplStatMetric{StatID: "SampleStat", + metricType: utils.MetaASR, + MetricValue: 1.2}, + }, + utils.MetaTCC: SplStatMetrics{ + &SplStatMetric{StatID: "SampleStat", + metricType: utils.MetaTCC, + MetricValue: 10.1}, + }, + }, + }, + &SortedSupplier{ + SupplierID: "supplier3", + SortingData: map[string]interface{}{ + utils.MetaACD: SplStatMetrics{ + &SplStatMetric{StatID: "SampleStat", + metricType: utils.MetaACD, + MetricValue: 0.1}, + }, + utils.MetaTCD: SplStatMetrics{ + &SplStatMetric{StatID: "SampleStat", + metricType: utils.MetaTCD, + MetricValue: 10.0}, + }, + utils.MetaASR: SplStatMetrics{ + &SplStatMetric{StatID: "SampleStat", + metricType: utils.MetaASR, + MetricValue: 1.2}, + }, + utils.MetaTCC: SplStatMetrics{ + &SplStatMetric{StatID: "SampleStat", + metricType: utils.MetaTCC, + MetricValue: 10.1}, + }, }, - SupplierParameters: "param3", }, }, } sSpls.SortQOS([]string{utils.MetaTCC, utils.MetaASR, utils.MetaACD, utils.MetaTCD}) - eOrderedSpls := &SortedSuppliers{ - SortedSuppliers: []*SortedSupplier{ - &SortedSupplier{ - SupplierID: "supplier2", - globalStats: map[string]float64{ - utils.MetaACD: 0.2, - utils.MetaTCD: 20.0, - utils.MetaASR: 1.2, - utils.MetaTCC: 10.1, - }, - SupplierParameters: "param2", - }, - &SortedSupplier{ - SupplierID: "supplier3", - globalStats: map[string]float64{ - utils.MetaACD: 0.1, - utils.MetaTCD: 10.0, - utils.MetaASR: 1.2, - utils.MetaTCC: 10.1, - }, - SupplierParameters: "param3", - }, - &SortedSupplier{ - SupplierID: "supplier1", - globalStats: map[string]float64{ - utils.MetaACD: 0.2, - utils.MetaTCD: 15.0, - utils.MetaASR: -1.0, - utils.MetaTCC: 10.1, - }, - SupplierParameters: "param1", - }, - }, + rcv := make([]string, len(sSpls.SortedSuppliers)) + eIds := []string{"supplier2", "supplier3", "supplier1"} + for i, spl := range sSpls.SortedSuppliers { + rcv[i] = spl.SupplierID + } - if !reflect.DeepEqual(eOrderedSpls, sSpls) { - t.Errorf("Expecting: %s, received: %s", - utils.ToJSON(eOrderedSpls), utils.ToJSON(sSpls)) + if !reflect.DeepEqual(eIds, rcv) { + t.Errorf("Expecting: %+v, \n received: %+v", + eIds, rcv) } } @@ -976,75 +860,49 @@ func TestLibSuppliersSortQOS6(t *testing.T) { SortedSuppliers: []*SortedSupplier{ &SortedSupplier{ SupplierID: "supplier1", - globalStats: map[string]float64{ - utils.MetaACD: 0.2, - }, SortingData: map[string]interface{}{ utils.Weight: 15.0, + utils.MetaACD: SplStatMetrics{ + &SplStatMetric{StatID: "SampleStat", + metricType: utils.MetaACD, + MetricValue: 0.2}, + }, }, - SupplierParameters: "param1", }, &SortedSupplier{ SupplierID: "supplier2", - globalStats: map[string]float64{ - utils.MetaACD: 0.2, - }, SortingData: map[string]interface{}{ utils.Weight: 25.0, + utils.MetaACD: SplStatMetrics{ + &SplStatMetric{StatID: "SampleStat", + metricType: utils.MetaACD, + MetricValue: 0.2}, + }, }, - SupplierParameters: "param2", }, &SortedSupplier{ SupplierID: "supplier3", - globalStats: map[string]float64{ - utils.MetaACD: 0.1, - }, SortingData: map[string]interface{}{ utils.Weight: 20.0, + utils.MetaACD: SplStatMetrics{ + &SplStatMetric{StatID: "SampleStat", + metricType: utils.MetaACD, + MetricValue: 0.1}, + }, }, - SupplierParameters: "param3", }, }, } sSpls.SortQOS([]string{utils.MetaACD}) - eOrderedSpls := &SortedSuppliers{ - SortedSuppliers: []*SortedSupplier{ - &SortedSupplier{ - SupplierID: "supplier2", - globalStats: map[string]float64{ - utils.MetaACD: 0.2, - }, - SortingData: map[string]interface{}{ - utils.Weight: 25.0, - }, - SupplierParameters: "param2", - }, - &SortedSupplier{ - SupplierID: "supplier1", - globalStats: map[string]float64{ - utils.MetaACD: 0.2, - }, - SortingData: map[string]interface{}{ - utils.Weight: 15.0, - }, - SupplierParameters: "param1", - }, + rcv := make([]string, len(sSpls.SortedSuppliers)) + eIds := []string{"supplier2", "supplier1", "supplier3"} + for i, spl := range sSpls.SortedSuppliers { + rcv[i] = spl.SupplierID - &SortedSupplier{ - SupplierID: "supplier3", - globalStats: map[string]float64{ - utils.MetaACD: 0.1, - }, - SortingData: map[string]interface{}{ - utils.Weight: 20.0, - }, - SupplierParameters: "param3", - }, - }, } - if !reflect.DeepEqual(eOrderedSpls, sSpls) { - t.Errorf("Expecting: %s, received: %s", - utils.ToJSON(eOrderedSpls), utils.ToJSON(sSpls)) + if !reflect.DeepEqual(eIds, rcv) { + t.Errorf("Expecting: %+v, \n received: %+v", + eIds, rcv) } } @@ -1053,74 +911,49 @@ func TestLibSuppliersSortQOS7(t *testing.T) { SortedSuppliers: []*SortedSupplier{ &SortedSupplier{ SupplierID: "supplier1", - globalStats: map[string]float64{ - utils.MetaACD: -1.0, - }, SortingData: map[string]interface{}{ utils.Weight: 15.0, + utils.MetaACD: SplStatMetrics{ + &SplStatMetric{StatID: "SampleStat", + metricType: utils.MetaACD, + MetricValue: -1.0}, + }, }, - SupplierParameters: "param1", }, &SortedSupplier{ SupplierID: "supplier2", - globalStats: map[string]float64{ - utils.MetaACD: -1.0, - }, SortingData: map[string]interface{}{ utils.Weight: 25.0, + utils.MetaACD: SplStatMetrics{ + &SplStatMetric{StatID: "SampleStat", + metricType: utils.MetaACD, + MetricValue: -1.0}, + }, }, - SupplierParameters: "param2", }, &SortedSupplier{ SupplierID: "supplier3", - globalStats: map[string]float64{ - utils.MetaACD: -1.0, - }, SortingData: map[string]interface{}{ utils.Weight: 20.0, + utils.MetaACD: SplStatMetrics{ + &SplStatMetric{StatID: "SampleStat", + metricType: utils.MetaACD, + MetricValue: -1.0}, + }, }, - SupplierParameters: "param3", }, }, } sSpls.SortQOS([]string{utils.MetaACD}) - eOrderedSpls := &SortedSuppliers{ - SortedSuppliers: []*SortedSupplier{ - &SortedSupplier{ - SupplierID: "supplier2", - globalStats: map[string]float64{ - utils.MetaACD: -1.0, - }, - SortingData: map[string]interface{}{ - utils.Weight: 25.0, - }, - SupplierParameters: "param2", - }, - &SortedSupplier{ - SupplierID: "supplier3", - globalStats: map[string]float64{ - utils.MetaACD: -1.0, - }, - SortingData: map[string]interface{}{ - utils.Weight: 20.0, - }, - SupplierParameters: "param3", - }, - &SortedSupplier{ - SupplierID: "supplier1", - globalStats: map[string]float64{ - utils.MetaACD: -1.0, - }, - SortingData: map[string]interface{}{ - utils.Weight: 15.0, - }, - SupplierParameters: "param1", - }, - }, + rcv := make([]string, len(sSpls.SortedSuppliers)) + eIds := []string{"supplier2", "supplier3", "supplier1"} + for i, spl := range sSpls.SortedSuppliers { + rcv[i] = spl.SupplierID + } - if !reflect.DeepEqual(eOrderedSpls, sSpls) { - t.Errorf("Expecting: %s, received: %s", - utils.ToJSON(eOrderedSpls), utils.ToJSON(sSpls)) + if !reflect.DeepEqual(eIds, rcv) { + t.Errorf("Expecting: %+v, \n received: %+v", + eIds, rcv) } } @@ -1129,75 +962,49 @@ func TestLibSuppliersSortQOS8(t *testing.T) { SortedSuppliers: []*SortedSupplier{ &SortedSupplier{ SupplierID: "supplier1", - globalStats: map[string]float64{ - utils.MetaACD: -1.0, - }, SortingData: map[string]interface{}{ utils.Weight: 15.0, + utils.MetaACD: SplStatMetrics{ + &SplStatMetric{StatID: "SampleStat", + metricType: utils.MetaACD, + MetricValue: -1.0}, + }, }, - SupplierParameters: "param1", }, &SortedSupplier{ SupplierID: "supplier2", - globalStats: map[string]float64{ - utils.MetaACD: -1.0, - }, SortingData: map[string]interface{}{ utils.Weight: 25.0, + utils.MetaACD: SplStatMetrics{ + &SplStatMetric{StatID: "SampleStat", + metricType: utils.MetaACD, + MetricValue: -1.0}, + }, }, SupplierParameters: "param2", }, &SortedSupplier{ SupplierID: "supplier3", - globalStats: map[string]float64{ - utils.MetaACD: 10.0, - }, SortingData: map[string]interface{}{ utils.Weight: 20.0, + utils.MetaACD: SplStatMetrics{ + &SplStatMetric{StatID: "SampleStat", + metricType: utils.MetaACD, + MetricValue: 10.0}, + }, }, - SupplierParameters: "param3", }, }, } sSpls.SortQOS([]string{utils.MetaACD}) - eOrderedSpls := &SortedSuppliers{ - SortedSuppliers: []*SortedSupplier{ - &SortedSupplier{ - SupplierID: "supplier3", - globalStats: map[string]float64{ - utils.MetaACD: 10.0, - }, - SortingData: map[string]interface{}{ - utils.Weight: 20.0, - }, - SupplierParameters: "param3", - }, - &SortedSupplier{ - SupplierID: "supplier2", - globalStats: map[string]float64{ - utils.MetaACD: -1.0, - }, - SortingData: map[string]interface{}{ - utils.Weight: 25.0, - }, - SupplierParameters: "param2", - }, + rcv := make([]string, len(sSpls.SortedSuppliers)) + eIds := []string{"supplier3", "supplier2", "supplier1"} + for i, spl := range sSpls.SortedSuppliers { + rcv[i] = spl.SupplierID - &SortedSupplier{ - SupplierID: "supplier1", - globalStats: map[string]float64{ - utils.MetaACD: -1.0, - }, - SortingData: map[string]interface{}{ - utils.Weight: 15.0, - }, - SupplierParameters: "param1", - }, - }, } - if !reflect.DeepEqual(eOrderedSpls, sSpls) { - t.Errorf("Expecting: %s, received: %s", - utils.ToJSON(eOrderedSpls), utils.ToJSON(sSpls)) + if !reflect.DeepEqual(eIds, rcv) { + t.Errorf("Expecting: %+v, \n received: %+v", + eIds, rcv) } } -*/ diff --git a/engine/suppliers.go b/engine/suppliers.go index 743dac3e2..37f3328da 100644 --- a/engine/suppliers.go +++ b/engine/suppliers.go @@ -312,7 +312,6 @@ func (spS *SupplierService) populateSortingData(ev *utils.CGREvent, spl *Supplie } } } - provStatsMetrics := make(map[string]SplStatMetrics) //calculate metrics if len(spl.StatIDs) != 0 { metricSupp, err := spS.statMetrics(spl.StatIDs, ev.Tenant) //create metric map for suppier @@ -332,25 +331,19 @@ func (spS *SupplierService) populateSortingData(ev *utils.CGREvent, spl *Supplie switch metric { default: sortedSpl.SortingData[metric] = SplStatMetrics{&SplStatMetric{StatID: utils.META_NONE, metricType: metric, MetricValue: -1.0}} - provStatsMetrics[metric] = SplStatMetrics{&SplStatMetric{StatID: utils.META_NONE, metricType: metric, MetricValue: -1.0}} case utils.MetaPDD: sortedSpl.SortingData[metric] = SplStatMetrics{&SplStatMetric{StatID: utils.META_NONE, metricType: metric, MetricValue: 10000000.0}} - provStatsMetrics[metric] = SplStatMetrics{&SplStatMetric{StatID: utils.META_NONE, metricType: metric, MetricValue: 10000000.0}} } } else { sortedSpl.SortingData[metric] = val - provStatsMetrics[metric] = val } } } - //reas - //reds //filter the supplier if len(spl.FilterIDs) != 0 { nM := config.NewNavigableMap(nil) nM.Set([]string{utils.MetaReq}, ev.Event, false, false) - nM.Set([]string{utils.MetaVars}, sortedSpl.SortingData, false, false) - nM.Set([]string{"*metrics"}, newSplStsDP(provStatsMetrics), false, false) + nM.Set([]string{utils.MetaVars}, convertSortingData(sortedSpl.SortingData), false, false) if pass, err = spS.filterS.Pass(ev.Tenant, spl.FilterIDs, nM); err != nil {