mirror of
https://github.com/cgrates/cgrates.git
synced 2026-02-11 18:16:24 +05:00
SMGeneric with storeSMCost separately and goroutine only for large timespans
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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:]...)
|
||||
|
||||
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user