SessionS - properly charge terminate without initiate event

This commit is contained in:
Trial97
2020-12-07 15:49:28 +02:00
committed by Dan Christian Bogos
parent 29d5e5d2b9
commit 19f30a418d
3 changed files with 46 additions and 38 deletions

View File

@@ -56,7 +56,8 @@ cgrates (0.10.1) UNRELEASED; urgency=medium
* [SessionS] Use correctly SessionTTLUsage when calculate end usage in case of terminate session from ttl mechanism
* [SessionS] Add SessionTLLLastUsage as option for an extra debit in case of ttl mechanism
* [Templates] Added new dataconverter: *string2hex
* [SessionS] Properly charge terminate without initiate event
-- DanB <danb@cgrates.org> Wed, 5 May 2020 15:22:59 +0200
cgrates (0.10.0) UNRELEASED; urgency=medium

View File

@@ -1420,17 +1420,17 @@ func (sS *SessionS) updateSession(s *Session, updtEv engine.MapEvent, isMsg, for
}
var maxUsageSet bool // so we know if we have set the 0 on purpose
for i, sr := range s.SRuns {
reqType := sr.Event.GetStringIgnoreErrors(utils.RequestType)
if reqType == utils.META_NONE {
continue
}
var rplyMaxUsage time.Duration
if !authReqs.HasField(
sr.Event.GetStringIgnoreErrors(utils.RequestType)) {
if reqType != utils.META_PREPAID || s.debitStop != nil {
rplyMaxUsage = reqMaxUsage
} else if rplyMaxUsage, err = sS.debitSession(s, i, reqMaxUsage,
updtEv.GetDurationPtrIgnoreErrors(utils.LastUsed)); err != nil {
return
}
if rplyMaxUsage > reqMaxUsage {
rplyMaxUsage = reqMaxUsage
}
if !maxUsageSet || rplyMaxUsage < maxUsage {
maxUsage = rplyMaxUsage
maxUsageSet = true
@@ -1472,35 +1472,37 @@ func (sS *SessionS) endSession(s *Session, tUsage, lastUsage *time.Duration,
sUsage = sr.TotalUsage
}
if sr.EventCost != nil {
if notCharged := sUsage - sr.EventCost.GetUsage(); notCharged > 0 { // we did not charge enough, make a manual debit here
if sr.CD.LoopIndex > 0 {
sr.CD.TimeStart = sr.CD.TimeEnd
if !isMsg { // in case of one time charge there is no need of corrections
if notCharged := sUsage - sr.EventCost.GetUsage(); notCharged > 0 { // we did not charge enough, make a manual debit here
if sr.CD.LoopIndex > 0 {
sr.CD.TimeStart = sr.CD.TimeEnd
}
sr.CD.TimeEnd = sr.CD.TimeStart.Add(notCharged)
sr.CD.DurationIndex += notCharged
cc := new(engine.CallCost)
if err = sS.connMgr.Call(sS.cgrCfg.SessionSCfg().RALsConns, nil, utils.ResponderDebit,
&engine.CallDescriptorWithArgDispatcher{
CallDescriptor: sr.CD,
ArgDispatcher: s.ArgDispatcher}, cc); err == nil {
sr.EventCost.Merge(
engine.NewEventCostFromCallCost(cc, s.CGRID,
sr.Event.GetStringIgnoreErrors(utils.RunID)))
}
} else if notCharged < 0 { // charged too much, try refund
if err = sS.refundSession(s, sRunIdx, -notCharged); err != nil {
utils.Logger.Warning(
fmt.Sprintf(
"<%s> failed refunding session: <%s>, srIdx: <%d>, error: <%s>",
utils.SessionS, s.CGRID, sRunIdx, err.Error()))
}
}
sr.CD.TimeEnd = sr.CD.TimeStart.Add(notCharged)
sr.CD.DurationIndex += notCharged
cc := new(engine.CallCost)
if err = sS.connMgr.Call(sS.cgrCfg.SessionSCfg().RALsConns, nil, utils.ResponderDebit,
&engine.CallDescriptorWithArgDispatcher{
CallDescriptor: sr.CD,
ArgDispatcher: s.ArgDispatcher}, cc); err == nil {
sr.EventCost.Merge(
engine.NewEventCostFromCallCost(cc, s.CGRID,
sr.Event.GetStringIgnoreErrors(utils.RunID)))
}
} else if notCharged < 0 { // charged too much, try refund
if err = sS.refundSession(s, sRunIdx, -notCharged); err != nil {
if err := sS.roundCost(s, sRunIdx); err != nil { // will round the cost and refund the extra increment
utils.Logger.Warning(
fmt.Sprintf(
"<%s> failed refunding session: <%s>, srIdx: <%d>, error: <%s>",
fmt.Sprintf("<%s> failed rounding session cost for <%s>, srIdx: <%d>, error: <%s>",
utils.SessionS, s.CGRID, sRunIdx, err.Error()))
}
}
if err := sS.roundCost(s, sRunIdx); err != nil { // will round the cost and refund the extra increment
utils.Logger.Warning(
fmt.Sprintf("<%s> failed rounding session cost for <%s>, srIdx: <%d>, error: <%s>",
utils.SessionS, s.CGRID, sRunIdx, err.Error()))
}
}
if sS.cgrCfg.SessionSCfg().StoreSCosts {
if err := sS.storeSCost(s, sRunIdx); err != nil {
utils.Logger.Warning(
@@ -1508,7 +1510,6 @@ func (sS *SessionS) endSession(s *Session, tUsage, lastUsage *time.Duration,
utils.SessionS, s.CGRID, sRunIdx, err.Error()))
}
}
// set cost fields
sr.Event[utils.Cost] = sr.EventCost.GetCost()
sr.Event[utils.CostDetails] = utils.ToJSON(sr.EventCost) // avoid map[string]interface{} when decoding
@@ -2538,6 +2539,7 @@ func (sS *SessionS) BiRPCv1TerminateSession(clnt rpcclient.ClientConnector,
}
var s *Session
fib := utils.Fib()
var isMsg bool // one time charging, do not perform indexing and sTerminator
for i := 0; i < sS.cgrCfg.SessionSCfg().TerminateAttempts; i++ {
if s = sS.getRelocateSession(cgrID,
ev.GetStringIgnoreErrors(utils.InitialOriginID),
@@ -2549,21 +2551,26 @@ func (sS *SessionS) BiRPCv1TerminateSession(clnt rpcclient.ClientConnector,
time.Sleep(time.Duration(fib()) * time.Millisecond)
continue
}
isMsg = true
if s, err = sS.initSession(args.CGREvent.Tenant,
ev, sS.biJClntID(clnt),
ev.GetStringIgnoreErrors(utils.OriginID), dbtItvl,
args.ArgDispatcher, false, args.ForceDuration); err != nil {
args.ArgDispatcher, isMsg, args.ForceDuration); err != nil {
return utils.NewErrRALs(err)
}
if _, err = sS.updateSession(s, ev, isMsg, args.ForceDuration); err != nil {
return err
}
break
}
if !isMsg {
s.UpdateSRuns(ev, sS.cgrCfg.SessionSCfg().AlterableFields)
}
s.UpdateSRuns(ev, sS.cgrCfg.SessionSCfg().AlterableFields)
if err = sS.terminateSession(s,
ev.GetDurationPtrIgnoreErrors(utils.Usage),
ev.GetDurationPtrIgnoreErrors(utils.LastUsed),
ev.GetTimePtrIgnoreErrors(utils.AnswerTime, utils.EmptyString),
false); err != nil {
isMsg); err != nil {
return utils.NewErrRALs(err)
}
}

View File

@@ -227,7 +227,7 @@ func testSessionsItUpdateUnexist(t *testing.T) {
utils.SetupTime: time.Date(2016, time.January, 5, 18, 30, 49, 0, time.UTC),
utils.AnswerTime: time.Date(2016, time.January, 5, 18, 31, 05, 0, time.UTC),
utils.Usage: usage,
utils.CGRDebitInterval: "10s",
utils.CGRDebitInterval: "0s",
},
},
}
@@ -242,7 +242,7 @@ func testSessionsItUpdateUnexist(t *testing.T) {
time.Sleep(10 * time.Millisecond)
eAcntVal = 8.582900
eAcntVal = 8.599600
if err := sItRPC.Call(utils.APIerSv2GetAccount, attrs, &acnt); err != nil {
t.Error(err)
} else if acnt.BalanceMap[utils.MONETARY].GetTotalValue() != eAcntVal {