SMGeneric with storeSMCost separately and goroutine only for large timespans

This commit is contained in:
DanB
2016-09-20 18:26:15 +02:00
parent 379f537200
commit 2c8cf6fbc0
3 changed files with 29 additions and 20 deletions

View File

@@ -29,7 +29,6 @@ type CallCost struct {
Direction, Category, Tenant, Subject, Account, Destination, TOR string
Cost float64
Timespans TimeSpans
TimespansMerged bool
RatedUsage float64
deductConnectFee bool
negativeConnectFee bool // the connect fee went negative on default balance

View File

@@ -260,20 +260,14 @@ func (tss *TimeSpans) Decompress() { // must be pointer receiver
func (tss *TimeSpans) Merge() { // Merge whenever possible
tssVal := *tss
if len(tssVal) > 2 {
middle := len(tssVal) / 2
tssVal1 := tssVal[:middle]
tssVal2 := tssVal[middle:]
tssVal1.Merge()
tssVal2.Merge()
tssVal = append(tssVal1, tssVal2 ...)
}
if len(tssVal) > 2 { // Optimization for faster merge
middle := len(tssVal) / 2
tssVal1 := tssVal[:middle]
tssVal2 := tssVal[middle:]
tssVal1.Merge()
tssVal2.Merge()
tssVal = append(tssVal1, tssVal2...)
}
for i := 1; i < len(tssVal); i++ {
if tssVal[i-1].Merge(tssVal[i]) {
tssVal = append(tssVal[:i], tssVal[i+1:]...)

View File

@@ -253,11 +253,6 @@ func (self *SMGSession) saveOperations(originID string) error {
return err
}
}
if len(cc.Timespans) > 50 { // Merge since we will get a callCost too big
cc.Timespans.Decompress()
cc.Timespans.Merge() // Here we could wait a while depending on the size of the timespans
cc.Timespans.Compress()
}
smCost := &engine.SMCost{
CGRID: self.eventStart.GetCgrId(self.timezone),
CostSource: utils.SESSION_MANAGER_SOURCE,
@@ -267,6 +262,27 @@ func (self *SMGSession) saveOperations(originID string) error {
Usage: self.TotalUsage().Seconds(),
CostDetails: cc,
}
if len(smCost.CostDetails.Timespans) > MaxTimespansInCost { // Merge since we will get a callCost too big
if err := utils.Clone(cc, &smCost.CostDetails); err != nil { // Avoid concurrency on CC
utils.Logger.Err(fmt.Sprintf("<SMGeneric> Could not clone callcost for sessionID: %s, runId: %s, error: %s", originID, self.runId, err.Error()))
}
go func(smCost *engine.SMCost) { // could take longer than the locked stage
if err := self.storeSMCost(smCost); err != nil {
utils.Logger.Err(fmt.Sprintf("<SMGeneric> Could not store callcost for sessionID: %s, runId: %s, error: %s", originID, self.runId, err.Error()))
}
}(smCost)
} else {
return self.storeSMCost(smCost)
}
return nil
}
func (self *SMGSession) storeSMCost(smCost *engine.SMCost) error {
if len(smCost.CostDetails.Timespans) > MaxTimespansInCost { // Merge so we can compress the CostDetails
smCost.CostDetails.Timespans.Decompress()
smCost.CostDetails.Timespans.Merge()
smCost.CostDetails.Timespans.Compress()
}
var reply string
if err := self.cdrsrv.Call("CdrsV1.StoreSMCost", engine.AttrCDRSStoreSMCost{Cost: smCost, CheckDuplicate: true}, &reply); err != nil {
if err == utils.ErrExists {