Added cache for EventCost.FieldAsInterface

This commit is contained in:
Trial97
2020-02-05 18:11:23 +02:00
committed by Dan Christian Bogos
parent 51d32e9a79
commit ffef415e8c
8 changed files with 63 additions and 11 deletions

View File

@@ -60,6 +60,7 @@ func NewCDRFromExternalCDR(extCdr *ExternalCDR, timezone string) (*CDR, error) {
if err = json.Unmarshal([]byte(extCdr.CostDetails), cdr.CostDetails); err != nil {
return nil, err
}
cdr.CostDetails.initCache()
}
if extCdr.ExtraFields != nil {
cdr.ExtraFields = make(map[string]string)
@@ -156,7 +157,7 @@ func (cdr *CDR) FieldAsString(rsrPrs *config.RSRParser) (parsed string, err erro
config.NewNavigableMap(map[string]interface{}{
utils.MetaReq: cdr.AsMapStringIface(),
utils.MetaEC: cdr.CostDetails,
}), utils.NestingSep)
}), utils.NestingSep)
if err != nil {
return
}
@@ -169,7 +170,7 @@ func (cdr *CDR) FieldsAsString(rsrFlds config.RSRParsers) string {
config.NewNavigableMap(map[string]interface{}{
utils.MetaReq: cdr.AsMapStringIface(),
utils.MetaEC: cdr.CostDetails,
}), utils.NestingSep)
}), utils.NestingSep)
if err != nil {
return ""
}
@@ -242,9 +243,7 @@ func (cdr *CDR) AsMapStringIface() (mp map[string]interface{}) {
mp[utils.CostSource] = cdr.CostSource
mp[utils.Cost] = cdr.Cost
if cdr.CostDetails != nil {
var result map[string]interface{}
json.Unmarshal([]byte(utils.ToJSON(cdr.CostDetails)), &result)
mp[utils.CostDetails] = result
mp[utils.CostDetails] = cdr.CostDetails
}
return
}

View File

@@ -18,7 +18,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
package engine
import (
"encoding/json"
"reflect"
"strconv"
"testing"
@@ -489,6 +488,7 @@ func TestCdrClone(t *testing.T) {
Cost: utils.Float64Pointer(0.74),
},
}
eOut.CostDetails.initCache()
if rcv := cdr.Clone(); !reflect.DeepEqual(rcv, eOut) {
t.Errorf("Expecting: %+v,\n received: %+v", eOut, rcv)
}
@@ -579,8 +579,6 @@ func TestCDRTestCDRAsMapStringIface2(t *testing.T) {
CostDetails: NewEventCostFromCallCost(cc, "TestCDRTestCDRAsMapStringIface2", utils.MetaDefault),
}
var result map[string]interface{}
json.Unmarshal([]byte(utils.ToJSON(cdr.CostDetails)), &result)
mp := map[string]interface{}{
"field_extr1": "val_extr1",
"fieldextr2": "valextr2",
@@ -605,7 +603,7 @@ func TestCDRTestCDRAsMapStringIface2(t *testing.T) {
utils.PreRated: false,
utils.Partial: false,
utils.ExtraInfo: cdr.ExtraInfo,
utils.CostDetails: result,
utils.CostDetails: cdr.CostDetails,
}
if cdrMp := cdr.AsMapStringIface(); !reflect.DeepEqual(mp, cdrMp) {
t.Errorf("Expecting: %+v, received: %+v", mp, cdrMp)

View File

@@ -37,6 +37,7 @@ func NewBareEventCost() *EventCost {
Rates: make(ChargedRates),
Timings: make(ChargedTimings),
Charges: make([]*ChargingInterval, 0),
cache: config.NewNavigableMap(nil),
}
}
@@ -117,6 +118,14 @@ type EventCost struct {
RatingFilters RatingFilters
Rates ChargedRates
Timings ChargedTimings
cache *config.NavigableMap
}
func (ec *EventCost) initCache() {
if ec != nil {
ec.cache = config.NewNavigableMap(nil)
}
}
func (ec *EventCost) ratingIDForRateInterval(ri *RateInterval, rf RatingMatchedFilters) string {
@@ -180,6 +189,7 @@ func (ec *EventCost) Clone() (cln *EventCost) {
return
}
cln = new(EventCost)
cln.initCache()
cln.CGRID = ec.CGRID
cln.RunID = ec.RunID
cln.StartTime = ec.StartTime
@@ -845,6 +855,27 @@ func (ec *EventCost) FieldAsInterface(fldPath []string) (val interface{}, err er
if len(fldPath) == 0 {
return nil, utils.ErrNotFound
}
if val, err = ec.cache.FieldAsInterface(fldPath); err != nil {
if err != utils.ErrNotFound { // item found in cache
return
}
err = nil // cancel previous err
} else if val == nil {
return nil, utils.ErrNotFound
} else {
return // data found in cache
}
val, err = ec.fieldAsInterface(fldPath)
if err == nil {
ec.cache.Set(fldPath, val, false, false)
} else if err == utils.ErrNotFound {
ec.cache.Set(fldPath, nil, false, false)
}
return
}
// FieldAsInterface the implementation of FieldAsInterface
func (ec *EventCost) fieldAsInterface(fldPath []string) (val interface{}, err error) {
switch fldPath[0] {
default: // "Charges[1]"
opath, indx := utils.GetPathIndex(fldPath[0])
@@ -888,16 +919,34 @@ func (ec *EventCost) FieldAsInterface(fldPath []string) (val interface{}, err er
}
return ec.Cost, nil
case utils.AccountSummary:
if len(fldPath) == 1 {
return ec.AccountSummary, nil
}
return ec.AccountSummary.FieldAsInterface(fldPath[1:])
case utils.Timings:
if len(fldPath) == 1 {
return ec.Timings, nil
}
return ec.Timings.FieldAsInterface(fldPath[1:])
case utils.Rates:
if len(fldPath) == 1 {
return ec.Rates, nil
}
return ec.Rates.FieldAsInterface(fldPath[1:])
case utils.RatingFilters:
if len(fldPath) == 1 {
return ec.RatingFilters, nil
}
return ec.RatingFilters.FieldAsInterface(fldPath[1:])
case utils.Accounting:
if len(fldPath) == 1 {
return ec.Accounting, nil
}
return ec.Accounting.FieldAsInterface(fldPath[1:])
case utils.Rating:
if len(fldPath) == 1 {
return ec.Rating, nil
}
return ec.Rating.FieldAsInterface(fldPath[1:])
}
return nil, fmt.Errorf("unsupported field prefix: <%s>", fldPath[0])

View File

@@ -204,6 +204,7 @@ var testEC = &EventCost{
StartTime: "00:00:00",
},
},
cache: config.NewNavigableMap(nil),
}
func TestECClone(t *testing.T) {
@@ -2514,6 +2515,7 @@ func TestECSyncKeys(t *testing.T) {
StartTime: "00:00:00",
},
},
cache: config.NewNavigableMap(nil),
}
ec.SyncKeys(refEC)

View File

@@ -1019,7 +1019,6 @@ func TestPassFilterMissingField(t *testing.T) {
}
func TestEventCostFilter(t *testing.T) {
cfg, _ := config.NewDefaultCGRConfig()
data := NewInternalDB(nil, nil, true, cfg.DataDbCfg().Items)
dmFilterPass := NewDataManager(data, config.CgrConfig().CacheCfg(), nil)
@@ -1153,7 +1152,7 @@ func TestEventCostFilter(t *testing.T) {
},
},
}
cd.initCache()
cgrDp := config.NewNavigableMap(map[string]interface{}{utils.MetaEC: cd})
if pass, err := filterS.Pass("cgrates.org",

View File

@@ -124,6 +124,7 @@ func TestResponderGobSMCost(t *testing.T) {
if err != nil {
t.Error("decode error: ", err)
}
q.Cost.CostDetails.initCache()
if !reflect.DeepEqual(attr, q) {
t.Error("wrong transmission")
}

View File

@@ -906,6 +906,7 @@ func (ms *MongoStorage) GetSMCosts(cgrid, runid, originHost, originIDPrefix stri
return err
}
clone := smCost
clone.CostDetails.initCache()
smcs = append(smcs, &clone)
}
if len(smcs) == 0 {
@@ -1165,6 +1166,7 @@ func (ms *MongoStorage) GetCDRs(qryFltr *utils.CDRsFilter, remove bool) ([]*CDR,
return err
}
clone := cdr
clone.CostDetails.initCache()
cdrs = append(cdrs, &clone)
}
if len(cdrs) == 0 {

View File

@@ -863,6 +863,7 @@ func (self *SQLStorage) GetSMCosts(cgrid, runid, originHost, originIDPrefix stri
if err := json.Unmarshal([]byte(result.CostDetails), smc.CostDetails); err != nil {
return nil, err
}
smc.CostDetails.initCache()
smCosts = append(smCosts, smc)
}
if len(smCosts) == 0 {
@@ -1158,6 +1159,7 @@ func (self *SQLStorage) GetCDRs(qryFltr *utils.CDRsFilter, remove bool) ([]*CDR,
if cdr, err := NewCDRFromSQL(result); err != nil {
return nil, 0, err
} else {
cdr.CostDetails.initCache()
cdrs = append(cdrs, cdr)
}
}