Changed Weight to Weights of type DynamicWeights in AttributeProfile

This commit is contained in:
andronache98
2022-01-26 15:16:31 +02:00
committed by Dan Christian Bogos
parent 50c1a3441f
commit 3ed0e7eaa2
11 changed files with 82 additions and 63 deletions

View File

@@ -609,7 +609,7 @@ func testAttributeSGetAttributeForEventAnyContext(t *testing.T) {
Value: "1001",
},
},
Weight: 10.0,
Weights: ";10.0",
},
}
var result string
@@ -644,7 +644,7 @@ func testAttributeSGetAttributeForEventAnyContext(t *testing.T) {
Value: "1001",
},
},
Weight: 10.0,
Weights: ";10.0",
}
if !reflect.DeepEqual(expAttrFromEv, attrReply) {
t.Errorf("Expecting: %s, received: %s", utils.ToJSON(expAttrFromEv), utils.ToJSON(attrReply))
@@ -680,7 +680,7 @@ func testAttributeSGetAttributeForEventSameAnyContext(t *testing.T) {
Value: "1001",
},
},
Weight: 10.0,
Weights: ";10.0",
}
if !reflect.DeepEqual(expAttrFromEv, attrReply) {
t.Errorf("Expecting: %s, received: %s", utils.ToJSON(expAttrFromEv), utils.ToJSON(attrReply))
@@ -738,7 +738,7 @@ func testAttributeSGetAttributeForEvent(t *testing.T) {
FilterIDs: []string{},
},
},
Weight: 10.0,
Weights: ";10.0",
}
if *encoding == utils.MetaGOB {
eAttrPrf.Attributes[0].FilterIDs = nil
@@ -764,7 +764,7 @@ func testAttributeSGetAttributeForEvent(t *testing.T) {
FilterIDs: []string{},
},
},
Weight: 10.0,
Weights: ";10.0",
},
}
if err := attrSRPC.Call(context.Background(), utils.AdminSv1SetAttributeProfile,
@@ -854,7 +854,7 @@ func testAttributeProcessEventWithSearchAndReplace(t *testing.T) {
},
},
Blocker: true,
Weight: 10,
Weights: ";10",
},
}
var result string
@@ -912,7 +912,7 @@ func testAttributeSProcessWithMultipleRuns(t *testing.T) {
Value: "Value1",
},
},
Weight: 10,
Weights: ";10",
},
}
attrPrf2 := &engine.APIAttributeProfileWithAPIOpts{
@@ -926,7 +926,7 @@ func testAttributeSProcessWithMultipleRuns(t *testing.T) {
Value: "Value2",
},
},
Weight: 20,
Weights: ";20",
},
}
attrPrf3 := &engine.APIAttributeProfileWithAPIOpts{
@@ -940,7 +940,7 @@ func testAttributeSProcessWithMultipleRuns(t *testing.T) {
Value: "Value3",
},
},
Weight: 30,
Weights: ";30",
},
}
// Add attribute in DM
@@ -1016,7 +1016,7 @@ func testAttributeSProcessWithMultipleRuns2(t *testing.T) {
Value: "Value1",
},
},
Weight: 10,
Weights: ";10",
},
}
attrPrf2 := &engine.APIAttributeProfileWithAPIOpts{
@@ -1030,7 +1030,7 @@ func testAttributeSProcessWithMultipleRuns2(t *testing.T) {
Value: "Value2",
},
},
Weight: 20,
Weights: ";20",
},
}
attrPrf3 := &engine.APIAttributeProfileWithAPIOpts{
@@ -1044,7 +1044,7 @@ func testAttributeSProcessWithMultipleRuns2(t *testing.T) {
Value: "Value3",
},
},
Weight: 30,
Weights: ";30",
},
}
// Add attributeProfiles

View File

@@ -449,7 +449,7 @@ func testCacheSSetMoreAttributeProfiles(t *testing.T) {
Value: "Value1",
},
},
Weight: 10,
Weights: ";10",
},
}
attrPrf2 := &engine.APIAttributeProfileWithAPIOpts{
@@ -463,7 +463,7 @@ func testCacheSSetMoreAttributeProfiles(t *testing.T) {
Value: "Value2",
},
},
Weight: 20,
Weights: ";20",
},
}
attrPrf3 := &engine.APIAttributeProfileWithAPIOpts{
@@ -477,7 +477,7 @@ func testCacheSSetMoreAttributeProfiles(t *testing.T) {
Value: "Value3",
},
},
Weight: 30,
Weights: ";30",
},
}
// Add attributeProfiles

View File

@@ -811,7 +811,7 @@ func TestFiltersSetFilterReloadCache(t *testing.T) {
APIAttributeProfile: &engine.APIAttributeProfile{
FilterIDs: []string{"FLTR_ID"},
ID: "ATTR_ID",
Weight: 10,
Weights: ";10",
Attributes: []*engine.ExternalAttribute{
{
Path: "*req.Account",
@@ -968,7 +968,7 @@ func TestFiltersSetFilterClearCache(t *testing.T) {
APIAttributeProfile: &engine.APIAttributeProfile{
FilterIDs: []string{"FLTR_ID"},
ID: "ATTR_ID",
Weight: 10,
Weights: ";10",
Attributes: []*engine.ExternalAttribute{
{
Path: "*req.Account",

View File

@@ -74,8 +74,10 @@ func (alS *AttributeS) attributeProfileForEvent(ctx *context.Context, tnt string
}
attrIDs = aPrflIDs.AsSlice()
}
var apWw *apWithWeight
for _, apID := range attrIDs {
aPrfl, err := alS.dm.GetAttributeProfile(ctx, tnt, apID, true, true, utils.NonTransactional)
var aPrfl *AttributeProfile
aPrfl, err = alS.dm.GetAttributeProfile(ctx, tnt, apID, true, true, utils.NonTransactional)
if err != nil {
if err == utils.ErrNotFound {
continue
@@ -92,18 +94,24 @@ func (alS *AttributeS) attributeProfileForEvent(ctx *context.Context, tnt string
continue
}
}
if (matchAttrPrfl == nil || matchAttrPrfl.Weight < aPrfl.Weight) &&
var apfWeight float64
if apfWeight, err = WeightFromDynamics(ctx, aPrfl.Weights,
alS.fltrS, tnt, evNm); err != nil {
return
}
if (apWw == nil || apWw.weight < apfWeight) &&
tntID != lastID &&
(profileRuns <= 0 || processedPrfNo[tntID] < profileRuns) {
matchAttrPrfl = aPrfl
apWw = &apWithWeight{aPrfl, apfWeight}
}
}
// All good, convert from Map to Slice so we can sort
if matchAttrPrfl == nil {
if apWw == nil {
return nil, utils.ErrNotFound
}
(evNm[utils.MetaVars].(utils.MapStorage))[utils.MetaAttrPrfTenantID] = matchAttrPrfl.TenantIDInline()
return
(evNm[utils.MetaVars].(utils.MapStorage))[utils.MetaAttrPrfTenantID] = apWw.AttributeProfile.TenantIDInline()
return apWw.AttributeProfile, nil
}
// AttrSProcessEventReply reply used for proccess event

View File

@@ -20,13 +20,17 @@ package engine
import (
"fmt"
"sort"
"strings"
"github.com/cgrates/cgrates/config"
"github.com/cgrates/cgrates/utils"
)
type apWithWeight struct {
*AttributeProfile
weight float64
}
// Attribute used by AttributeProfile to describe a single attribute
type Attribute struct {
FilterIDs []string
@@ -42,7 +46,7 @@ type AttributeProfile struct {
FilterIDs []string
Attributes []*Attribute
Blocker bool // blocker flag to stop processing on multiple runs
Weight float64
Weights utils.DynamicWeights
}
// AttributeProfileWithAPIOpts is used in replicatorV1 for dispatcher
@@ -81,10 +85,10 @@ func (ap *AttributeProfile) TenantIDInline() string {
// AttributeProfiles is a sortable list of Attribute profiles
type AttributeProfiles []*AttributeProfile
// Sort is part of sort interface, sort based on Weight
func (aps AttributeProfiles) Sort() {
sort.Slice(aps, func(i, j int) bool { return aps[i].Weight > aps[j].Weight })
}
// // Sort is part of sort interface, sort based on Weight
// func (aps AttributeProfiles) Sort() {
// sort.Slice(aps, func(i, j int) bool { return aps[i].Weights[i] > aps[j].Weights })
// }
// ExternalAttribute the attribute for external profile
type ExternalAttribute struct {
@@ -101,7 +105,7 @@ type APIAttributeProfile struct {
FilterIDs []string
Attributes []*ExternalAttribute
Blocker bool // blocker flag to stop processing on multiple runs
Weight float64
Weights string
}
type APIAttributeProfileWithAPIOpts struct {
@@ -116,7 +120,7 @@ func NewAPIAttributeProfile(attr *AttributeProfile) (ext *APIAttributeProfile) {
FilterIDs: attr.FilterIDs,
Attributes: make([]*ExternalAttribute, len(attr.Attributes)),
Blocker: attr.Blocker,
Weight: attr.Weight,
Weights: attr.Weights.String(utils.InfieldSep, utils.ANDSep),
}
for i, at := range attr.Attributes {
ext.Attributes[i] = &ExternalAttribute{
@@ -135,6 +139,11 @@ func (ext *APIAttributeProfile) AsAttributeProfile() (attr *AttributeProfile, er
if len(ext.Attributes) == 0 {
return nil, utils.NewErrMandatoryIeMissing("Attributes")
}
if ext.Weights != utils.EmptyString {
if attr.Weights, err = utils.NewDynamicWeightsFromString(ext.Weights, utils.InfieldSep, utils.ANDSep); err != nil {
return
}
}
attr.Attributes = make([]*Attribute, len(ext.Attributes))
for i, extAttr := range ext.Attributes {
if extAttr.Path == utils.EmptyString {
@@ -154,8 +163,6 @@ func (ext *APIAttributeProfile) AsAttributeProfile() (attr *AttributeProfile, er
attr.Tenant = ext.Tenant
attr.ID = ext.ID
attr.FilterIDs = ext.FilterIDs
attr.Blocker = ext.Blocker
attr.Weight = ext.Weight
return
}
@@ -203,7 +210,7 @@ func (ap *AttributeProfile) Set(path []string, val interface{}, newBranch bool,
ap.Blocker, err = utils.IfaceAsBool(val)
case utils.Weight:
if val != utils.EmptyString {
ap.Weight, err = utils.IfaceAsFloat64(val)
ap.Weights, err = utils.NewDynamicWeightsFromString(utils.IfaceAsString(val), utils.InfieldSep, utils.ANDSep)
}
default:
return utils.ErrWrongPath
@@ -248,9 +255,7 @@ func (ap *AttributeProfile) Merge(v2 interface{}) {
if vi.Blocker {
ap.Blocker = true
}
if vi.Weight != 0 {
ap.Weight = vi.Weight
}
ap.Weights = append(ap.Weights, vi.Weights...)
}
func (ap *AttributeProfile) String() string { return utils.ToJSON(ap) }
@@ -288,7 +293,7 @@ func (ap *AttributeProfile) FieldAsInterface(fldPath []string) (_ interface{}, e
case utils.Blocker:
return ap.Blocker, nil
case utils.Weight:
return ap.Weight, nil
return ap.Weights, nil
case utils.Attributes:
return ap.Attributes, nil
}

View File

@@ -411,7 +411,7 @@ func TestLoadAttributeProfiles(t *testing.T) {
},
},
Blocker: true,
Weight: 20,
Weights: 20,
},
}

View File

@@ -1065,8 +1065,8 @@ func (tps AttributeMdls) AsTPAttributes() (result []*utils.TPAttributeProfile) {
Blocker: tp.Blocker,
}
}
if tp.Weight != 0 {
th.Weight = tp.Weight
if tp.Weights != utils.EmptyString {
th.Weights = tp.Weights
}
if tp.FilterIDs != utils.EmptyString {
if _, has := filterMap[key.TenantID()]; !has {
@@ -1116,10 +1116,11 @@ func APItoModelTPAttribute(ap *utils.TPAttributeProfile) (mdls AttributeMdls) {
}
mdl.FilterIDs += val
}
if ap.Weight != 0 {
mdl.Weight = ap.Weight
if ap.Weights != utils.EmptyString {
mdl.Weights = ap.Weights
}
}
mdl.Path = reqAttribute.Path
mdl.Value = reqAttribute.Value
mdl.Type = reqAttribute.Type
@@ -1133,11 +1134,15 @@ func APItoAttributeProfile(tpAttr *utils.TPAttributeProfile, timezone string) (a
attrPrf = &AttributeProfile{
Tenant: tpAttr.Tenant,
ID: tpAttr.ID,
Weight: tpAttr.Weight,
Blocker: tpAttr.Blocker,
FilterIDs: make([]string, len(tpAttr.FilterIDs)),
Attributes: make([]*Attribute, len(tpAttr.Attributes)),
}
if tpAttr.Weights != utils.EmptyString {
if attrPrf.Weights, err = utils.NewDynamicWeightsFromString(tpAttr.Weights, utils.InfieldSep, utils.ANDSep); err != nil {
return
}
}
for i, fli := range tpAttr.FilterIDs {
attrPrf.FilterIDs[i] = fli
}
@@ -1167,7 +1172,7 @@ func AttributeProfileToAPI(attrPrf *AttributeProfile) (tpAttr *utils.TPAttribute
FilterIDs: make([]string, len(attrPrf.FilterIDs)),
Attributes: make([]*utils.TPAttribute, len(attrPrf.Attributes)),
Blocker: attrPrf.Blocker,
Weight: attrPrf.Weight,
Weights: attrPrf.Weights.String(utils.InfieldSep, utils.ANDSep),
}
for i, fli := range attrPrf.FilterIDs {
tpAttr.FilterIDs[i] = fli

View File

@@ -1047,7 +1047,7 @@ func TestAPItoAttributeProfile(t *testing.T) {
Value: "Al1",
},
},
Weight: 20,
Weights: 20,
}
expected := &AttributeProfile{
Tenant: "cgrates.org",
@@ -1080,7 +1080,7 @@ func TestAttributeProfileToAPI(t *testing.T) {
Value: "Al1",
},
},
Weight: 20,
Weights: 20,
}
attr := &AttributeProfile{
Tenant: "cgrates.org",
@@ -1115,7 +1115,7 @@ func TestAttributeProfileToAPI2(t *testing.T) {
Value: "~*req.Account",
},
},
Weight: 20,
Weights: 20,
}
attr := &AttributeProfile{
Tenant: "cgrates.org",
@@ -1150,7 +1150,7 @@ func TestAPItoModelTPAttribute(t *testing.T) {
Value: "Al1",
},
},
Weight: 20,
Weights: 20,
}
expected := AttributeMdls{
&AttributeMdl{
@@ -1161,7 +1161,7 @@ func TestAPItoModelTPAttribute(t *testing.T) {
AttributeFilterIDs: "filter_id1;filter_id2",
Path: utils.MetaReq + utils.NestingSep + "FL1",
Value: "Al1",
Weight: 20,
Weights: 20,
},
}
rcv := APItoModelTPAttribute(tpAlsPrf)
@@ -1186,7 +1186,7 @@ func TestCsvDumpForAttributeModels(t *testing.T) {
Value: "Al2",
},
},
Weight: 20,
Weights: 20,
}
expected := AttributeMdls{
&AttributeMdl{
@@ -1196,7 +1196,7 @@ func TestCsvDumpForAttributeModels(t *testing.T) {
FilterIDs: "FLTR_ACNT_dan;*ai:~*req.AnswerTime:2014-07-14T14:35:00Z;*string:~*opts.*context:con1",
Path: utils.MetaReq + utils.NestingSep + "FL1",
Value: "Al1",
Weight: 20,
Weights: 20,
},
&AttributeMdl{
Tpid: "TP1",
@@ -1231,7 +1231,7 @@ func TestModelAsTPAttribute2(t *testing.T) {
FilterIDs: "FLTR_ACNT_dan;FLTR_DST_DE;*ai:~*req.AnswerTime:2014-07-14T14:35:00Z|2014-07-14T14:36:00Z;*string:~*opts.*context:con1",
Path: utils.MetaReq + utils.NestingSep + "FL1",
Value: "Al1",
Weight: 20,
Weights: 20,
},
}
expected := &utils.TPAttributeProfile{
@@ -1246,7 +1246,7 @@ func TestModelAsTPAttribute2(t *testing.T) {
Value: "Al1",
},
},
Weight: 20,
Weights: 20,
}
expected2 := &utils.TPAttributeProfile{
TPid: "TP1",
@@ -1260,7 +1260,7 @@ func TestModelAsTPAttribute2(t *testing.T) {
Value: "Al1",
},
},
Weight: 20,
Weights: 20,
}
rcv := models.AsTPAttributes()
sort.Strings(rcv[0].FilterIDs)
@@ -1278,7 +1278,7 @@ func TestModelAsTPAttribute(t *testing.T) {
FilterIDs: "FLTR_ACNT_dan;FLTR_DST_DE;*ai:~*req.AnswerTime:2014-07-14T14:35:00Z;*string:~*opts.*context:con1",
Path: utils.MetaReq + utils.NestingSep + "FL1",
Value: "Al1",
Weight: 20,
Weights: 20,
},
}
expected := &utils.TPAttributeProfile{
@@ -1293,7 +1293,7 @@ func TestModelAsTPAttribute(t *testing.T) {
Value: "Al1",
},
},
Weight: 20,
Weights: 20,
}
expected2 := &utils.TPAttributeProfile{
TPid: "TP1",
@@ -1307,7 +1307,7 @@ func TestModelAsTPAttribute(t *testing.T) {
Value: "Al1",
},
},
Weight: 20,
Weights: 20,
}
rcv := models.AsTPAttributes()
sort.Strings(rcv[0].FilterIDs)
@@ -3979,7 +3979,7 @@ func TestAPItoAttributeProfileError1(t *testing.T) {
Value: "Al1",
},
},
Weight: 20,
Weights: 20,
}
_, err := APItoAttributeProfile(tpAlsPrf, "UTC")
@@ -4001,7 +4001,7 @@ func TestAPItoAttributeProfileError2(t *testing.T) {
Value: "\"constant;`>;q=0.7;expires=3600constant\"",
},
},
Weight: 20,
Weights: 20,
}
_, err := APItoAttributeProfile(tpAlsPrf, "UTC")

View File

@@ -221,7 +221,7 @@ type AttributeMdl struct {
Tenant string `index:"0" re:""`
ID string `index:"1" re:""`
FilterIDs string `index:"2" re:""`
Weight float64 `index:"3" re:"\d+\.?\d*"`
Weights string `index:"3" re:"\d+\.?\d*"`
AttributeFilterIDs string `index:"4" re:""`
Path string `index:"5" re:""`
Type string `index:"6" re:""`

View File

@@ -535,10 +535,11 @@ func (v6AttrPrf v6AttributeProfile) AsAttributeProfile() (attrPrf *engine.Attrib
Tenant: v6AttrPrf.Tenant,
ID: v6AttrPrf.ID,
FilterIDs: v6AttrPrf.FilterIDs,
Weight: v6AttrPrf.Weight,
Blocker: v6AttrPrf.Blocker,
Attributes: make([]*engine.Attribute, len(v6AttrPrf.Attributes)),
}
attrPrf.Weights = make(utils.DynamicWeights, 1)
attrPrf.Weights[0].Weight = v6AttrPrf.Weight
if strings.HasSuffix(fltr, utils.PipeSep) {
attrPrf.FilterIDs = append(attrPrf.FilterIDs, strings.TrimSuffix(fltr, utils.PipeSep))
}

View File

@@ -314,7 +314,7 @@ type TPAttributeProfile struct {
FilterIDs []string
Attributes []*TPAttribute
Blocker bool
Weight float64
Weights string
}
// TPChargerProfile is used in APIs to manage remotely offline ChargerProfile