mirror of
https://github.com/cgrates/cgrates.git
synced 2026-02-15 21:29:52 +05:00
Renaming from SupplierS -> RouteS ( part 1)
This commit is contained in:
committed by
Dan Christian Bogos
parent
1127fe3177
commit
cdaa675234
223
engine/libroutes.go
Normal file
223
engine/libroutes.go
Normal file
@@ -0,0 +1,223 @@
|
||||
/*
|
||||
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 <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
package engine
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/cgrates/cgrates/config"
|
||||
"github.com/cgrates/cgrates/utils"
|
||||
)
|
||||
|
||||
// SortedRoute represents one route in SortedRoutes
|
||||
type SortedRoute struct {
|
||||
RouteID string
|
||||
RouteParameters string
|
||||
SortingData map[string]interface{} // store here extra info like cost or stats
|
||||
}
|
||||
|
||||
// SortedRoutes is returned as part of GetRoutes call
|
||||
type SortedRoutes struct {
|
||||
ProfileID string // Profile matched
|
||||
Sorting string // Sorting algorithm
|
||||
Count int // number of suppliers returned
|
||||
SortedRoutes []*SortedRoute // list of supplier IDs and SortingData data
|
||||
}
|
||||
|
||||
// RouteIDs returns a list of route IDs
|
||||
func (sRoutes *SortedRoutes) RouteIDs() (rIDs []string) {
|
||||
rIDs = make([]string, len(sRoutes.SortedRoutes))
|
||||
for i, sRoute := range sRoutes.SortedRoutes {
|
||||
rIDs[i] = sRoute.RouteID
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// RoutesWithParams returns a list of routes IDs with Parameters
|
||||
func (sRoutes *SortedRoutes) RoutesWithParams() (sPs []string) {
|
||||
sPs = make([]string, len(sRoutes.SortedRoutes))
|
||||
for i, spl := range sRoutes.SortedRoutes {
|
||||
sPs[i] = spl.RouteID
|
||||
if spl.RouteParameters != "" {
|
||||
sPs[i] += utils.InInFieldSep + spl.RouteParameters
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// SortWeight is part of sort interface, sort based on Weight
|
||||
func (sRoutes *SortedRoutes) SortWeight() {
|
||||
sort.Slice(sRoutes.SortedRoutes, func(i, j int) bool {
|
||||
return sRoutes.SortedRoutes[i].SortingData[utils.Weight].(float64) > sRoutes.SortedRoutes[j].SortingData[utils.Weight].(float64)
|
||||
})
|
||||
}
|
||||
|
||||
// SortLeastCost is part of sort interface,
|
||||
// sort ascendent based on Cost with fallback on Weight
|
||||
func (sSpls *SortedRoutes) SortLeastCost() {
|
||||
sort.Slice(sSpls.SortedRoutes, func(i, j int) bool {
|
||||
if sSpls.SortedRoutes[i].SortingData[utils.Cost].(float64) == sSpls.SortedRoutes[j].SortingData[utils.Cost].(float64) {
|
||||
return sSpls.SortedRoutes[i].SortingData[utils.Weight].(float64) > sSpls.SortedRoutes[j].SortingData[utils.Weight].(float64)
|
||||
}
|
||||
return sSpls.SortedRoutes[i].SortingData[utils.Cost].(float64) < sSpls.SortedRoutes[j].SortingData[utils.Cost].(float64)
|
||||
})
|
||||
}
|
||||
|
||||
// SortHighestCost is part of sort interface,
|
||||
// sort descendent based on Cost with fallback on Weight
|
||||
func (sSpls *SortedRoutes) SortHighestCost() {
|
||||
sort.Slice(sSpls.SortedRoutes, func(i, j int) bool {
|
||||
if sSpls.SortedRoutes[i].SortingData[utils.Cost].(float64) == sSpls.SortedRoutes[j].SortingData[utils.Cost].(float64) {
|
||||
return sSpls.SortedRoutes[i].SortingData[utils.Weight].(float64) > sSpls.SortedRoutes[j].SortingData[utils.Weight].(float64)
|
||||
}
|
||||
return sSpls.SortedRoutes[i].SortingData[utils.Cost].(float64) > sSpls.SortedRoutes[j].SortingData[utils.Cost].(float64)
|
||||
})
|
||||
}
|
||||
|
||||
// SortQOS is part of sort interface,
|
||||
// sort based on Stats
|
||||
func (sSpls *SortedRoutes) SortQOS(params []string) {
|
||||
//sort suppliers
|
||||
sort.Slice(sSpls.SortedRoutes, func(i, j int) bool {
|
||||
for _, param := range params {
|
||||
//in case we have the same value for the current param we skip to the next one
|
||||
if sSpls.SortedRoutes[i].SortingData[param].(float64) == sSpls.SortedRoutes[j].SortingData[param].(float64) {
|
||||
continue
|
||||
}
|
||||
switch param {
|
||||
default:
|
||||
if sSpls.SortedRoutes[i].SortingData[param].(float64) > sSpls.SortedRoutes[j].SortingData[param].(float64) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
case utils.MetaPDD: //in case of pdd the smallest value if the best
|
||||
if sSpls.SortedRoutes[i].SortingData[param].(float64) < sSpls.SortedRoutes[j].SortingData[param].(float64) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
}
|
||||
//in case that we have the same value for all params we sort base on weight
|
||||
return sSpls.SortedRoutes[i].SortingData[utils.Weight].(float64) > sSpls.SortedRoutes[j].SortingData[utils.Weight].(float64)
|
||||
})
|
||||
}
|
||||
|
||||
// SortResourceAscendent is part of sort interface,
|
||||
// sort ascendent based on ResourceUsage with fallback on Weight
|
||||
func (sSpls *SortedRoutes) SortResourceAscendent() {
|
||||
sort.Slice(sSpls.SortedRoutes, func(i, j int) bool {
|
||||
if sSpls.SortedRoutes[i].SortingData[utils.ResourceUsage].(float64) == sSpls.SortedRoutes[j].SortingData[utils.ResourceUsage].(float64) {
|
||||
return sSpls.SortedRoutes[i].SortingData[utils.Weight].(float64) > sSpls.SortedRoutes[j].SortingData[utils.Weight].(float64)
|
||||
}
|
||||
return sSpls.SortedRoutes[i].SortingData[utils.ResourceUsage].(float64) < sSpls.SortedRoutes[j].SortingData[utils.ResourceUsage].(float64)
|
||||
})
|
||||
}
|
||||
|
||||
// SortResourceDescendent is part of sort interface,
|
||||
// sort descendent based on ResourceUsage with fallback on Weight
|
||||
func (sSpls *SortedRoutes) SortResourceDescendent() {
|
||||
sort.Slice(sSpls.SortedRoutes, func(i, j int) bool {
|
||||
if sSpls.SortedRoutes[i].SortingData[utils.ResourceUsage].(float64) == sSpls.SortedRoutes[j].SortingData[utils.ResourceUsage].(float64) {
|
||||
return sSpls.SortedRoutes[i].SortingData[utils.Weight].(float64) > sSpls.SortedRoutes[j].SortingData[utils.Weight].(float64)
|
||||
}
|
||||
return sSpls.SortedRoutes[i].SortingData[utils.ResourceUsage].(float64) > sSpls.SortedRoutes[j].SortingData[utils.ResourceUsage].(float64)
|
||||
})
|
||||
}
|
||||
|
||||
// SortLoadDistribution is part of sort interface,
|
||||
// sort based on the following formula (float64(ratio + metricVal) / float64(ratio)) -1 with fallback on Weight
|
||||
func (sSpls *SortedRoutes) SortLoadDistribution() {
|
||||
sort.Slice(sSpls.SortedRoutes, func(i, j int) bool {
|
||||
splIVal := ((sSpls.SortedRoutes[i].SortingData[utils.Ratio].(float64)+sSpls.SortedRoutes[i].SortingData[utils.Load].(float64))/sSpls.SortedRoutes[i].SortingData[utils.Ratio].(float64) - 1.0)
|
||||
splJVal := ((sSpls.SortedRoutes[j].SortingData[utils.Ratio].(float64)+sSpls.SortedRoutes[j].SortingData[utils.Load].(float64))/sSpls.SortedRoutes[j].SortingData[utils.Ratio].(float64) - 1.0)
|
||||
if splIVal == splJVal {
|
||||
return sSpls.SortedRoutes[i].SortingData[utils.Weight].(float64) > sSpls.SortedRoutes[j].SortingData[utils.Weight].(float64)
|
||||
}
|
||||
return splIVal < splJVal
|
||||
})
|
||||
}
|
||||
|
||||
// Digest returns list of supplierIDs + parameters for easier outside access
|
||||
// format suppl1:suppl1params,suppl2:suppl2params
|
||||
func (sSpls *SortedRoutes) Digest() string {
|
||||
return strings.Join(sSpls.RoutesWithParams(), utils.FIELDS_SEP)
|
||||
}
|
||||
|
||||
func (sSpls *SortedRoutes) AsNavigableMap() (nm *config.NavigableMap) {
|
||||
mp := map[string]interface{}{
|
||||
"ProfileID": sSpls.ProfileID,
|
||||
"Sorting": sSpls.Sorting,
|
||||
"Count": sSpls.Count,
|
||||
}
|
||||
sm := make([]map[string]interface{}, len(sSpls.SortedRoutes))
|
||||
for i, ss := range sSpls.SortedRoutes {
|
||||
sm[i] = map[string]interface{}{
|
||||
"SupplierID": ss.RouteID,
|
||||
"SupplierParameters": ss.RouteParameters,
|
||||
"SortingData": ss.SortingData,
|
||||
}
|
||||
}
|
||||
mp["SortedSuppliers"] = sm
|
||||
return config.NewNavigableMap(mp)
|
||||
}
|
||||
|
||||
type SupplierWithParams struct {
|
||||
SupplierName string
|
||||
SupplierParams string
|
||||
}
|
||||
|
||||
// SuppliersSorter is the interface which needs to be implemented by supplier sorters
|
||||
type RoutesSorter interface {
|
||||
SortRoutes(string, []*Route, *utils.CGREvent, *optsGetSuppliers) (*SortedRoutes, error)
|
||||
}
|
||||
|
||||
// NewRouteSortDispatcher constructs RouteSortDispatcher
|
||||
func NewRouteSortDispatcher(lcrS *RouteService) (rsd RouteSortDispatcher, err error) {
|
||||
rsd = make(map[string]RoutesSorter)
|
||||
rsd[utils.MetaWeight] = NewWeightSorter(lcrS)
|
||||
rsd[utils.MetaLC] = NewLeastCostSorter(lcrS)
|
||||
rsd[utils.MetaHC] = NewHighestCostSorter(lcrS)
|
||||
rsd[utils.MetaQOS] = NewQOSSupplierSorter(lcrS)
|
||||
rsd[utils.MetaReas] = NewResourceAscendetSorter(lcrS)
|
||||
rsd[utils.MetaReds] = NewResourceDescendentSorter(lcrS)
|
||||
rsd[utils.MetaLoad] = NewLoadDistributionSorter(lcrS)
|
||||
return
|
||||
}
|
||||
|
||||
// RouteSortDispatcher will initialize strategies
|
||||
// and dispatch requests to them
|
||||
type RouteSortDispatcher map[string]RoutesSorter
|
||||
|
||||
func (ssd RouteSortDispatcher) SortSuppliers(prflID, strategy string,
|
||||
suppls []*Route, suplEv *utils.CGREvent, extraOpts *optsGetSuppliers) (sortedRoutes *SortedRoutes, err error) {
|
||||
sd, has := ssd[strategy]
|
||||
if !has {
|
||||
return nil, fmt.Errorf("unsupported sorting strategy: %s", strategy)
|
||||
}
|
||||
if sortedRoutes, err = sd.SortRoutes(prflID, suppls, suplEv, extraOpts); err != nil {
|
||||
return
|
||||
}
|
||||
if len(sortedRoutes.SortedRoutes) == 0 {
|
||||
return nil, utils.ErrNotFound
|
||||
}
|
||||
return
|
||||
}
|
||||
@@ -1,223 +0,0 @@
|
||||
/*
|
||||
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 <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
package engine
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/cgrates/cgrates/config"
|
||||
"github.com/cgrates/cgrates/utils"
|
||||
)
|
||||
|
||||
// SupplierReply represents one supplier in
|
||||
type SortedSupplier struct {
|
||||
SupplierID string
|
||||
SupplierParameters string
|
||||
SortingData map[string]interface{} // store here extra info like cost or stats
|
||||
}
|
||||
|
||||
// SuppliersReply is returned as part of GetSuppliers call
|
||||
type SortedSuppliers struct {
|
||||
ProfileID string // Profile matched
|
||||
Sorting string // Sorting algorithm
|
||||
Count int // number of suppliers returned
|
||||
SortedSuppliers []*SortedSupplier // list of supplier IDs and SortingData data
|
||||
}
|
||||
|
||||
// SupplierIDs returns list of suppliers
|
||||
func (sSpls *SortedSuppliers) SupplierIDs() (sIDs []string) {
|
||||
sIDs = make([]string, len(sSpls.SortedSuppliers))
|
||||
for i, spl := range sSpls.SortedSuppliers {
|
||||
sIDs[i] = spl.SupplierID
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// SupplierIDs returns list of suppliers
|
||||
func (sSpls *SortedSuppliers) SuppliersWithParams() (sPs []string) {
|
||||
sPs = make([]string, len(sSpls.SortedSuppliers))
|
||||
for i, spl := range sSpls.SortedSuppliers {
|
||||
sPs[i] = spl.SupplierID
|
||||
if spl.SupplierParameters != "" {
|
||||
sPs[i] += utils.InInFieldSep + spl.SupplierParameters
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// SortWeight is part of sort interface, sort based on Weight
|
||||
func (sSpls *SortedSuppliers) SortWeight() {
|
||||
sort.Slice(sSpls.SortedSuppliers, func(i, j int) bool {
|
||||
return sSpls.SortedSuppliers[i].SortingData[utils.Weight].(float64) > sSpls.SortedSuppliers[j].SortingData[utils.Weight].(float64)
|
||||
})
|
||||
}
|
||||
|
||||
// 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)
|
||||
}
|
||||
return sSpls.SortedSuppliers[i].SortingData[utils.Cost].(float64) < sSpls.SortedSuppliers[j].SortingData[utils.Cost].(float64)
|
||||
})
|
||||
}
|
||||
|
||||
// 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) {
|
||||
return sSpls.SortedSuppliers[i].SortingData[utils.Weight].(float64) > sSpls.SortedSuppliers[j].SortingData[utils.Weight].(float64)
|
||||
}
|
||||
return sSpls.SortedSuppliers[i].SortingData[utils.Cost].(float64) > sSpls.SortedSuppliers[j].SortingData[utils.Cost].(float64)
|
||||
})
|
||||
}
|
||||
|
||||
// SortQOS is part of sort interface,
|
||||
// sort based on Stats
|
||||
func (sSpls *SortedSuppliers) SortQOS(params []string) {
|
||||
//sort suppliers
|
||||
sort.Slice(sSpls.SortedSuppliers, func(i, j int) bool {
|
||||
for _, param := range params {
|
||||
//in case we have the same value for the current param we skip to the next one
|
||||
if sSpls.SortedSuppliers[i].SortingData[param].(float64) == sSpls.SortedSuppliers[j].SortingData[param].(float64) {
|
||||
continue
|
||||
}
|
||||
switch param {
|
||||
default:
|
||||
if sSpls.SortedSuppliers[i].SortingData[param].(float64) > sSpls.SortedSuppliers[j].SortingData[param].(float64) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
case utils.MetaPDD: //in case of pdd the smallest value if the best
|
||||
if sSpls.SortedSuppliers[i].SortingData[param].(float64) < sSpls.SortedSuppliers[j].SortingData[param].(float64) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
}
|
||||
//in case that we have the same value for all params we sort base on weight
|
||||
return sSpls.SortedSuppliers[i].SortingData[utils.Weight].(float64) > sSpls.SortedSuppliers[j].SortingData[utils.Weight].(float64)
|
||||
})
|
||||
}
|
||||
|
||||
// SortResourceAscendent is part of sort interface,
|
||||
// sort ascendent based on ResourceUsage with fallback on Weight
|
||||
func (sSpls *SortedSuppliers) SortResourceAscendent() {
|
||||
sort.Slice(sSpls.SortedSuppliers, func(i, j int) bool {
|
||||
if sSpls.SortedSuppliers[i].SortingData[utils.ResourceUsage].(float64) == sSpls.SortedSuppliers[j].SortingData[utils.ResourceUsage].(float64) {
|
||||
return sSpls.SortedSuppliers[i].SortingData[utils.Weight].(float64) > sSpls.SortedSuppliers[j].SortingData[utils.Weight].(float64)
|
||||
}
|
||||
return sSpls.SortedSuppliers[i].SortingData[utils.ResourceUsage].(float64) < sSpls.SortedSuppliers[j].SortingData[utils.ResourceUsage].(float64)
|
||||
})
|
||||
}
|
||||
|
||||
// SortResourceDescendent is part of sort interface,
|
||||
// sort descendent based on ResourceUsage with fallback on Weight
|
||||
func (sSpls *SortedSuppliers) SortResourceDescendent() {
|
||||
sort.Slice(sSpls.SortedSuppliers, func(i, j int) bool {
|
||||
if sSpls.SortedSuppliers[i].SortingData[utils.ResourceUsage].(float64) == sSpls.SortedSuppliers[j].SortingData[utils.ResourceUsage].(float64) {
|
||||
return sSpls.SortedSuppliers[i].SortingData[utils.Weight].(float64) > sSpls.SortedSuppliers[j].SortingData[utils.Weight].(float64)
|
||||
}
|
||||
return sSpls.SortedSuppliers[i].SortingData[utils.ResourceUsage].(float64) > sSpls.SortedSuppliers[j].SortingData[utils.ResourceUsage].(float64)
|
||||
})
|
||||
}
|
||||
|
||||
// SortLoadDistribution is part of sort interface,
|
||||
// sort based on the following formula (float64(ratio + metricVal) / float64(ratio)) -1 with fallback on Weight
|
||||
func (sSpls *SortedSuppliers) SortLoadDistribution() {
|
||||
sort.Slice(sSpls.SortedSuppliers, func(i, j int) bool {
|
||||
splIVal := ((sSpls.SortedSuppliers[i].SortingData[utils.Ratio].(float64)+sSpls.SortedSuppliers[i].SortingData[utils.Load].(float64))/sSpls.SortedSuppliers[i].SortingData[utils.Ratio].(float64) - 1.0)
|
||||
splJVal := ((sSpls.SortedSuppliers[j].SortingData[utils.Ratio].(float64)+sSpls.SortedSuppliers[j].SortingData[utils.Load].(float64))/sSpls.SortedSuppliers[j].SortingData[utils.Ratio].(float64) - 1.0)
|
||||
if splIVal == splJVal {
|
||||
return sSpls.SortedSuppliers[i].SortingData[utils.Weight].(float64) > sSpls.SortedSuppliers[j].SortingData[utils.Weight].(float64)
|
||||
}
|
||||
return splIVal < splJVal
|
||||
})
|
||||
}
|
||||
|
||||
// Digest returns list of supplierIDs + parameters for easier outside access
|
||||
// format suppl1:suppl1params,suppl2:suppl2params
|
||||
func (sSpls *SortedSuppliers) Digest() string {
|
||||
return strings.Join(sSpls.SuppliersWithParams(), utils.FIELDS_SEP)
|
||||
}
|
||||
|
||||
func (sSpls *SortedSuppliers) AsNavigableMap() (nm *config.NavigableMap) {
|
||||
mp := map[string]interface{}{
|
||||
"ProfileID": sSpls.ProfileID,
|
||||
"Sorting": sSpls.Sorting,
|
||||
"Count": sSpls.Count,
|
||||
}
|
||||
sm := make([]map[string]interface{}, len(sSpls.SortedSuppliers))
|
||||
for i, ss := range sSpls.SortedSuppliers {
|
||||
sm[i] = map[string]interface{}{
|
||||
"SupplierID": ss.SupplierID,
|
||||
"SupplierParameters": ss.SupplierParameters,
|
||||
"SortingData": ss.SortingData,
|
||||
}
|
||||
}
|
||||
mp["SortedSuppliers"] = sm
|
||||
return config.NewNavigableMap(mp)
|
||||
}
|
||||
|
||||
type SupplierWithParams struct {
|
||||
SupplierName string
|
||||
SupplierParams string
|
||||
}
|
||||
|
||||
// SuppliersSorter is the interface which needs to be implemented by supplier sorters
|
||||
type SuppliersSorter interface {
|
||||
SortSuppliers(string, []*Supplier, *utils.CGREvent, *optsGetSuppliers) (*SortedSuppliers, error)
|
||||
}
|
||||
|
||||
// NewSupplierSortDispatcher constructs SupplierSortDispatcher
|
||||
func NewSupplierSortDispatcher(lcrS *SupplierService) (ssd SupplierSortDispatcher, err error) {
|
||||
ssd = make(map[string]SuppliersSorter)
|
||||
ssd[utils.MetaWeight] = NewWeightSorter(lcrS)
|
||||
ssd[utils.MetaLC] = NewLeastCostSorter(lcrS)
|
||||
ssd[utils.MetaHC] = NewHighestCostSorter(lcrS)
|
||||
ssd[utils.MetaQOS] = NewQOSSupplierSorter(lcrS)
|
||||
ssd[utils.MetaReas] = NewResourceAscendetSorter(lcrS)
|
||||
ssd[utils.MetaReds] = NewResourceDescendentSorter(lcrS)
|
||||
ssd[utils.MetaLoad] = NewLoadDistributionSorter(lcrS)
|
||||
return
|
||||
}
|
||||
|
||||
// SupplierStrategyHandler will initialize strategies
|
||||
// and dispatch requests to them
|
||||
type SupplierSortDispatcher map[string]SuppliersSorter
|
||||
|
||||
func (ssd SupplierSortDispatcher) SortSuppliers(prflID, strategy string,
|
||||
suppls []*Supplier, suplEv *utils.CGREvent, extraOpts *optsGetSuppliers) (sortedSuppls *SortedSuppliers, err error) {
|
||||
sd, has := ssd[strategy]
|
||||
if !has {
|
||||
return nil, fmt.Errorf("unsupported sorting strategy: %s", strategy)
|
||||
}
|
||||
if sortedSuppls, err = sd.SortSuppliers(prflID, suppls, suplEv, extraOpts); err != nil {
|
||||
return
|
||||
}
|
||||
if len(sortedSuppls.SortedSuppliers) == 0 {
|
||||
return nil, utils.ErrNotFound
|
||||
}
|
||||
return
|
||||
}
|
||||
@@ -1893,28 +1893,28 @@ func FilterToTPFilter(f *Filter) (tpFltr *utils.TPFilterProfile) {
|
||||
return
|
||||
}
|
||||
|
||||
type TpSuppliers []*TpSupplier
|
||||
type TPRoutes []*TpRoute
|
||||
|
||||
// CSVHeader return the header for csv fields as a slice of string
|
||||
func (tps TpSuppliers) CSVHeader() (result []string) {
|
||||
func (tps TPRoutes) CSVHeader() (result []string) {
|
||||
return []string{"#" + utils.Tenant, utils.ID, utils.FilterIDs, utils.ActivationIntervalString,
|
||||
utils.Sorting, utils.SortingParameters, utils.SupplierID, utils.SupplierFilterIDs,
|
||||
utils.SupplierAccountIDs, utils.SupplierRatingplanIDs, utils.SupplierResourceIDs,
|
||||
utils.SupplierStatIDs, utils.SupplierWeight, utils.SupplierBlocker,
|
||||
utils.SupplierParameters, utils.Weight,
|
||||
utils.Sorting, utils.SortingParameters, utils.RouteID, utils.RouteFilterIDs,
|
||||
utils.RouteAccountIDs, utils.RouteRatingplanIDs, utils.RouteResourceIDs,
|
||||
utils.RouteStatIDs, utils.RouteWeight, utils.RouteBlocker,
|
||||
utils.RouteParameters, utils.Weight,
|
||||
}
|
||||
}
|
||||
|
||||
func (tps TpSuppliers) AsTPSuppliers() (result []*utils.TPSupplierProfile) {
|
||||
func (tps TPRoutes) AsTPRouteProfile() (result []*utils.TPRouteProfile) {
|
||||
filtermap := make(map[string]utils.StringMap)
|
||||
mst := make(map[string]*utils.TPSupplierProfile)
|
||||
suppliersMap := make(map[string]map[string]*utils.TPSupplier)
|
||||
mst := make(map[string]*utils.TPRouteProfile)
|
||||
suppliersMap := make(map[string]map[string]*utils.TPRoute)
|
||||
sortingParameterMap := make(map[string]utils.StringMap)
|
||||
for _, tp := range tps {
|
||||
tenID := (&utils.TenantID{Tenant: tp.Tenant, ID: tp.ID}).TenantID()
|
||||
th, found := mst[tenID]
|
||||
if !found {
|
||||
th = &utils.TPSupplierProfile{
|
||||
th = &utils.TPRouteProfile{
|
||||
TPid: tp.Tpid,
|
||||
Tenant: tp.Tenant,
|
||||
ID: tp.ID,
|
||||
@@ -1922,42 +1922,42 @@ func (tps TpSuppliers) AsTPSuppliers() (result []*utils.TPSupplierProfile) {
|
||||
SortingParameters: []string{},
|
||||
}
|
||||
}
|
||||
if tp.SupplierID != "" {
|
||||
if tp.RouteID != "" {
|
||||
if _, has := suppliersMap[tenID]; !has {
|
||||
suppliersMap[(&utils.TenantID{Tenant: tp.Tenant, ID: tp.ID}).TenantID()] = make(map[string]*utils.TPSupplier)
|
||||
suppliersMap[(&utils.TenantID{Tenant: tp.Tenant, ID: tp.ID}).TenantID()] = make(map[string]*utils.TPRoute)
|
||||
}
|
||||
sup, found := suppliersMap[tenID][tp.SupplierID]
|
||||
sup, found := suppliersMap[tenID][tp.RouteID]
|
||||
if !found {
|
||||
sup = &utils.TPSupplier{
|
||||
ID: tp.SupplierID,
|
||||
Weight: tp.SupplierWeight,
|
||||
Blocker: tp.SupplierBlocker,
|
||||
sup = &utils.TPRoute{
|
||||
ID: tp.RouteID,
|
||||
Weight: tp.RouteWeight,
|
||||
Blocker: tp.RouteBlocker,
|
||||
}
|
||||
}
|
||||
if tp.SupplierParameters != "" {
|
||||
sup.SupplierParameters = tp.SupplierParameters
|
||||
if tp.RouteParameters != "" {
|
||||
sup.RouteParameters = tp.RouteParameters
|
||||
}
|
||||
if tp.SupplierFilterIDs != "" {
|
||||
supFilterSplit := strings.Split(tp.SupplierFilterIDs, utils.INFIELD_SEP)
|
||||
if tp.RouteFilterIDs != "" {
|
||||
supFilterSplit := strings.Split(tp.RouteFilterIDs, utils.INFIELD_SEP)
|
||||
sup.FilterIDs = append(sup.FilterIDs, supFilterSplit...)
|
||||
}
|
||||
if tp.SupplierRatingplanIDs != "" {
|
||||
ratingPlanSplit := strings.Split(tp.SupplierRatingplanIDs, utils.INFIELD_SEP)
|
||||
if tp.RouteRatingplanIDs != "" {
|
||||
ratingPlanSplit := strings.Split(tp.RouteRatingplanIDs, utils.INFIELD_SEP)
|
||||
sup.RatingPlanIDs = append(sup.RatingPlanIDs, ratingPlanSplit...)
|
||||
}
|
||||
if tp.SupplierResourceIDs != "" {
|
||||
resSplit := strings.Split(tp.SupplierResourceIDs, utils.INFIELD_SEP)
|
||||
if tp.RouteResourceIDs != "" {
|
||||
resSplit := strings.Split(tp.RouteResourceIDs, utils.INFIELD_SEP)
|
||||
sup.ResourceIDs = append(sup.ResourceIDs, resSplit...)
|
||||
}
|
||||
if tp.SupplierStatIDs != "" {
|
||||
statSplit := strings.Split(tp.SupplierStatIDs, utils.INFIELD_SEP)
|
||||
if tp.RouteStatIDs != "" {
|
||||
statSplit := strings.Split(tp.RouteStatIDs, utils.INFIELD_SEP)
|
||||
sup.StatIDs = append(sup.StatIDs, statSplit...)
|
||||
}
|
||||
if tp.SupplierAccountIDs != "" {
|
||||
accSplit := strings.Split(tp.SupplierAccountIDs, utils.INFIELD_SEP)
|
||||
if tp.RouteAccountIDs != "" {
|
||||
accSplit := strings.Split(tp.RouteAccountIDs, utils.INFIELD_SEP)
|
||||
sup.AccountIDs = append(sup.AccountIDs, accSplit...)
|
||||
}
|
||||
suppliersMap[(&utils.TenantID{Tenant: tp.Tenant, ID: tp.ID}).TenantID()][tp.SupplierID] = sup
|
||||
suppliersMap[(&utils.TenantID{Tenant: tp.Tenant, ID: tp.ID}).TenantID()][tp.RouteID] = sup
|
||||
}
|
||||
if tp.SortingParameters != "" {
|
||||
if _, has := sortingParameterMap[tenID]; !has {
|
||||
@@ -1992,12 +1992,12 @@ func (tps TpSuppliers) AsTPSuppliers() (result []*utils.TPSupplierProfile) {
|
||||
}
|
||||
mst[(&utils.TenantID{Tenant: tp.Tenant, ID: tp.ID}).TenantID()] = th
|
||||
}
|
||||
result = make([]*utils.TPSupplierProfile, len(mst))
|
||||
result = make([]*utils.TPRouteProfile, len(mst))
|
||||
i := 0
|
||||
for tntID, th := range mst {
|
||||
result[i] = th
|
||||
for _, supdata := range suppliersMap[tntID] {
|
||||
result[i].Suppliers = append(result[i].Suppliers, supdata)
|
||||
result[i].Routes = append(result[i].Routes, supdata)
|
||||
}
|
||||
for filterdata := range filtermap[tntID] {
|
||||
result[i].FilterIDs = append(result[i].FilterIDs, filterdata)
|
||||
@@ -2010,12 +2010,12 @@ func (tps TpSuppliers) AsTPSuppliers() (result []*utils.TPSupplierProfile) {
|
||||
return
|
||||
}
|
||||
|
||||
func APItoModelTPSuppliers(st *utils.TPSupplierProfile) (mdls TpSuppliers) {
|
||||
if len(st.Suppliers) == 0 {
|
||||
func APItoModelTPRoutes(st *utils.TPRouteProfile) (mdls TPRoutes) {
|
||||
if len(st.Routes) == 0 {
|
||||
return
|
||||
}
|
||||
for i, supl := range st.Suppliers {
|
||||
mdl := &TpSupplier{
|
||||
for i, supl := range st.Routes {
|
||||
mdl := &TpRoute{
|
||||
Tenant: st.Tenant,
|
||||
Tpid: st.TPid,
|
||||
ID: st.ID,
|
||||
@@ -2044,119 +2044,119 @@ func APItoModelTPSuppliers(st *utils.TPSupplierProfile) (mdls TpSuppliers) {
|
||||
}
|
||||
}
|
||||
}
|
||||
mdl.SupplierID = supl.ID
|
||||
mdl.RouteID = supl.ID
|
||||
for i, val := range supl.AccountIDs {
|
||||
if i != 0 {
|
||||
mdl.SupplierAccountIDs += utils.INFIELD_SEP
|
||||
mdl.RouteAccountIDs += utils.INFIELD_SEP
|
||||
}
|
||||
mdl.SupplierAccountIDs += val
|
||||
mdl.RouteAccountIDs += val
|
||||
}
|
||||
for i, val := range supl.RatingPlanIDs {
|
||||
if i != 0 {
|
||||
mdl.SupplierRatingplanIDs += utils.INFIELD_SEP
|
||||
mdl.RouteRatingplanIDs += utils.INFIELD_SEP
|
||||
}
|
||||
mdl.SupplierRatingplanIDs += val
|
||||
mdl.RouteRatingplanIDs += val
|
||||
}
|
||||
for i, val := range supl.FilterIDs {
|
||||
if i != 0 {
|
||||
mdl.SupplierFilterIDs += utils.INFIELD_SEP
|
||||
mdl.RouteFilterIDs += utils.INFIELD_SEP
|
||||
}
|
||||
mdl.SupplierFilterIDs += val
|
||||
mdl.RouteFilterIDs += val
|
||||
}
|
||||
for i, val := range supl.ResourceIDs {
|
||||
if i != 0 {
|
||||
mdl.SupplierResourceIDs += utils.INFIELD_SEP
|
||||
mdl.RouteResourceIDs += utils.INFIELD_SEP
|
||||
}
|
||||
mdl.SupplierResourceIDs += val
|
||||
mdl.RouteResourceIDs += val
|
||||
}
|
||||
for i, val := range supl.StatIDs {
|
||||
if i != 0 {
|
||||
mdl.SupplierStatIDs += utils.INFIELD_SEP
|
||||
mdl.RouteStatIDs += utils.INFIELD_SEP
|
||||
}
|
||||
mdl.SupplierStatIDs += val
|
||||
mdl.RouteStatIDs += val
|
||||
}
|
||||
mdl.SupplierWeight = supl.Weight
|
||||
mdl.SupplierParameters = supl.SupplierParameters
|
||||
mdl.SupplierBlocker = supl.Blocker
|
||||
mdl.RouteWeight = supl.Weight
|
||||
mdl.RouteParameters = supl.RouteParameters
|
||||
mdl.RouteBlocker = supl.Blocker
|
||||
mdls = append(mdls, mdl)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func APItoSupplierProfile(tpSPP *utils.TPSupplierProfile, timezone string) (spp *SupplierProfile, err error) {
|
||||
spp = &SupplierProfile{
|
||||
Tenant: tpSPP.Tenant,
|
||||
ID: tpSPP.ID,
|
||||
Sorting: tpSPP.Sorting,
|
||||
Weight: tpSPP.Weight,
|
||||
Suppliers: make([]*Supplier, len(tpSPP.Suppliers)),
|
||||
SortingParameters: make([]string, len(tpSPP.SortingParameters)),
|
||||
FilterIDs: make([]string, len(tpSPP.FilterIDs)),
|
||||
func APItoRouteProfile(tpRp *utils.TPRouteProfile, timezone string) (rp *RouteProfile, err error) {
|
||||
rp = &RouteProfile{
|
||||
Tenant: tpRp.Tenant,
|
||||
ID: tpRp.ID,
|
||||
Sorting: tpRp.Sorting,
|
||||
Weight: tpRp.Weight,
|
||||
Routes: make([]*Route, len(tpRp.Routes)),
|
||||
SortingParameters: make([]string, len(tpRp.SortingParameters)),
|
||||
FilterIDs: make([]string, len(tpRp.FilterIDs)),
|
||||
}
|
||||
for i, stp := range tpSPP.SortingParameters {
|
||||
spp.SortingParameters[i] = stp
|
||||
for i, stp := range tpRp.SortingParameters {
|
||||
rp.SortingParameters[i] = stp
|
||||
}
|
||||
for i, fli := range tpSPP.FilterIDs {
|
||||
spp.FilterIDs[i] = fli
|
||||
for i, fli := range tpRp.FilterIDs {
|
||||
rp.FilterIDs[i] = fli
|
||||
}
|
||||
if tpSPP.ActivationInterval != nil {
|
||||
if spp.ActivationInterval, err = tpSPP.ActivationInterval.AsActivationInterval(timezone); err != nil {
|
||||
if tpRp.ActivationInterval != nil {
|
||||
if rp.ActivationInterval, err = tpRp.ActivationInterval.AsActivationInterval(timezone); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
for i, suplier := range tpSPP.Suppliers {
|
||||
spp.Suppliers[i] = &Supplier{
|
||||
ID: suplier.ID,
|
||||
Weight: suplier.Weight,
|
||||
Blocker: suplier.Blocker,
|
||||
RatingPlanIDs: suplier.RatingPlanIDs,
|
||||
AccountIDs: suplier.AccountIDs,
|
||||
FilterIDs: suplier.FilterIDs,
|
||||
ResourceIDs: suplier.ResourceIDs,
|
||||
StatIDs: suplier.StatIDs,
|
||||
SupplierParameters: suplier.SupplierParameters,
|
||||
for i, route := range tpRp.Routes {
|
||||
rp.Routes[i] = &Route{
|
||||
ID: route.ID,
|
||||
Weight: route.Weight,
|
||||
Blocker: route.Blocker,
|
||||
RatingPlanIDs: route.RatingPlanIDs,
|
||||
AccountIDs: route.AccountIDs,
|
||||
FilterIDs: route.FilterIDs,
|
||||
ResourceIDs: route.ResourceIDs,
|
||||
StatIDs: route.StatIDs,
|
||||
RouteParameters: route.RouteParameters,
|
||||
}
|
||||
}
|
||||
return spp, nil
|
||||
return rp, nil
|
||||
}
|
||||
|
||||
func SupplierProfileToAPI(spp *SupplierProfile) (tpSPP *utils.TPSupplierProfile) {
|
||||
tpSPP = &utils.TPSupplierProfile{
|
||||
Tenant: spp.Tenant,
|
||||
ID: spp.ID,
|
||||
FilterIDs: make([]string, len(spp.FilterIDs)),
|
||||
func RouteProfileToAPI(rp *RouteProfile) (tpRp *utils.TPRouteProfile) {
|
||||
tpRp = &utils.TPRouteProfile{
|
||||
Tenant: rp.Tenant,
|
||||
ID: rp.ID,
|
||||
FilterIDs: make([]string, len(rp.FilterIDs)),
|
||||
ActivationInterval: new(utils.TPActivationInterval),
|
||||
Sorting: spp.Sorting,
|
||||
SortingParameters: make([]string, len(spp.SortingParameters)),
|
||||
Suppliers: make([]*utils.TPSupplier, len(spp.Suppliers)),
|
||||
Weight: spp.Weight,
|
||||
Sorting: rp.Sorting,
|
||||
SortingParameters: make([]string, len(rp.SortingParameters)),
|
||||
Routes: make([]*utils.TPRoute, len(rp.Routes)),
|
||||
Weight: rp.Weight,
|
||||
}
|
||||
|
||||
for i, supp := range spp.Suppliers {
|
||||
tpSPP.Suppliers[i] = &utils.TPSupplier{
|
||||
ID: supp.ID,
|
||||
FilterIDs: supp.FilterIDs,
|
||||
AccountIDs: supp.AccountIDs,
|
||||
RatingPlanIDs: supp.RatingPlanIDs,
|
||||
ResourceIDs: supp.ResourceIDs,
|
||||
StatIDs: supp.StatIDs,
|
||||
Weight: supp.Weight,
|
||||
Blocker: supp.Blocker,
|
||||
SupplierParameters: supp.SupplierParameters,
|
||||
for i, route := range rp.Routes {
|
||||
tpRp.Routes[i] = &utils.TPRoute{
|
||||
ID: route.ID,
|
||||
FilterIDs: route.FilterIDs,
|
||||
AccountIDs: route.AccountIDs,
|
||||
RatingPlanIDs: route.RatingPlanIDs,
|
||||
ResourceIDs: route.ResourceIDs,
|
||||
StatIDs: route.StatIDs,
|
||||
Weight: route.Weight,
|
||||
Blocker: route.Blocker,
|
||||
RouteParameters: route.RouteParameters,
|
||||
}
|
||||
}
|
||||
for i, fli := range spp.FilterIDs {
|
||||
tpSPP.FilterIDs[i] = fli
|
||||
for i, fli := range rp.FilterIDs {
|
||||
tpRp.FilterIDs[i] = fli
|
||||
}
|
||||
for i, fli := range spp.SortingParameters {
|
||||
tpSPP.SortingParameters[i] = fli
|
||||
for i, fli := range rp.SortingParameters {
|
||||
tpRp.SortingParameters[i] = fli
|
||||
}
|
||||
if spp.ActivationInterval != nil {
|
||||
if !spp.ActivationInterval.ActivationTime.IsZero() {
|
||||
tpSPP.ActivationInterval.ActivationTime = spp.ActivationInterval.ActivationTime.Format(time.RFC3339)
|
||||
if rp.ActivationInterval != nil {
|
||||
if !rp.ActivationInterval.ActivationTime.IsZero() {
|
||||
tpRp.ActivationInterval.ActivationTime = rp.ActivationInterval.ActivationTime.Format(time.RFC3339)
|
||||
}
|
||||
if !spp.ActivationInterval.ExpiryTime.IsZero() {
|
||||
tpSPP.ActivationInterval.ExpiryTime = spp.ActivationInterval.ExpiryTime.Format(time.RFC3339)
|
||||
if !rp.ActivationInterval.ExpiryTime.IsZero() {
|
||||
tpRp.ActivationInterval.ExpiryTime = rp.ActivationInterval.ExpiryTime.Format(time.RFC3339)
|
||||
}
|
||||
}
|
||||
return
|
||||
|
||||
@@ -348,26 +348,26 @@ func (t TBLVersion) TableName() string {
|
||||
return utils.TBLVersions
|
||||
}
|
||||
|
||||
type TpSupplier struct {
|
||||
PK uint `gorm:"primary_key"`
|
||||
Tpid string
|
||||
Tenant string `index:"0" re:""`
|
||||
ID string `index:"1" re:""`
|
||||
FilterIDs string `index:"2" re:""`
|
||||
ActivationInterval string `index:"3" re:""`
|
||||
Sorting string `index:"4" re:""`
|
||||
SortingParameters string `index:"5" re:""`
|
||||
SupplierID string `index:"6" re:""`
|
||||
SupplierFilterIDs string `index:"7" re:""`
|
||||
SupplierAccountIDs string `index:"8" re:""`
|
||||
SupplierRatingplanIDs string `index:"9" re:""`
|
||||
SupplierResourceIDs string `index:"10" re:""`
|
||||
SupplierStatIDs string `index:"11" re:""`
|
||||
SupplierWeight float64 `index:"12" re:"\d+\.?\d*"`
|
||||
SupplierBlocker bool `index:"13" re:""`
|
||||
SupplierParameters string `index:"14" re:""`
|
||||
Weight float64 `index:"15" re:"\d+\.?\d*"`
|
||||
CreatedAt time.Time
|
||||
type TpRoute struct {
|
||||
PK uint `gorm:"primary_key"`
|
||||
Tpid string
|
||||
Tenant string `index:"0" re:""`
|
||||
ID string `index:"1" re:""`
|
||||
FilterIDs string `index:"2" re:""`
|
||||
ActivationInterval string `index:"3" re:""`
|
||||
Sorting string `index:"4" re:""`
|
||||
SortingParameters string `index:"5" re:""`
|
||||
RouteID string `index:"6" re:""`
|
||||
RouteFilterIDs string `index:"7" re:""`
|
||||
RouteAccountIDs string `index:"8" re:""`
|
||||
RouteRatingplanIDs string `index:"9" re:""`
|
||||
RouteResourceIDs string `index:"10" re:""`
|
||||
RouteStatIDs string `index:"11" re:""`
|
||||
RouteWeight float64 `index:"12" re:"\d+\.?\d*"`
|
||||
RouteBlocker bool `index:"13" re:""`
|
||||
RouteParameters string `index:"14" re:""`
|
||||
Weight float64 `index:"15" re:"\d+\.?\d*"`
|
||||
CreatedAt time.Time
|
||||
}
|
||||
|
||||
type TPAttribute struct {
|
||||
|
||||
@@ -22,24 +22,24 @@ import (
|
||||
"github.com/cgrates/cgrates/utils"
|
||||
)
|
||||
|
||||
func NewWeightSorter(spS *SupplierService) *WeightSorter {
|
||||
return &WeightSorter{spS: spS,
|
||||
func NewWeightSorter(rS *RouteService) *WeightSorter {
|
||||
return &WeightSorter{rS: rS,
|
||||
sorting: utils.MetaWeight}
|
||||
}
|
||||
|
||||
// WeightSorter orders suppliers based on their weight, no cost involved
|
||||
type WeightSorter struct {
|
||||
sorting string
|
||||
spS *SupplierService
|
||||
rS *RouteService
|
||||
}
|
||||
|
||||
func (ws *WeightSorter) SortSuppliers(prflID string,
|
||||
suppls []*Supplier, suplEv *utils.CGREvent, extraOpts *optsGetSuppliers) (sortedSuppls *SortedSuppliers, err error) {
|
||||
suppls []*Route, suplEv *utils.CGREvent, extraOpts *optsGetSuppliers) (sortedSuppls *SortedSuppliers, err error) {
|
||||
sortedSuppls = &SortedSuppliers{ProfileID: prflID,
|
||||
Sorting: ws.sorting,
|
||||
SortedSuppliers: make([]*SortedSupplier, 0)}
|
||||
for _, s := range suppls {
|
||||
if srtSpl, pass, err := ws.spS.populateSortingData(suplEv, s, extraOpts); err != nil {
|
||||
if srtSpl, pass, err := ws.rS.populateSortingData(suplEv, s, extraOpts); err != nil {
|
||||
return nil, err
|
||||
} else if pass && srtSpl != nil {
|
||||
sortedSuppls.SortedSuppliers = append(sortedSuppls.SortedSuppliers, srtSpl)
|
||||
@@ -29,48 +29,48 @@ import (
|
||||
"github.com/cgrates/cgrates/utils"
|
||||
)
|
||||
|
||||
// Supplier defines supplier related information used within a SupplierProfile
|
||||
type Supplier struct {
|
||||
ID string // SupplierID
|
||||
FilterIDs []string
|
||||
AccountIDs []string
|
||||
RatingPlanIDs []string // used when computing price
|
||||
ResourceIDs []string // queried in some strategies
|
||||
StatIDs []string // queried in some strategies
|
||||
Weight float64
|
||||
Blocker bool // do not process further supplier after this one
|
||||
SupplierParameters string
|
||||
// Route defines routes related information used within a RouteProfile
|
||||
type Route struct {
|
||||
ID string // SupplierID
|
||||
FilterIDs []string
|
||||
AccountIDs []string
|
||||
RatingPlanIDs []string // used when computing price
|
||||
ResourceIDs []string // queried in some strategies
|
||||
StatIDs []string // queried in some strategies
|
||||
Weight float64
|
||||
Blocker bool // do not process further supplier after this one
|
||||
RouteParameters string
|
||||
|
||||
cacheSupplier map[string]interface{} // cache["*ratio"]=ratio
|
||||
cacheRoute map[string]interface{} // cache["*ratio"]=ratio
|
||||
lazyCheckRules []*FilterRule
|
||||
}
|
||||
|
||||
// SupplierProfile represents the configuration of a Supplier profile
|
||||
type SupplierProfile struct {
|
||||
// RouteProfile represents the configuration of a Supplier profile
|
||||
type RouteProfile struct {
|
||||
Tenant string
|
||||
ID string // LCR Profile ID
|
||||
FilterIDs []string
|
||||
ActivationInterval *utils.ActivationInterval // Activation interval
|
||||
Sorting string // Sorting strategy
|
||||
SortingParameters []string
|
||||
Suppliers []*Supplier
|
||||
Routes []*Route
|
||||
Weight float64
|
||||
|
||||
cache map[string]interface{}
|
||||
}
|
||||
|
||||
// SupplierProfileWithArgDispatcher is used in replicatorV1 for dispatcher
|
||||
type SupplierProfileWithArgDispatcher struct {
|
||||
*SupplierProfile
|
||||
type RouteProfileWithArgDispatcher struct {
|
||||
*RouteProfile
|
||||
*utils.ArgDispatcher
|
||||
}
|
||||
|
||||
func (sp *SupplierProfile) compileCacheParameters() error {
|
||||
if sp.Sorting == utils.MetaLoad {
|
||||
func (rp *RouteProfile) compileCacheParameters() error {
|
||||
if rp.Sorting == utils.MetaLoad {
|
||||
// construct the map for ratio
|
||||
ratioMap := make(map[string]int)
|
||||
// []string{"supplierID:Ratio"}
|
||||
for _, splIDWithRatio := range sp.SortingParameters {
|
||||
for _, splIDWithRatio := range rp.SortingParameters {
|
||||
splitted := strings.Split(splIDWithRatio, utils.CONCATENATED_KEY_SEP)
|
||||
ratioVal, err := strconv.Atoi(splitted[1])
|
||||
if err != nil {
|
||||
@@ -78,58 +78,58 @@ func (sp *SupplierProfile) compileCacheParameters() error {
|
||||
}
|
||||
ratioMap[splitted[0]] = ratioVal
|
||||
}
|
||||
// add the ratio for each supplier
|
||||
for _, supplier := range sp.Suppliers {
|
||||
supplier.cacheSupplier = make(map[string]interface{})
|
||||
if ratioSupplier, has := ratioMap[supplier.ID]; !has { // in case that ratio isn't defined for specific suppliers check for default
|
||||
// add the ratio for each route
|
||||
for _, route := range rp.Routes {
|
||||
route.cacheRoute = make(map[string]interface{})
|
||||
if ratioSupplier, has := ratioMap[route.ID]; !has { // in case that ratio isn't defined for specific suppliers check for default
|
||||
if ratioDefault, has := ratioMap[utils.MetaDefault]; !has { // in case that *default ratio isn't defined take it from config
|
||||
supplier.cacheSupplier[utils.MetaRatio] = config.CgrConfig().SupplierSCfg().DefaultRatio
|
||||
route.cacheRoute[utils.MetaRatio] = config.CgrConfig().SupplierSCfg().DefaultRatio
|
||||
} else {
|
||||
supplier.cacheSupplier[utils.MetaRatio] = ratioDefault
|
||||
route.cacheRoute[utils.MetaRatio] = ratioDefault
|
||||
}
|
||||
} else {
|
||||
supplier.cacheSupplier[utils.MetaRatio] = ratioSupplier
|
||||
route.cacheRoute[utils.MetaRatio] = ratioSupplier
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Compile is a wrapper for convenience setting up the SupplierProfile
|
||||
func (sp *SupplierProfile) Compile() error {
|
||||
return sp.compileCacheParameters()
|
||||
// Compile is a wrapper for convenience setting up the RouteProfile
|
||||
func (rp *RouteProfile) Compile() error {
|
||||
return rp.compileCacheParameters()
|
||||
}
|
||||
|
||||
// TenantID returns unique identifier of the LCRProfile in a multi-tenant environment
|
||||
func (rp *SupplierProfile) TenantID() string {
|
||||
func (rp *RouteProfile) TenantID() string {
|
||||
return utils.ConcatenatedKey(rp.Tenant, rp.ID)
|
||||
}
|
||||
|
||||
// SupplierProfiles is a sortable list of SupplierProfile
|
||||
type SupplierProfiles []*SupplierProfile
|
||||
// RouteProfiles is a sortable list of RouteProfile
|
||||
type RouteProfiles []*RouteProfile
|
||||
|
||||
// Sort is part of sort interface, sort based on Weight
|
||||
func (lps SupplierProfiles) Sort() {
|
||||
func (lps RouteProfiles) Sort() {
|
||||
sort.Slice(lps, func(i, j int) bool { return lps[i].Weight > lps[j].Weight })
|
||||
}
|
||||
|
||||
// NewSupplierService initializes the Supplier Service
|
||||
func NewSupplierService(dm *DataManager,
|
||||
filterS *FilterS, cgrcfg *config.CGRConfig, connMgr *ConnManager) (spS *SupplierService, err error) {
|
||||
spS = &SupplierService{
|
||||
// NewRouteService initializes the Route Service
|
||||
func NewRouteService(dm *DataManager,
|
||||
filterS *FilterS, cgrcfg *config.CGRConfig, connMgr *ConnManager) (rS *RouteService, err error) {
|
||||
rS = &RouteService{
|
||||
dm: dm,
|
||||
filterS: filterS,
|
||||
cgrcfg: cgrcfg,
|
||||
connMgr: connMgr,
|
||||
}
|
||||
if spS.sorter, err = NewSupplierSortDispatcher(spS); err != nil {
|
||||
if rS.sorter, err = NewRouteSortDispatcher(rS); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// SupplierService is the service computing Supplier queries
|
||||
type SupplierService struct {
|
||||
// RouteService is the service computing route queries
|
||||
type RouteService struct {
|
||||
dm *DataManager
|
||||
filterS *FilterS
|
||||
cgrcfg *config.CGRConfig
|
||||
@@ -138,17 +138,17 @@ type SupplierService struct {
|
||||
}
|
||||
|
||||
// ListenAndServe will initialize the service
|
||||
func (spS *SupplierService) ListenAndServe(exitChan chan bool) error {
|
||||
utils.Logger.Info(fmt.Sprintf("<%s> starting <%s> subsystem", utils.CoreS, utils.SupplierS))
|
||||
func (rpS *RouteService) ListenAndServe(exitChan chan bool) error {
|
||||
utils.Logger.Info(fmt.Sprintf("<%s> starting <%s> subsystem", utils.CoreS, utils.RouteS))
|
||||
e := <-exitChan
|
||||
exitChan <- e // put back for the others listening for shutdown request
|
||||
return nil
|
||||
}
|
||||
|
||||
// Shutdown is called to shutdown the service
|
||||
func (spS *SupplierService) Shutdown() error {
|
||||
utils.Logger.Info(fmt.Sprintf("<%s> service shutdown initialized", utils.SupplierS))
|
||||
utils.Logger.Info(fmt.Sprintf("<%s> service shutdown complete", utils.SupplierS))
|
||||
func (rpS *RouteService) Shutdown() error {
|
||||
utils.Logger.Info(fmt.Sprintf("<%s> service shutdown initialized", utils.RouteS))
|
||||
utils.Logger.Info(fmt.Sprintf("<%s> service shutdown complete", utils.RouteS))
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -1089,21 +1089,21 @@ type TPFilter struct {
|
||||
Values []string // Filter definition
|
||||
}
|
||||
|
||||
// TPSupplier is used in TPSupplierProfile
|
||||
type TPSupplier struct {
|
||||
ID string // SupplierID
|
||||
FilterIDs []string
|
||||
AccountIDs []string
|
||||
RatingPlanIDs []string // used when computing price
|
||||
ResourceIDs []string // queried in some strategies
|
||||
StatIDs []string // queried in some strategies
|
||||
Weight float64
|
||||
Blocker bool
|
||||
SupplierParameters string
|
||||
// TPRoute is used in TPRouteProfile
|
||||
type TPRoute struct {
|
||||
ID string // RouteID
|
||||
FilterIDs []string
|
||||
AccountIDs []string
|
||||
RatingPlanIDs []string // used when computing price
|
||||
ResourceIDs []string // queried in some strategies
|
||||
StatIDs []string // queried in some strategies
|
||||
Weight float64
|
||||
Blocker bool
|
||||
RouteParameters string
|
||||
}
|
||||
|
||||
// TPSupplierProfile is used in APIs to manage remotely offline SupplierProfile
|
||||
type TPSupplierProfile struct {
|
||||
// TPRouteProfile is used in APIs to manage remotely offline RouteProfile
|
||||
type TPRouteProfile struct {
|
||||
TPid string
|
||||
Tenant string
|
||||
ID string
|
||||
@@ -1111,7 +1111,7 @@ type TPSupplierProfile struct {
|
||||
ActivationInterval *TPActivationInterval // Time when this limit becomes active and expires
|
||||
Sorting string
|
||||
SortingParameters []string
|
||||
Suppliers []*TPSupplier
|
||||
Routes []*TPRoute
|
||||
Weight float64
|
||||
}
|
||||
|
||||
|
||||
@@ -558,15 +558,14 @@ const (
|
||||
Async = "Async"
|
||||
Sorting = "Sorting"
|
||||
SortingParameters = "SortingParameters"
|
||||
SupplierAccountIDs = "SupplierAccountIDs"
|
||||
SupplierRatingplanIDs = "SupplierRatingplanIDs"
|
||||
SupplierStatIDs = "SupplierStatIDs"
|
||||
SupplierWeight = "SupplierWeight"
|
||||
SupplierParameters = "SupplierParameters"
|
||||
SupplierBlocker = "SupplierBlocker"
|
||||
SupplierResourceIDs = "SupplierResourceIDs"
|
||||
SupplierID = "SupplierID"
|
||||
SupplierFilterIDs = "SupplierFilterIDs"
|
||||
RouteAccountIDs = "RouteAccountIDs"
|
||||
RouteRatingplanIDs = "RouteRatingplanIDs"
|
||||
RouteStatIDs = "RouteStatIDs"
|
||||
RouteWeight = "RouteWeight"
|
||||
RouteParameters = "RouteParameters"
|
||||
RouteBlocker = "RouteBlocker"
|
||||
RouteResourceIDs = "RouteResourceIDs"
|
||||
RouteFilterIDs = "RouteFilterIDs"
|
||||
AttributeFilterIDs = "AttributeFilterIDs"
|
||||
QueueLength = "QueueLength"
|
||||
TTL = "TTL"
|
||||
@@ -761,7 +760,7 @@ const (
|
||||
const (
|
||||
SessionS = "SessionS"
|
||||
AttributeS = "AttributeS"
|
||||
SupplierS = "SupplierS"
|
||||
RouteS = "RouteS"
|
||||
ResourceS = "ResourceS"
|
||||
StatService = "StatS"
|
||||
FilterS = "FilterS"
|
||||
|
||||
Reference in New Issue
Block a user