From f0ba9a093d8bbe9d9a585e2bb04c077289c24750 Mon Sep 17 00:00:00 2001 From: TeoV Date: Wed, 17 Jun 2020 11:14:07 +0300 Subject: [PATCH] Use correctly SessionTTLUsage when calculate end usage in case of terminate session from ttl mechanism --- engine/rateprofile.go | 3 +-- packages/debian/changelog | 1 + sessions/sessions.go | 22 +++++++++------------- sessions/sessions_data_it_test.go | 30 ++++++++++++++++++++++++++++-- 4 files changed, 39 insertions(+), 17 deletions(-) diff --git a/engine/rateprofile.go b/engine/rateprofile.go index bc0c82985..38ca71ce1 100644 --- a/engine/rateprofile.go +++ b/engine/rateprofile.go @@ -60,8 +60,7 @@ type Rate struct { Increment time.Duration // RateIncrement Blocker bool // RateBlocker will make this rate recurrent, deactivating further intervals - val *utils.Decimal // cached version of the Decimal - grpItvl *time.Duration // populated from IntervalStart if duration is provided + val *utils.Decimal // cached version of the Decimal } // RateProfileWithArgDispatcher is used in replicatorV1 for dispatcher diff --git a/packages/debian/changelog b/packages/debian/changelog index 40e505e2c..436965f18 100644 --- a/packages/debian/changelog +++ b/packages/debian/changelog @@ -68,6 +68,7 @@ cgrates (0.11.0~dev) UNRELEASED; urgency=medium * [ERs] Renamed *default reader folders * [FilterS] Updated Filter indexes * [General] Added *mo+extraDuration time support (e.g. *mo+1h will be time.Now() + 1 month + 1 hour) + * [SessionS] Use correctly SessionTTLUsage when calculate end usage in case of terminate session from ttl mechanism -- DanB Wed, 19 Feb 2020 13:25:52 +0200 diff --git a/sessions/sessions.go b/sessions/sessions.go index 646a7bd52..08bd8a41e 100644 --- a/sessions/sessions.go +++ b/sessions/sessions.go @@ -301,11 +301,7 @@ func (sS *SessionS) setSTerminator(s *Session, opts engine.MapEvent) { go func() { select { case <-s.sTerminator.timer.C: - endUsage := s.sTerminator.ttl - if s.sTerminator.ttlUsage != nil { - endUsage = *s.sTerminator.ttlUsage - } - sS.forceSTerminate(s, endUsage, + sS.forceSTerminate(s, s.sTerminator.ttl, s.sTerminator.ttlUsage, s.sTerminator.ttlLastUsed) case <-s.sTerminator.endChan: s.sTerminator.timer.Stop() @@ -316,10 +312,10 @@ func (sS *SessionS) setSTerminator(s *Session, opts engine.MapEvent) { // forceSTerminate is called when a session times-out or it is forced from CGRateS side // not thread safe -func (sS *SessionS) forceSTerminate(s *Session, extraDebit time.Duration, lastUsed *time.Duration) (err error) { - if extraDebit != 0 { +func (sS *SessionS) forceSTerminate(s *Session, extraUsage time.Duration, tUsage, lastUsed *time.Duration) (err error) { + if extraUsage != 0 { for i := range s.SRuns { - if _, err = sS.debitSession(s, i, extraDebit, lastUsed); err != nil { + if _, err = sS.debitSession(s, i, extraUsage, lastUsed); err != nil { utils.Logger.Warning( fmt.Sprintf( "<%s> failed debitting cgrID %s, sRunIdx: %d, err: %s", @@ -328,7 +324,7 @@ func (sS *SessionS) forceSTerminate(s *Session, extraDebit time.Duration, lastUs } } // we apply the correction before - if err = sS.endSession(s, nil, nil, nil, false); err != nil { + if err = sS.endSession(s, tUsage, lastUsed, nil, false); err != nil { utils.Logger.Warning( fmt.Sprintf( "<%s> failed force terminating session with ID <%s>, err: <%s>", @@ -517,7 +513,7 @@ func (sS *SessionS) debitLoopSession(s *Session, sRunIdx int, fmt.Sprintf("<%s> could not disconnect session: %s, error: %s", utils.SessionS, s.cgrID(), err.Error())) } - if err = sS.forceSTerminate(s, 0, nil); err != nil { + if err = sS.forceSTerminate(s, 0, nil, nil); err != nil { utils.Logger.Warning(fmt.Sprintf("<%s> failed force-terminating session: <%s>, err: <%s>", utils.SessionS, s.cgrID(), err)) } s.Unlock() @@ -551,7 +547,7 @@ func (sS *SessionS) debitLoopSession(s *Session, sRunIdx int, utils.Logger.Warning( fmt.Sprintf("<%s> could not disconnect session: <%s>, error: <%s>", utils.SessionS, s.cgrID(), err.Error())) - if err = sS.forceSTerminate(s, 0, nil); err != nil { + if err = sS.forceSTerminate(s, 0, nil, nil); err != nil { utils.Logger.Warning(fmt.Sprintf("<%s> failed force-terminating session: <%s>, err: <%s>", utils.SessionS, s.cgrID(), err)) } @@ -1312,7 +1308,7 @@ func (sS *SessionS) syncSessions() { if len(ss) == 0 { continue } - if err := sS.forceSTerminate(ss[0], 0, nil); err != nil { + if err := sS.forceSTerminate(ss[0], 0, nil, nil); err != nil { utils.Logger.Warning( fmt.Sprintf("<%s> failed force-terminating session: <%s>, err: <%s>", utils.SessionS, cgrID, err.Error())) @@ -3587,7 +3583,7 @@ func (sS *SessionS) BiRPCv1ForceDisconnect(clnt rpcclient.ClientConnector, if len(ss) == 0 { continue } - if errTerm := sS.forceSTerminate(ss[0], 0, nil); errTerm != nil { + if errTerm := sS.forceSTerminate(ss[0], 0, nil, nil); errTerm != nil { utils.Logger.Warning( fmt.Sprintf( "<%s> failed force-terminating session with id: <%s>, err: <%s>", diff --git a/sessions/sessions_data_it_test.go b/sessions/sessions_data_it_test.go index 0f4eb1939..e75c12be2 100644 --- a/sessions/sessions_data_it_test.go +++ b/sessions/sessions_data_it_test.go @@ -608,12 +608,25 @@ func testSessionsDataTTLExpired(t *testing.T) { } time.Sleep(70 * time.Millisecond) - eAcntVal = 99328.000000 + eAcntVal = 100352.000000 if err := sDataRPC.Call(utils.APIerSv2GetAccount, acntAttrs, &acnt); err != nil { t.Error(err) } else if dataVal := acnt.BalanceMap[utils.DATA].GetTotalValue(); dataVal != eAcntVal { t.Errorf("Expected: %f, received: %f", eAcntVal, dataVal) } + + // verify the cdr usage SessionTTLUsage ( 2048) + var cdrs []*engine.ExternalCDR + req := utils.RPCCDRsFilter{Accounts: []string{acntAttrs.Account}} + if err := sDataRPC.Call(utils.APIerSv2GetCDRs, &req, &cdrs); err != nil { + t.Error("Unexpected error: ", err.Error()) + } else if len(cdrs) != 1 { + t.Error("Unexpected number of CDRs returned: ", len(cdrs)) + } else { + if cdrs[0].Usage != "2048" { + t.Errorf("Unexpected CDR Usage received, cdr: %v %+v ", cdrs[0].Usage, cdrs[0]) + } + } } func testSessionsDataTTLExpMultiUpdates(t *testing.T) { @@ -735,7 +748,7 @@ func testSessionsDataTTLExpMultiUpdates(t *testing.T) { } time.Sleep(60 * time.Millisecond) // TTL will kick in - eAcntVal = 98304.000000 // 1MB is returned + eAcntVal = 100352.000000 // initial balance ( 102400 ) - SessionTTLUsage from update ( 2048 ) if err := sDataRPC.Call(utils.APIerSv2GetAccount, acntAttrs, &acnt); err != nil { t.Error(err) } else if dataVal := acnt.BalanceMap[utils.DATA].GetTotalValue(); dataVal != eAcntVal { @@ -745,6 +758,19 @@ func testSessionsDataTTLExpMultiUpdates(t *testing.T) { new(utils.SessionFilter), &aSessions); err == nil || err.Error() != utils.ErrNotFound.Error() { t.Error(err, aSessions) } + + // verify the cdr usage SessionTTLUsage ( 2048) + var cdrs []*engine.ExternalCDR + req := utils.RPCCDRsFilter{Accounts: []string{acntAttrs.Account}} + if err := sDataRPC.Call(utils.APIerSv2GetCDRs, &req, &cdrs); err != nil { + t.Error("Unexpected error: ", err.Error()) + } else if len(cdrs) != 1 { + t.Error("Unexpected number of CDRs returned: ", len(cdrs)) + } else { + if cdrs[0].Usage != "2048" { + t.Errorf("Unexpected CDR Usage received, cdr: %v %+v ", cdrs[0].Usage, cdrs[0]) + } + } } func testSessionsDataMultipleDataNoUsage(t *testing.T) {