mirror of
https://github.com/cgrates/cgrates.git
synced 2026-02-15 21:29:52 +05:00
first working load distribution lcr
This commit is contained in:
@@ -20,6 +20,7 @@ package engine
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
@@ -37,6 +38,12 @@ const (
|
||||
LCR_STRATEGY_QOS_THRESHOLD = "*qos_threshold"
|
||||
LCR_STRATEGY_QOS = "*qos"
|
||||
LCR_STRATEGY_LOAD = "*load_distribution"
|
||||
|
||||
// used for load distribution sorting
|
||||
RAND_LIMIT = 99
|
||||
LOW_PRIORITY_LIMIT = 100
|
||||
MED_PRIORITY_LIMIT = 200
|
||||
HIGH_PRIORITY_LIMIT = 300
|
||||
)
|
||||
|
||||
// A request for LCR, used in APIer and SM where we need to expose it
|
||||
@@ -295,6 +302,7 @@ func (lc *LCRCost) Sort() {
|
||||
sort.Sort(QOSSorter(lc.SupplierCosts))
|
||||
case LCR_STRATEGY_LOAD:
|
||||
lc.SortLoadDistribution()
|
||||
sort.Sort(HighestSupplierCostSorter(lc.SupplierCosts))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -317,11 +325,11 @@ func (lc *LCRCost) SortLoadDistribution() {
|
||||
}
|
||||
}
|
||||
}
|
||||
supplierQueues := make(map[string]*StatsQueue)
|
||||
supplierQueues := make(map[*LCRSupplierCost]*StatsQueue)
|
||||
for _, supCost := range lc.SupplierCosts {
|
||||
for _, sq := range supCost.supplierQueues {
|
||||
if sq.conf.TimeWindow == winnerTimeWindow {
|
||||
supplierQueues[supCost.Supplier] = sq
|
||||
supplierQueues[supCost] = sq
|
||||
break
|
||||
}
|
||||
}
|
||||
@@ -333,13 +341,29 @@ func (lc *LCRCost) SortLoadDistribution() {
|
||||
// if some have a cdr count not divisible by ponder return them first and all ordered by cdr times, oldest first
|
||||
// if all have a multiple of ponder return in the order of cdr times, oldest first
|
||||
|
||||
// first put them in one of the above categories
|
||||
for supCost, sq := range supplierQueues {
|
||||
ponder := lc.GetSupplierPonder(supCost.Supplier)
|
||||
cdrCount := len(sq.Cdrs)
|
||||
if cdrCount < ponder {
|
||||
supCost.Cost = float64(LOW_PRIORITY_LIMIT + rand.Intn(RAND_LIMIT))
|
||||
continue
|
||||
}
|
||||
if cdrCount%ponder == 0 {
|
||||
supCost.Cost = float64(MED_PRIORITY_LIMIT+rand.Intn(RAND_LIMIT)) + time.Now().Sub(sq.Cdrs[len(sq.Cdrs)-1].SetupTime).Seconds()
|
||||
continue
|
||||
} else {
|
||||
supCost.Cost = float64(HIGH_PRIORITY_LIMIT+rand.Intn(RAND_LIMIT)) + time.Now().Sub(sq.Cdrs[len(sq.Cdrs)-1].SetupTime).Seconds()
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// used in load distribution strategy only
|
||||
// receives a long supplier id and will return the ponder found in strategy params
|
||||
func (lc *LCRCost) GetSupplierPonder(supplier string) float64 {
|
||||
func (lc *LCRCost) GetSupplierPonder(supplier string) int {
|
||||
// parse strategy params
|
||||
ponders := make(map[string]float64)
|
||||
ponders := make(map[string]int)
|
||||
params := strings.Split(lc.Entry.StrategyParams, utils.INFIELD_SEP)
|
||||
for _, param := range params {
|
||||
ponderSlice := strings.Split(param, utils.CONCATENATED_KEY_SEP)
|
||||
@@ -347,7 +371,7 @@ func (lc *LCRCost) GetSupplierPonder(supplier string) float64 {
|
||||
Logger.Warning(fmt.Sprintf("bad format in load distribution strategy param: %s", lc.Entry.StrategyParams))
|
||||
continue
|
||||
}
|
||||
p, err := strconv.ParseFloat(ponderSlice[1], 64)
|
||||
p, err := strconv.Atoi(ponderSlice[1])
|
||||
if err != nil {
|
||||
Logger.Warning(fmt.Sprintf("bad format in load distribution strategy param: %s", lc.Entry.StrategyParams))
|
||||
continue
|
||||
|
||||
@@ -280,6 +280,7 @@ func TestLCRCostSuppliersString(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestLCRCostSuppliersLoad(t *testing.T) {
|
||||
setupTime := time.Date(2015, 7, 31, 6, 43, 0, 0, time.UTC)
|
||||
lcrCost := &LCRCost{
|
||||
Entry: &LCREntry{DestinationId: utils.ANY, RPCategory: "call", Strategy: LCR_STRATEGY_LOAD, StrategyParams: "ivo12:10;dan12:3;*default:7", Weight: 10.0},
|
||||
SupplierCosts: []*LCRSupplierCost{
|
||||
@@ -287,21 +288,21 @@ func TestLCRCostSuppliersLoad(t *testing.T) {
|
||||
Supplier: "*out:tenant12:call:ivo12",
|
||||
supplierQueues: []*StatsQueue{
|
||||
&StatsQueue{
|
||||
Cdrs: []*QCdr{&QCdr{}, &QCdr{}, &QCdr{}},
|
||||
Cdrs: []*QCdr{&QCdr{SetupTime: setupTime}, &QCdr{SetupTime: setupTime}, &QCdr{SetupTime: setupTime}},
|
||||
conf: &CdrStats{
|
||||
QueueLength: 0,
|
||||
TimeWindow: 3 * time.Minute,
|
||||
},
|
||||
},
|
||||
&StatsQueue{
|
||||
Cdrs: []*QCdr{&QCdr{}, &QCdr{}, &QCdr{}},
|
||||
Cdrs: []*QCdr{&QCdr{SetupTime: setupTime}, &QCdr{SetupTime: setupTime}, &QCdr{SetupTime: setupTime}},
|
||||
conf: &CdrStats{
|
||||
QueueLength: 0,
|
||||
TimeWindow: 1 * time.Minute,
|
||||
},
|
||||
},
|
||||
&StatsQueue{
|
||||
Cdrs: []*QCdr{&QCdr{}, &QCdr{}, &QCdr{}},
|
||||
Cdrs: []*QCdr{&QCdr{SetupTime: setupTime}, &QCdr{SetupTime: setupTime}, &QCdr{SetupTime: setupTime}},
|
||||
conf: &CdrStats{
|
||||
QueueLength: 0,
|
||||
TimeWindow: 10 * time.Minute,
|
||||
@@ -313,21 +314,21 @@ func TestLCRCostSuppliersLoad(t *testing.T) {
|
||||
Supplier: "*out:tenant12:call:dan12",
|
||||
supplierQueues: []*StatsQueue{
|
||||
&StatsQueue{
|
||||
Cdrs: []*QCdr{&QCdr{}, &QCdr{}, &QCdr{}, &QCdr{}, &QCdr{}},
|
||||
Cdrs: []*QCdr{&QCdr{SetupTime: setupTime}, &QCdr{SetupTime: setupTime}, &QCdr{SetupTime: setupTime}, &QCdr{SetupTime: setupTime}, &QCdr{SetupTime: setupTime}},
|
||||
conf: &CdrStats{
|
||||
QueueLength: 0,
|
||||
TimeWindow: 10 * time.Minute,
|
||||
},
|
||||
},
|
||||
&StatsQueue{
|
||||
Cdrs: []*QCdr{&QCdr{}, &QCdr{}, &QCdr{}, &QCdr{}, &QCdr{}},
|
||||
Cdrs: []*QCdr{&QCdr{SetupTime: setupTime}, &QCdr{SetupTime: setupTime}, &QCdr{SetupTime: setupTime}, &QCdr{SetupTime: setupTime}, &QCdr{SetupTime: setupTime}},
|
||||
conf: &CdrStats{
|
||||
QueueLength: 0,
|
||||
TimeWindow: 7 * time.Minute,
|
||||
},
|
||||
},
|
||||
&StatsQueue{
|
||||
Cdrs: []*QCdr{&QCdr{}, &QCdr{}, &QCdr{}, &QCdr{}, &QCdr{}},
|
||||
Cdrs: []*QCdr{&QCdr{SetupTime: setupTime}, &QCdr{SetupTime: setupTime}, &QCdr{SetupTime: setupTime}, &QCdr{SetupTime: setupTime}, &QCdr{SetupTime: setupTime}},
|
||||
conf: &CdrStats{
|
||||
QueueLength: 0,
|
||||
TimeWindow: 7 * time.Minute,
|
||||
@@ -339,28 +340,28 @@ func TestLCRCostSuppliersLoad(t *testing.T) {
|
||||
Supplier: "*out:tenant12:call:rif12",
|
||||
supplierQueues: []*StatsQueue{
|
||||
&StatsQueue{
|
||||
Cdrs: []*QCdr{&QCdr{}, &QCdr{}},
|
||||
Cdrs: []*QCdr{&QCdr{SetupTime: setupTime}, &QCdr{SetupTime: setupTime}},
|
||||
conf: &CdrStats{
|
||||
QueueLength: 0,
|
||||
TimeWindow: 7 * time.Minute,
|
||||
},
|
||||
},
|
||||
&StatsQueue{
|
||||
Cdrs: []*QCdr{&QCdr{}, &QCdr{}},
|
||||
Cdrs: []*QCdr{&QCdr{SetupTime: setupTime}, &QCdr{SetupTime: setupTime}},
|
||||
conf: &CdrStats{
|
||||
QueueLength: 0,
|
||||
TimeWindow: 7 * time.Minute,
|
||||
},
|
||||
},
|
||||
&StatsQueue{
|
||||
Cdrs: []*QCdr{&QCdr{}, &QCdr{}},
|
||||
Cdrs: []*QCdr{&QCdr{SetupTime: setupTime}, &QCdr{SetupTime: setupTime}},
|
||||
conf: &CdrStats{
|
||||
QueueLength: 0,
|
||||
TimeWindow: 10 * time.Minute,
|
||||
},
|
||||
},
|
||||
&StatsQueue{
|
||||
Cdrs: []*QCdr{&QCdr{}, &QCdr{}},
|
||||
Cdrs: []*QCdr{&QCdr{SetupTime: setupTime}, &QCdr{SetupTime: setupTime}},
|
||||
conf: &CdrStats{
|
||||
QueueLength: 0,
|
||||
TimeWindow: 1 * time.Minute,
|
||||
@@ -374,6 +375,6 @@ func TestLCRCostSuppliersLoad(t *testing.T) {
|
||||
if lcrCost.SupplierCosts[0].Supplier != "" ||
|
||||
lcrCost.SupplierCosts[1].Supplier != "" ||
|
||||
lcrCost.SupplierCosts[2].Supplier != "" {
|
||||
//t.Error("Error soring on load distribution: ", utils.ToIJSON(lcrCost))
|
||||
t.Error("Error soring on load distribution: ", utils.ToIJSON(lcrCost))
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user