diff --git a/engine/libsuppliers.go b/engine/libsuppliers.go index fe850d391..de5e0b3bc 100644 --- a/engine/libsuppliers.go +++ b/engine/libsuppliers.go @@ -68,9 +68,9 @@ func (sSpls *SortedSuppliers) SortWeight() { }) } -// SortCost is part of sort interface, -// sort based on Cost with fallback on Weight -func (sSpls *SortedSuppliers) SortCost() { +// SortLeastCost is part of sort interface, +// sort ascendent based on Cost with fallback on Weight +func (sSpls *SortedSuppliers) SortLeastCost() { sort.Slice(sSpls.SortedSuppliers, func(i, j int) bool { if sSpls.SortedSuppliers[i].SortingData[utils.Cost].(float64) == sSpls.SortedSuppliers[j].SortingData[utils.Cost].(float64) { return sSpls.SortedSuppliers[i].SortingData[utils.Weight].(float64) > sSpls.SortedSuppliers[j].SortingData[utils.Weight].(float64) @@ -79,8 +79,8 @@ func (sSpls *SortedSuppliers) SortCost() { }) } -// SortCost is part of sort interface, -// sort based on Cost with fallback on Weight +// SortHighestCost is part of sort interface, +// sort descendent based on Cost with fallback on Weight func (sSpls *SortedSuppliers) SortHighestCost() { sort.Slice(sSpls.SortedSuppliers, func(i, j int) bool { if sSpls.SortedSuppliers[i].SortingData[utils.Cost].(float64) == sSpls.SortedSuppliers[j].SortingData[utils.Cost].(float64) { @@ -90,6 +90,15 @@ func (sSpls *SortedSuppliers) SortHighestCost() { }) } +// SortQOS is part of sort interface, +// sort based on Stats +func (sSpls *SortedSuppliers) SortQOS() { + sort.Slice(sSpls.SortedSuppliers, func(i, j int) bool { + //to be added + return true + }) +} + // Digest returns list of supplierIDs + parameters for easier outside access // format suppl1:suppl1params,suppl2:suppl2params func (sSpls *SortedSuppliers) Digest() string { @@ -112,6 +121,7 @@ func NewSupplierSortDispatcher(lcrS *SupplierService) (ssd SupplierSortDispatche ssd[utils.MetaWeight] = NewWeightSorter() ssd[utils.MetaLeastCost] = NewLeastCostSorter(lcrS) ssd[utils.MetaHighestCost] = NewHighestCostSorter(lcrS) + ssd[utils.MetaQOS] = NewQOSSupplierSorter(lcrS) return } diff --git a/engine/libsuppliers_test.go b/engine/libsuppliers_test.go index 2ff7e4f72..74af9779c 100644 --- a/engine/libsuppliers_test.go +++ b/engine/libsuppliers_test.go @@ -26,6 +26,7 @@ import ( func TestLibSuppliersSortCost(t *testing.T) { sSpls := &SortedSuppliers{ + Sorting: utils.MetaLeastCost, SortedSuppliers: []*SortedSupplier{ &SortedSupplier{ SupplierID: "supplier1", @@ -53,8 +54,9 @@ func TestLibSuppliersSortCost(t *testing.T) { }, }, } - sSpls.SortCost() + sSpls.SortLeastCost() eOrderedSpls := &SortedSuppliers{ + Sorting: utils.MetaLeastCost, SortedSuppliers: []*SortedSupplier{ &SortedSupplier{ SupplierID: "supplier3", @@ -221,6 +223,7 @@ func TestSortedSuppliersDigest3(t *testing.T) { func TestLibSuppliersSortHighestCost(t *testing.T) { sSpls := &SortedSuppliers{ + Sorting: utils.MetaHighestCost, SortedSuppliers: []*SortedSupplier{ &SortedSupplier{ SupplierID: "supplier1", @@ -250,6 +253,7 @@ func TestLibSuppliersSortHighestCost(t *testing.T) { } sSpls.SortHighestCost() eOrderedSpls := &SortedSuppliers{ + Sorting: utils.MetaHighestCost, SortedSuppliers: []*SortedSupplier{ &SortedSupplier{ SupplierID: "supplier2", diff --git a/engine/spls_highestcost.go b/engine/spls_highestcost.go index c2f5bc767..a44aa1edf 100755 --- a/engine/spls_highestcost.go +++ b/engine/spls_highestcost.go @@ -66,11 +66,10 @@ func (lcs *HightCostSorter) SortSuppliers(prflID string, suppls []*Supplier, for k, v := range costData { srtData[k] = v } - sortedSuppls.SortedSuppliers = append(sortedSuppls.SortedSuppliers, - &SortedSupplier{ - SupplierID: s.ID, - SortingData: srtData, - SupplierParameters: s.SupplierParameters}) + sortedSuppls.SortedSuppliers = append(sortedSuppls.SortedSuppliers, &SortedSupplier{ + SupplierID: s.ID, + SortingData: srtData, + SupplierParameters: s.SupplierParameters}) } if len(sortedSuppls.SortedSuppliers) == 0 { return nil, utils.ErrNotFound diff --git a/engine/spls_leastcost.go b/engine/spls_leastcost.go index d80c742e7..23ef67183 100644 --- a/engine/spls_leastcost.go +++ b/engine/spls_leastcost.go @@ -66,15 +66,14 @@ func (lcs *LeastCostSorter) SortSuppliers(prflID string, suppls []*Supplier, for k, v := range costData { srtData[k] = v } - sortedSuppls.SortedSuppliers = append(sortedSuppls.SortedSuppliers, - &SortedSupplier{ - SupplierID: s.ID, - SortingData: srtData, - SupplierParameters: s.SupplierParameters}) + sortedSuppls.SortedSuppliers = append(sortedSuppls.SortedSuppliers, &SortedSupplier{ + SupplierID: s.ID, + SortingData: srtData, + SupplierParameters: s.SupplierParameters}) } if len(sortedSuppls.SortedSuppliers) == 0 { return nil, utils.ErrNotFound } - sortedSuppls.SortCost() + sortedSuppls.SortLeastCost() return } diff --git a/engine/spls_qos.go b/engine/spls_qos.go new file mode 100755 index 000000000..6a485342c --- /dev/null +++ b/engine/spls_qos.go @@ -0,0 +1,73 @@ +/* +Real-time Online/Offline Charging System (OCS) for Telecom & ISP environments +Copyright (C) ITsysCOM GmbH + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see +*/ + +package engine + +import ( + "fmt" + + "github.com/cgrates/cgrates/utils" +) + +func NewQOSSupplierSorter(spS *SupplierService) *QOSSupplierSorter { + return &QOSSupplierSorter{spS: spS, + sorting: utils.MetaQOS} +} + +// QOSSorter sorts suppliers based on stats +type QOSSupplierSorter struct { + sorting string + spS *SupplierService +} + +func (lcs *QOSSupplierSorter) SortSuppliers(prflID string, suppls []*Supplier, + ev *utils.CGREvent, extraOpts *optsGetSuppliers) (sortedSuppls *SortedSuppliers, err error) { + sortedSuppls = &SortedSuppliers{ProfileID: prflID, + Sorting: lcs.sorting, + SortedSuppliers: make([]*SortedSupplier, 0)} + for _, s := range suppls { + metricSupp, err := lcs.spS.statMetrics([]string{}, []string{}) //create metric map for suppier s + if err != nil { + if extraOpts.ignoreErrors { + utils.Logger.Warning( + fmt.Sprintf("<%s> profile: %s ignoring supplier with ID: %s, err: %s", + utils.SupplierS, prflID, s.ID, err.Error())) + continue + } + return nil, err + } + + srtData := map[string]interface{}{ + utils.Weight: s.Weight, + } + + for k, v := range metricSupp { //transfer data from metric into srtData + srtData[k] = v + } + + sortedSuppls.SortedSuppliers = append(sortedSuppls.SortedSuppliers, &SortedSupplier{ + SupplierID: s.ID, + SortingData: srtData, + SupplierParameters: s.SupplierParameters}) + } + if len(sortedSuppls.SortedSuppliers) == 0 { + return nil, utils.ErrNotFound + } + sortedSuppls.SortQOS() + return +} diff --git a/utils/consts.go b/utils/consts.go index f19eff8b5..f91a84331 100755 --- a/utils/consts.go +++ b/utils/consts.go @@ -485,6 +485,7 @@ const ( MetaWeight = "*weight" MetaLeastCost = "*least_cost" MetaHighestCost = "*highest_cost" + MetaQOS = "*qos" Weight = "Weight" Cost = "Cost" RatingPlanID = "RatingPlanID"