mirror of
https://github.com/cgrates/cgrates.git
synced 2026-02-11 18:16:24 +05:00
refactor profile sorting for chargers
This commit is contained in:
committed by
Dan Christian Bogos
parent
0b26559d1f
commit
b00b2f07ae
@@ -47,7 +47,7 @@ func (cS *ChargerS) V1ProcessEvent(ctx *context.Context, args *utils.CGREvent,
|
||||
|
||||
// V1GetChargersForEvent exposes the list of ordered matching ChargingProfiles for an event
|
||||
func (cS *ChargerS) V1GetChargersForEvent(ctx *context.Context, args *utils.CGREvent,
|
||||
rply *utils.ChargerProfiles) (err error) {
|
||||
rply *[]*utils.ChargerProfile) (err error) {
|
||||
tnt := args.Tenant
|
||||
if tnt == utils.EmptyString {
|
||||
tnt = cS.cfg.GeneralCfg().DefaultTenant
|
||||
|
||||
@@ -19,6 +19,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
package chargers
|
||||
|
||||
import (
|
||||
"cmp"
|
||||
"slices"
|
||||
|
||||
"github.com/cgrates/birpc/context"
|
||||
"github.com/cgrates/cgrates/config"
|
||||
"github.com/cgrates/cgrates/engine"
|
||||
@@ -40,7 +43,7 @@ func NewChargerService(dm *engine.DataManager, filterS *engine.FilterS,
|
||||
}
|
||||
|
||||
// matchingChargingProfilesForEvent returns ordered list of matching chargers which are active by the time of the function call
|
||||
func (cS *ChargerS) matchingChargerProfilesForEvent(ctx *context.Context, tnt string, cgrEv *utils.CGREvent) (cPs utils.ChargerProfiles, err error) {
|
||||
func (cS *ChargerS) matchingChargerProfilesForEvent(ctx *context.Context, tnt string, cgrEv *utils.CGREvent) (cPs []*utils.ChargerProfile, err error) {
|
||||
evNm := utils.MapStorage{
|
||||
utils.MetaReq: cgrEv.Event,
|
||||
utils.MetaOpts: cgrEv.APIOpts,
|
||||
@@ -58,6 +61,8 @@ func (cS *ChargerS) matchingChargerProfilesForEvent(ctx *context.Context, tnt st
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
weights := make(map[string]float64) // stores sorting weights by profile ID
|
||||
for cpID := range cpIDs {
|
||||
cP, err := cS.dm.GetChargerProfile(ctx, tnt, cpID, true, true, utils.NonTransactional)
|
||||
if err != nil {
|
||||
@@ -76,13 +81,18 @@ func (cS *ChargerS) matchingChargerProfilesForEvent(ctx *context.Context, tnt st
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cP.ApplySortingWeight(weight)
|
||||
weights[cP.ID] = weight
|
||||
cPs = append(cPs, cP)
|
||||
}
|
||||
if len(cPs) == 0 {
|
||||
return nil, utils.ErrNotFound
|
||||
}
|
||||
cPs.Sort()
|
||||
|
||||
// Sort by weight (higher values first).
|
||||
slices.SortFunc(cPs, func(a, b *utils.ChargerProfile) int {
|
||||
return cmp.Compare(weights[b.ID], weights[a.ID])
|
||||
})
|
||||
|
||||
for i, cp := range cPs {
|
||||
var blocker bool
|
||||
if blocker, err = engine.BlockerFromDynamics(ctx, cp.Blockers, cS.fltrS, tnt, evNm); err != nil {
|
||||
@@ -104,8 +114,8 @@ type ChrgSProcessEventReply struct {
|
||||
}
|
||||
|
||||
func (cS *ChargerS) processEvent(ctx *context.Context, tnt string, cgrEv *utils.CGREvent) (rply []*ChrgSProcessEventReply, err error) {
|
||||
var cPs utils.ChargerProfiles
|
||||
if cPs, err = cS.matchingChargerProfilesForEvent(ctx, tnt, cgrEv); err != nil {
|
||||
cPs, err := cS.matchingChargerProfilesForEvent(ctx, tnt, cgrEv)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
||||
@@ -761,7 +761,7 @@ func testChargersSetGetChargerProfileEvent(t *testing.T) {
|
||||
}
|
||||
func testChargersGetChargersForEvent(t *testing.T) {
|
||||
|
||||
expected := &utils.ChargerProfiles{
|
||||
expected := []*utils.ChargerProfile{
|
||||
{
|
||||
Tenant: "cgrates.org",
|
||||
ID: "TEST_CHARGERS_IT_TEST",
|
||||
@@ -783,7 +783,7 @@ func testChargersGetChargersForEvent(t *testing.T) {
|
||||
},
|
||||
APIOpts: map[string]any{},
|
||||
}
|
||||
reply := &utils.ChargerProfiles{}
|
||||
var reply []*utils.ChargerProfile
|
||||
if err := chargersRPC.Call(context.Background(), utils.ChargerSv1GetChargersForEvent,
|
||||
cgrEv, &reply); err != nil {
|
||||
t.Error(err)
|
||||
@@ -956,7 +956,7 @@ func testChargersBlockerGetChargersForEvent(t *testing.T) {
|
||||
},
|
||||
APIOpts: map[string]any{},
|
||||
}
|
||||
expected := utils.ChargerProfiles{
|
||||
expected := []*utils.ChargerProfile{
|
||||
{
|
||||
ID: "CHARGER_TEST_1",
|
||||
Tenant: "cgrates.org",
|
||||
@@ -1001,7 +1001,7 @@ func testChargersBlockerGetChargersForEvent(t *testing.T) {
|
||||
RunID: "run2",
|
||||
},
|
||||
}
|
||||
var reply utils.ChargerProfiles
|
||||
var reply utils.ChargerProfile
|
||||
if err := chargersRPC.Call(context.Background(), utils.ChargerSv1GetChargersForEvent, args, &reply); err != nil {
|
||||
t.Error(err)
|
||||
} else if !reflect.DeepEqual(reply, expected) {
|
||||
|
||||
@@ -34,8 +34,8 @@ import (
|
||||
|
||||
func TestChargerSetChargerProfiles(t *testing.T) {
|
||||
var dmCharger *engine.DataManager
|
||||
cPPs := utils.ChargerProfiles{
|
||||
&utils.ChargerProfile{
|
||||
cPPs := []*utils.ChargerProfile{
|
||||
{
|
||||
Tenant: "cgrates.org",
|
||||
ID: "CPP_1",
|
||||
FilterIDs: []string{"FLTR_CP_1", "FLTR_CP_4", "*string:~*opts.*subsys:*chargers", "*ai:~*req.AnswerTime:2014-07-14T14:25:00Z"},
|
||||
@@ -47,7 +47,7 @@ func TestChargerSetChargerProfiles(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
&utils.ChargerProfile{
|
||||
{
|
||||
Tenant: "cgrates.org",
|
||||
ID: "CPP_2",
|
||||
FilterIDs: []string{"FLTR_CP_2", "*ai:~*req.AnswerTime:2014-07-14T14:25:00Z"},
|
||||
@@ -59,7 +59,7 @@ func TestChargerSetChargerProfiles(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
&utils.ChargerProfile{
|
||||
{
|
||||
Tenant: "cgrates.org",
|
||||
ID: "CPP_3",
|
||||
FilterIDs: []string{"FLTR_CP_3", "*ai:~*req.AnswerTime:2014-07-14T14:25:00Z"},
|
||||
@@ -152,8 +152,8 @@ func TestChargerMatchingChargerProfilesForEvent(t *testing.T) {
|
||||
cfg := config.NewDefaultCGRConfig()
|
||||
var chargerSrv *ChargerS
|
||||
var dmCharger *engine.DataManager
|
||||
cPPs := utils.ChargerProfiles{
|
||||
&utils.ChargerProfile{
|
||||
cPPs := []*utils.ChargerProfile{
|
||||
{
|
||||
Tenant: "cgrates.org",
|
||||
ID: "CPP_1",
|
||||
FilterIDs: []string{"FLTR_CP_1", "FLTR_CP_4", "*string:~*opts.*subsys:*chargers", "*ai:~*req.AnswerTime:2014-07-14T14:25:00Z"},
|
||||
@@ -165,7 +165,7 @@ func TestChargerMatchingChargerProfilesForEvent(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
&utils.ChargerProfile{
|
||||
{
|
||||
Tenant: "cgrates.org",
|
||||
ID: "CPP_2",
|
||||
FilterIDs: []string{"FLTR_CP_2", "*ai:~*req.AnswerTime:2014-07-14T14:25:00Z"},
|
||||
@@ -177,7 +177,7 @@ func TestChargerMatchingChargerProfilesForEvent(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
&utils.ChargerProfile{
|
||||
{
|
||||
Tenant: "cgrates.org",
|
||||
ID: "CPP_3",
|
||||
FilterIDs: []string{"FLTR_CP_3", "*ai:~*req.AnswerTime:2014-07-14T14:25:00Z"},
|
||||
@@ -322,8 +322,8 @@ func TestChargerProcessEvent(t *testing.T) {
|
||||
cfg := config.NewDefaultCGRConfig()
|
||||
var chargerSrv *ChargerS
|
||||
var dmCharger *engine.DataManager
|
||||
cPPs := utils.ChargerProfiles{
|
||||
&utils.ChargerProfile{
|
||||
cPPs := []*utils.ChargerProfile{
|
||||
{
|
||||
Tenant: "cgrates.org",
|
||||
ID: "CPP_1",
|
||||
FilterIDs: []string{"FLTR_CP_1", "FLTR_CP_4", "*string:~*opts.*subsys:*chargers", "*ai:~*req.AnswerTime:2014-07-14T14:25:00Z"},
|
||||
@@ -335,7 +335,7 @@ func TestChargerProcessEvent(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
&utils.ChargerProfile{
|
||||
{
|
||||
Tenant: "cgrates.org",
|
||||
ID: "CPP_2",
|
||||
FilterIDs: []string{"FLTR_CP_2", "*ai:~*req.AnswerTime:2014-07-14T14:25:00Z"},
|
||||
@@ -347,7 +347,7 @@ func TestChargerProcessEvent(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
&utils.ChargerProfile{
|
||||
{
|
||||
Tenant: "cgrates.org",
|
||||
ID: "CPP_3",
|
||||
FilterIDs: []string{"FLTR_CP_3", "*ai:~*req.AnswerTime:2014-07-14T14:25:00Z"},
|
||||
@@ -461,7 +461,6 @@ func TestChargerProcessEvent(t *testing.T) {
|
||||
}
|
||||
//verify each charger from cache
|
||||
for _, cp := range cPPs {
|
||||
cp.ApplySortingWeight(20) // cached ChargerProfiles have weight==20
|
||||
if tempCp, err := dmCharger.GetChargerProfile(context.Background(), cp.Tenant, cp.ID,
|
||||
true, false, utils.NonTransactional); err != nil {
|
||||
t.Errorf("Error: %+v", err)
|
||||
@@ -886,7 +885,7 @@ func TestChargersmatchingChargerProfilesForEventBlockerTrue(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
exp := utils.ChargerProfiles{
|
||||
exp := []*utils.ChargerProfile{
|
||||
{
|
||||
Tenant: "cgrates.org",
|
||||
ID: "CPP_2",
|
||||
@@ -1445,9 +1444,9 @@ func TestChargersV1GetChargersForEventNilErr(t *testing.T) {
|
||||
utils.AccountField: "1001",
|
||||
},
|
||||
}
|
||||
reply := &utils.ChargerProfiles{}
|
||||
var reply []*utils.ChargerProfile
|
||||
|
||||
exp := &utils.ChargerProfiles{
|
||||
exp := []*utils.ChargerProfile{
|
||||
{
|
||||
Tenant: "cgrates.org",
|
||||
ID: "1001",
|
||||
@@ -1455,7 +1454,7 @@ func TestChargersV1GetChargersForEventNilErr(t *testing.T) {
|
||||
RunID: "*default",
|
||||
},
|
||||
}
|
||||
err := cS.V1GetChargersForEvent(context.Background(), args, reply)
|
||||
err := cS.V1GetChargersForEvent(context.Background(), args, &reply)
|
||||
|
||||
if err != nil {
|
||||
t.Errorf("\nexpected: <%+v>, \nreceived: <%+v>", nil, err)
|
||||
@@ -1495,11 +1494,10 @@ func TestChargersV1GetChargersForEventErr(t *testing.T) {
|
||||
utils.AccountField: "1001",
|
||||
},
|
||||
}
|
||||
reply := &utils.ChargerProfiles{}
|
||||
|
||||
exp := &utils.ChargerProfiles{}
|
||||
var reply []*utils.ChargerProfile
|
||||
var exp []*utils.ChargerProfile
|
||||
experr := fmt.Sprintf("SERVER_ERROR: %s", utils.ErrNotImplemented)
|
||||
err := cS.V1GetChargersForEvent(context.Background(), args, reply)
|
||||
err := cS.V1GetChargersForEvent(context.Background(), args, &reply)
|
||||
|
||||
if err == nil || err.Error() != experr {
|
||||
t.Errorf("\nexpected: <%+v>, \nreceived: <%+v>", experr, err)
|
||||
|
||||
@@ -59,6 +59,6 @@ func (self *CmdGetChargersForEvent) PostprocessRpcParams() error {
|
||||
}
|
||||
|
||||
func (self *CmdGetChargersForEvent) RpcResult() any {
|
||||
var atr utils.ChargerProfiles
|
||||
var atr []*utils.ChargerProfile
|
||||
return &atr
|
||||
}
|
||||
|
||||
@@ -18,18 +18,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
|
||||
package utils
|
||||
|
||||
import (
|
||||
"sort"
|
||||
)
|
||||
|
||||
// ChargerProfiles is a sortable list of Charger profiles
|
||||
type ChargerProfiles []*ChargerProfile
|
||||
|
||||
// Sort is part of sort interface, sort based on Weight.
|
||||
func (cp ChargerProfiles) Sort() {
|
||||
sort.Slice(cp, func(i, j int) bool { return cp[i].weight > cp[j].weight })
|
||||
}
|
||||
|
||||
// ChargerProfile defines the configuration of a Charger.
|
||||
type ChargerProfile struct {
|
||||
Tenant string
|
||||
@@ -39,12 +27,6 @@ type ChargerProfile struct {
|
||||
Blockers DynamicBlockers
|
||||
RunID string
|
||||
AttributeIDs []string // perform data aliasing based on these Attributes
|
||||
weight float64
|
||||
}
|
||||
|
||||
// ApplySortingWeight assigns a weight value used for sorting ChargerProfiles.
|
||||
func (cp *ChargerProfile) ApplySortingWeight(weight float64) {
|
||||
cp.weight = weight
|
||||
}
|
||||
|
||||
// TenantID returns the concatenated tenant and ID.
|
||||
|
||||
@@ -71,25 +71,6 @@ func TestChargerProfileSet(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestChargerProfilesSort(t *testing.T) {
|
||||
cp := ChargerProfiles{{}, {Weights: DynamicWeights{
|
||||
{
|
||||
Weight: 20,
|
||||
},
|
||||
},
|
||||
weight: 20}}
|
||||
exp := ChargerProfiles{{Weights: DynamicWeights{
|
||||
{
|
||||
Weight: 20,
|
||||
},
|
||||
},
|
||||
weight: 20}, {}}
|
||||
cp.Sort()
|
||||
if !reflect.DeepEqual(exp, cp) {
|
||||
t.Errorf("Expected %v \n but received \n %v", ToJSON(exp), ToJSON(cp))
|
||||
}
|
||||
}
|
||||
|
||||
func TestChargerProfileAsInterface(t *testing.T) {
|
||||
cp := ChargerProfile{
|
||||
Tenant: "cgrates.org",
|
||||
|
||||
Reference in New Issue
Block a user