From 1a38e51a5d49be4ea8b1f46a85abc278535f4970 Mon Sep 17 00:00:00 2001 From: armirveliaj Date: Mon, 21 Oct 2024 09:29:46 -0400 Subject: [PATCH] Add new API: RankingSv1.GetRankingSummary --- apier/v1/rankings.go | 15 ++++-- apier/v1/rankings_test.go | 6 ++- engine/rankings.go | 13 +++++ engine/rankings_test.go | 99 +++++++++++++++++++++++++++++++++++++++ services/rankings.go | 2 +- services/rankings_test.go | 9 ++++ 6 files changed, 139 insertions(+), 5 deletions(-) create mode 100644 engine/rankings_test.go diff --git a/apier/v1/rankings.go b/apier/v1/rankings.go index baabb72e9..cb1814731 100644 --- a/apier/v1/rankings.go +++ b/apier/v1/rankings.go @@ -128,8 +128,17 @@ func (apierSv1 *APIerSv1) RemoveRankingProfile(ctx *context.Context, args *utils } // NewRankingSv1 initializes RankingSV1 -func NewRankingSv1() *RankingSv1 { - return &RankingSv1{} +func NewRankingSv1(rnks *engine.RankingS) *RankingSv1 { + return &RankingSv1{ + rnkS: rnks, + } } -type RankingSv1 struct{} +type RankingSv1 struct { + rnkS *engine.RankingS +} + +// GetRankingSummary returns summary of the last updated ranking +func (rnks *RankingSv1) GetRankingSummary(ctx *context.Context, arg utils.TenantIDWithAPIOpts, reply *engine.RankingSummary) error { + return rnks.rnkS.V1GetRankingSummary(ctx, arg, reply) +} diff --git a/apier/v1/rankings_test.go b/apier/v1/rankings_test.go index dc57b0d36..2215a9a88 100644 --- a/apier/v1/rankings_test.go +++ b/apier/v1/rankings_test.go @@ -26,10 +26,14 @@ import ( ) func TestNewRankingSv1(t *testing.T) { - rankingSvc := NewRankingSv1() + rankingS := &engine.RankingS{} + rankingSvc := NewRankingSv1(rankingS) if rankingSvc == nil { t.Errorf("NewRankingSv1() returned nil") } + if rankingSvc.rnkS != rankingS { + t.Errorf("NewRankingSv1() did not correctly set rnkS field") + } } func TestRemoveRankingProfile(t *testing.T) { diff --git a/engine/rankings.go b/engine/rankings.go index 5897f3e9e..9a8f89a00 100644 --- a/engine/rankings.go +++ b/engine/rankings.go @@ -513,3 +513,16 @@ func (rkS *RankingS) V1GetSchedule(ctx *context.Context, args *utils.ArgSchedule *schedRankings = scheduledRankings return nil } + +// V1GetRankingSummary returns a summary of ascending/descending stat of the last updated ranking +func (rS *RankingS) V1GetRankingSummary(ctx *context.Context, arg utils.TenantIDWithAPIOpts, reply *RankingSummary) (err error) { + var rnk *Ranking + if rnk, err = rS.dm.GetRanking(arg.Tenant, arg.ID, true, true, utils.NonTransactional); err != nil { + return + } + rnk.rMux.RLock() + rnkS := rnk.asRankingSummary() + rnk.rMux.RUnlock() + *reply = *rnkS + return +} diff --git a/engine/rankings_test.go b/engine/rankings_test.go new file mode 100644 index 000000000..2d0ad0546 --- /dev/null +++ b/engine/rankings_test.go @@ -0,0 +1,99 @@ +/* +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 ( + "testing" + "time" + + "github.com/cgrates/cgrates/config" +) + +func TestNewRankingS(t *testing.T) { + dm := &DataManager{} + connMgr := &ConnManager{} + filterS := &FilterS{} + cgrcfg := &config.CGRConfig{} + + rankingS := NewRankingS(dm, connMgr, filterS, cgrcfg) + + if rankingS == nil { + t.Fatal("Expected RankingS to be non-nil, got nil") + } + + if rankingS.dm != dm { + t.Errorf("Expected dm to be '%v', got '%v'", dm, rankingS.dm) + } + if rankingS.connMgr != connMgr { + t.Errorf("Expected connMgr to be '%v', got '%v'", connMgr, rankingS.connMgr) + } + if rankingS.filterS != filterS { + t.Errorf("Expected filterS to be '%v', got '%v'", filterS, rankingS.filterS) + } + if rankingS.cgrcfg != cgrcfg { + t.Errorf("Expected cgrcfg to be '%v', got '%v'", cgrcfg, rankingS.cgrcfg) + } + if rankingS.crn == nil { + t.Error("Expected crn to be initialized, got nil") + } + if rankingS.crnTQsMux == nil { + t.Error("Expected crnTQsMux to be initialized, got nil") + } + if len(rankingS.crnTQs) != 0 { + t.Errorf("Expected crnTQs to be empty, got length %d", len(rankingS.crnTQs)) + } + if rankingS.storedRankings == nil { + t.Error("Expected storedRankings to be initialized, got nil") + } + if rankingS.storingStopped == nil { + t.Error("Expected storingStopped channel to be initialized, got nil") + } + if rankingS.rankingStop == nil { + t.Error("Expected rankingStop channel to be initialized, got nil") + } +} +func TestAsRankingSummary(t *testing.T) { + lastUpdateTime, err := time.Parse(time.RFC3339, "2024-10-21T00:00:00Z") + if err != nil { + t.Fatalf("Failed to parse time: %v", err) + } + + ranking := &Ranking{ + Tenant: "tenant1", + ID: "ranking1", + LastUpdate: lastUpdateTime, + SortedStatIDs: []string{"stat1", "stat2", "stat3"}, + Metrics: make(map[string]map[string]float64), + Sorting: "asc", + SortingParameters: []string{"param1", "param2"}, + } + + rkSm := ranking.asRankingSummary() + + if rkSm.Tenant != ranking.Tenant { + t.Errorf("Expected Tenant to be '%s', got '%s'", ranking.Tenant, rkSm.Tenant) + } + if rkSm.ID != ranking.ID { + t.Errorf("Expected ID to be '%s', got '%s'", ranking.ID, rkSm.ID) + } + if rkSm.LastUpdate != ranking.LastUpdate { + t.Errorf("Expected LastUpdate to be '%v', got '%v'", ranking.LastUpdate, rkSm.LastUpdate) + } + +} diff --git a/services/rankings.go b/services/rankings.go index 2b2fe8bfa..35df72f28 100644 --- a/services/rankings.go +++ b/services/rankings.go @@ -86,7 +86,7 @@ func (rk *RankingService) Start() error { if err := rk.rks.StartRankingS(); err != nil { return err } - srv, err := engine.NewService(v1.NewRankingSv1()) + srv, err := engine.NewService(v1.NewRankingSv1(rk.rks)) if err != nil { return err } diff --git a/services/rankings_test.go b/services/rankings_test.go index d48ef516f..9095ff7d5 100644 --- a/services/rankings_test.go +++ b/services/rankings_test.go @@ -23,6 +23,7 @@ import ( "testing" "github.com/cgrates/birpc" + v1 "github.com/cgrates/cgrates/apier/v1" "github.com/cgrates/cgrates/config" "github.com/cgrates/cgrates/cores" "github.com/cgrates/cgrates/engine" @@ -117,3 +118,11 @@ func TestIsRunning(t *testing.T) { t.Errorf("Expected IsRunning to return false, got %v", result) } } + +func TestNewRankingSv1(t *testing.T) { + rankingS := &engine.RankingS{} + rankingSv1 := v1.NewRankingSv1(rankingS) + if rankingSv1 == nil { + t.Fatal("Expected a non-nil RankingSv1 instance, got nil") + } +}