Started adding FieldAsInterface for EventCost

This commit is contained in:
Trial97
2020-02-04 18:06:28 +02:00
committed by Dan Christian Bogos
parent b79b1dc39d
commit d8333b5b68
10 changed files with 180 additions and 21 deletions

View File

@@ -35,9 +35,9 @@ import (
)
var (
apierCfgPath string
apierCfg *config.CGRConfig
apierRPC *rpc.Client
apierCfgPath string
apierCfg *config.CGRConfig
apierRPC *rpc.Client
APIerSv2ConfigDIR string //run tests for specific configuration
sTestsAPIer = []func(t *testing.T){

View File

@@ -59,9 +59,9 @@ README:
* Execute remote Apis and test their replies(follow testtp scenario so we can test load in dataDb also).
*/
var (
cfgPath string
cfg *config.CGRConfig
rater *rpc.Client
cfgPath string
cfg *config.CGRConfig
rater *rpc.Client
APIerSv1ConfigDIR string
apierTests = []func(t *testing.T){

View File

@@ -34,10 +34,10 @@ import (
)
var (
apierCfgPath string
apierCfg *config.CGRConfig
apierRPC *rpc.Client
dm *engine.DataManager // share db connection here so we can check data we set through APIs
apierCfgPath string
apierCfg *config.CGRConfig
apierRPC *rpc.Client
dm *engine.DataManager // share db connection here so we can check data we set through APIs
APIerSv2ConfDIR string
sTestsv2it = []func(t *testing.T){

View File

@@ -236,6 +236,13 @@ func (scfg *SessionSCfg) loadFromJsonCfg(jsnCfg *SessionSJsonCfg) (err error) {
scfg.SessionTTLLastUsed = &sessionTTLLastUsed
}
}
if jsnCfg.Session_ttl_usage != nil {
if sessionTTLUsage, err := utils.ParseDurationWithNanosecs(*jsnCfg.Session_ttl_usage); err != nil {
return err
} else {
scfg.SessionTTLUsage = &sessionTTLUsage
}
}
if jsnCfg.Session_indexes != nil {
scfg.SessionIndexes = utils.StringMapFromSlice(*jsnCfg.Session_indexes)
}

View File

@@ -20,11 +20,15 @@ package engine
import (
"errors"
"fmt"
"strconv"
"strings"
"time"
"github.com/cgrates/cgrates/utils"
)
// NewBareEventCost will intialize the EventCost with minimum information
func NewBareEventCost() *EventCost {
return &EventCost{
Rating: make(Rating),
@@ -36,6 +40,7 @@ func NewBareEventCost() *EventCost {
}
}
// NewEventCostFromCallCost will initilaize the EventCost from a CallCost
func NewEventCostFromCallCost(cc *CallCost, cgrID, runID string) (ec *EventCost) {
ec = NewBareEventCost()
ec.CGRID = cgrID
@@ -169,6 +174,7 @@ func (ec *EventCost) rateIntervalForRatingID(ratingID string) (ri *RateInterval)
return
}
// Clone will create a clone of the object
func (ec *EventCost) Clone() (cln *EventCost) {
if ec == nil {
return
@@ -228,7 +234,7 @@ func (ec *EventCost) ResetCounters() {
}
}
// ComputeCost iterates through Charges, computing EventCost.Cost
// GetCost iterates through Charges, computing EventCost.Cost
func (ec *EventCost) GetCost() float64 {
if ec.Cost == nil {
var cost float64
@@ -241,7 +247,7 @@ func (ec *EventCost) GetCost() float64 {
return *ec.Cost
}
// ComputeUsage iterates through Charges, computing EventCost.Usage
// GetUsage iterates through Charges, computing EventCost.Usage
func (ec *EventCost) GetUsage() time.Duration {
if ec.Usage == nil {
var usage time.Duration
@@ -264,7 +270,7 @@ func (ec *EventCost) ComputeEventCostUsageIndexes() {
}
}
// AsCallDescriptor converts an EventCost into a CallDescriptor
// AsRefundIncrements converts an EventCost into a CallDescriptor
func (ec *EventCost) AsRefundIncrements(tor string) (cd *CallDescriptor) {
cd = &CallDescriptor{
CgrID: ec.CGRID,
@@ -463,7 +469,7 @@ func (ec *EventCost) appendCIlFromEC(oEC *EventCost, cIlIdx int) {
func (ec *EventCost) appendChargingIntervalFromEventCost(oEC *EventCost, cIlIdx int) {
lenChargers := len(ec.Charges)
if lenChargers != 0 && ec.Charges[lenChargers-1].PartiallyEquals(oEC.Charges[cIlIdx]) {
ec.Charges[lenChargers-1].CompressFactor += 1
ec.Charges[lenChargers-1].CompressFactor++
} else {
ec.appendCIlFromEC(oEC, cIlIdx)
}
@@ -793,7 +799,7 @@ func (ec *EventCost) Trim(atUsage time.Duration) (srplusEC *EventCost, err error
}
if len(srplsIncrements) != 0 { // partially covering, need trim
if lastActiveCIl.CompressFactor > 1 { // ChargingInterval not covering in full, need to split it
lastActiveCIl.CompressFactor -= 1
lastActiveCIl.CompressFactor--
ec.Charges = append(ec.Charges, lastActiveCIl.Clone())
lastActiveCIl = ec.Charges[len(ec.Charges)-1]
lastActiveCIl.CompressFactor = 1
@@ -833,3 +839,142 @@ func (ec *EventCost) Trim(atUsage time.Duration) (srplusEC *EventCost, err error
ec.RemoveStaleReferences() // data should be transferred by now, can clean the old one
return
}
// getIndex returns the path and index if index present
// path[index]=>path,index
// path=>path,nil
func getIndex(spath string) (opath string, idx *int) {
idxStart := strings.Index(spath, utils.IdxStart)
if idxStart == -1 || !strings.HasSuffix(spath, utils.IdxEnd) {
return spath, nil
}
slctr := spath[idxStart+1 : len(spath)-1]
opath = spath[:idxStart]
if strings.HasPrefix(slctr, utils.DynamicDataPrefix) {
return
}
idxVal, err := strconv.Atoi(slctr)
if err != nil {
return spath, nil
}
return opath, &idxVal
}
// FieldAsInterface func to implement DataProvider
func (ec *EventCost) FieldAsInterface(fldPath []string) (val interface{}, err error) {
if len(fldPath) == 0 {
return nil, utils.ErrNotFound
}
switch fldPath[0] {
default: //"Charges [1]"
opath, indx := getIndex(fldPath[0])
if opath != utils.Charges {
return nil, fmt.Errorf("unsupported field prefix: <%s>", opath)
}
if indx != nil {
chr := ec.Charges[*indx]
if len(fldPath) == 1 {
return chr, nil
}
if fldPath[1] == utils.Rating {
return ec.getRatingForPath(fldPath[2:], ec.Rating[chr.RatingID])
}
}
case utils.Charges: // not needed?
// return ec.Charges.FieldAsInterface(fldPath[1:])
case utils.CGRID:
if len(fldPath) != 1 {
return nil, utils.ErrNotFound
}
return ec.CGRID, nil
case utils.RunID:
if len(fldPath) != 1 {
return nil, utils.ErrNotFound
}
return ec.RunID, nil
case utils.StartTime:
if len(fldPath) != 1 {
return nil, utils.ErrNotFound
}
return ec.StartTime, nil
case utils.Usage:
if len(fldPath) != 1 {
return nil, utils.ErrNotFound
}
return ec.Usage, nil
case utils.Cost:
if len(fldPath) != 1 {
return nil, utils.ErrNotFound
}
return ec.Cost, nil
case utils.AccountSummary:
// return ec.AccountSummary.FieldAsInterface(fldPath[1:])
case utils.Timings: // not needed?
// return ec.Timings.FieldAsInterface(fldPath[1:])
case utils.Rates: // not needed?
// return ec.Rates.FieldAsInterface(fldPath[1:])
case utils.RatingFilters: // not needed?
// return ec.RatingFilters.FieldAsInterface(fldPath[1:])
case utils.Accounting: // not needed?
// return ec.Accounting.FieldAsInterface(fldPath[1:])
case utils.Rating: // not needed?
// return ec.Rating.FieldAsInterface(fldPath[1:])
}
return nil, fmt.Errorf("unsupported field prefix: <%s>", fldPath[0])
}
func (ec *EventCost) getRatingForPath(fldPath []string, rating *RatingUnit) (val interface{}, err error) {
if rating == nil {
return nil, utils.ErrNotFound
}
if len(fldPath) == 0 {
return rating, nil
}
switch fldPath[0] {
default:
opath, indx := getIndex(fldPath[0])
if opath != utils.Rates {
return nil, fmt.Errorf("unsupported field prefix: <%s>", opath)
}
rts, has := ec.Rates[rating.RatesID]
if !has || rts == nil {
return nil, utils.ErrNotFound
}
if indx != nil {
rt := rts[*indx]
if len(fldPath) == 1 {
return rt, nil
}
return rt.FieldAsInterface(fldPath[1:])
}
case utils.Rates:
rts, has := ec.Rates[rating.RatesID]
if !has || rts == nil {
return nil, utils.ErrNotFound
}
if len(fldPath) != 1 {
return nil, utils.ErrNotFound // no field on slice
}
return rts, nil
case utils.Timing:
tmg, has := ec.Timings[rating.TimingID]
if !has || tmg == nil {
return nil, utils.ErrNotFound
}
if len(fldPath) == 1 {
return tmg, nil
}
return tmg.FieldAsInterface(fldPath[1:])
case utils.RatingFilter:
rtFltr, has := ec.RatingFilters[rating.RatingFiltersID]
if !has || rtFltr == nil {
return nil, utils.ErrNotFound
}
if len(fldPath) == 1 {
return rtFltr, nil
}
return rtFltr.FieldAsInterface(fldPath[1:])
}
return rating.FieldAsInterface(fldPath)
}

View File

@@ -160,8 +160,7 @@ func (spS *SupplierService) matchingSupplierProfilesForEvent(ev *utils.CGREvent,
if singleResult {
matchingSLP = make([]*SupplierProfile, 1)
}
evNm := config.NewNavigableMap(nil)
evNm.Set([]string{utils.MetaReq}, ev.Event, false, false)
evNm := config.NewNavigableMap(map[string]interface{}{utils.MetaReq: ev.Event})
for lpID := range sPrflIDs {
splPrfl, err := spS.dm.GetSupplierProfile(ev.Tenant, lpID, true, true, utils.NonTransactional)
if err != nil {

View File

@@ -147,8 +147,8 @@ func (srvMngr *ServiceManager) GetConfig() *config.CGRConfig {
func (srvMngr *ServiceManager) StartServices() (err error) {
go srvMngr.handleReload()
for serviceName, shouldRun := range map[string]bool{
utils.APIerSv1: srvMngr.GetConfig().ApierCfg().Enabled,
utils.APIerSv2: srvMngr.GetConfig().ApierCfg().Enabled,
utils.APIerSv1: srvMngr.GetConfig().ApierCfg().Enabled,
utils.APIerSv2: srvMngr.GetConfig().ApierCfg().Enabled,
utils.StorDB: srvMngr.GetConfig().RalsCfg().Enabled || srvMngr.GetConfig().CdrsCfg().Enabled,
utils.AttributeS: srvMngr.GetConfig().AttributeSCfg().Enabled,
utils.ChargerS: srvMngr.GetConfig().ChargerSCfg().Enabled,

View File

@@ -48,6 +48,7 @@ type BiRPClient interface {
// getSessionTTL retrieves SessionTTL setting out of ev
// if SessionTTLMaxDelay is present in ev, the return is randomized
// ToDo: remove if not needed
func getSessionTTL(ev *engine.MapEvent, cfgSessionTTL time.Duration,
cfgSessionTTLMaxDelay *time.Duration) (ttl time.Duration, err error) {
if ttl, err = ev.GetDuration(utils.SessionTTL); err != nil {

View File

@@ -293,7 +293,7 @@ func (sS *SessionS) setSTerminator(s *Session) {
s.sTerminator.timer.Stop()
}
}()
time.Sleep(1) // force context switch to fix process message
time.Sleep(1) // force context switching
}
// forceSTerminate is called when a session times-out or it is forced from CGRateS side

View File

@@ -490,6 +490,13 @@ const (
Categories = "Categories"
Blocker = "Blocker"
RatingPlanID = "RatingPlanID"
StartTime = "StartTime"
AccountSummary = "AccountSummary"
RatingFilters = "RatingFilters"
RatingFilter = "RatingFilter"
Accounting = "Accounting"
Rating = "Rating"
Charges = "Charges"
MetaSessionS = "*sessions"
MetaDefault = "*default"
Error = "Error"
@@ -1181,7 +1188,7 @@ const (
APIerSv1GetAttributeProfile = "APIerSv1.GetAttributeProfile"
APIerSv1GetAttributeProfileIDs = "APIerSv1.GetAttributeProfileIDs"
APIerSv1RemoveAttributeProfile = "APIerSv1.RemoveAttributeProfile"
APIerSv2SetAttributeProfile = "APIerSv2.SetAttributeProfile"
APIerSv2SetAttributeProfile = "APIerSv2.SetAttributeProfile"
AttributeSv1GetAttributeForEvent = "AttributeSv1.GetAttributeForEvent"
AttributeSv1ProcessEvent = "AttributeSv1.ProcessEvent"
AttributeSv1Ping = "AttributeSv1.Ping"