mirror of
https://github.com/cgrates/cgrates.git
synced 2026-02-11 10:06:24 +05:00
Adding TotalUsage support for update events in sessions
This commit is contained in:
@@ -19,6 +19,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
package sessions
|
||||
|
||||
import (
|
||||
"math"
|
||||
"runtime"
|
||||
"sync"
|
||||
"time"
|
||||
@@ -279,6 +280,19 @@ func (s *Session) totalUsage() (tDur time.Duration) {
|
||||
return
|
||||
}
|
||||
|
||||
// lastUsage returns the first session run last usage
|
||||
// not thread save
|
||||
func (s *Session) lastUsage() (lUsage time.Duration) {
|
||||
if len(s.SRuns) == 0 {
|
||||
return
|
||||
}
|
||||
for _, sr := range s.SRuns {
|
||||
lUsage = sr.LastUsage
|
||||
break // only first
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// AsCGREvents is a method to return the Session as CGREvents
|
||||
// AsCGREvents is not thread safe since it is supposed to run by the time Session is closed
|
||||
func (s *Session) asCGREvents() (cgrEvs []*utils.CGREvent) {
|
||||
@@ -392,3 +406,18 @@ func (s *Session) UpdateSRuns(updEv engine.MapEvent, alterableFields utils.Strin
|
||||
s.updateSRuns(updEv, alterableFields)
|
||||
s.Unlock()
|
||||
}
|
||||
|
||||
// midSessionUsage computes the midSessionUsage out of totalUsage, considering what it has been debitted so far
|
||||
// lastUsage is returned for the case when too much was debitted so it can be passed to the debit function as reserve
|
||||
func (s *Session) midSessionUsage(totalUsage time.Duration) (usage time.Duration, lastUsage *time.Duration) {
|
||||
sTUsage := s.totalUsage()
|
||||
if sTUsage == 0 {
|
||||
return totalUsage, nil
|
||||
}
|
||||
if midUsage := totalUsage - sTUsage; midUsage >= 0 {
|
||||
return midUsage, nil
|
||||
} else {
|
||||
tLastUsage := time.Duration(int(math.Abs(float64(midUsage)))) + s.lastUsage()
|
||||
return 0, &tLastUsage
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1681,10 +1681,18 @@ func (sS *SessionS) updateSession(s *Session, updtEv, opts engine.MapEvent, isMs
|
||||
if err != utils.ErrNotFound {
|
||||
return
|
||||
}
|
||||
err = nil
|
||||
reqMaxUsage = sS.cgrCfg.SessionSCfg().GetDefaultUsage(updtEv.GetStringIgnoreErrors(utils.ToR))
|
||||
updtEv[utils.Usage] = reqMaxUsage
|
||||
}
|
||||
lastUsed := updtEv.GetDurationPtrIgnoreErrors(utils.LastUsed)
|
||||
var totalUsage time.Duration
|
||||
if totalUsage, err = updtEv.GetDuration(utils.TotalUsage); err != nil && err != utils.ErrNotFound {
|
||||
return
|
||||
} else {
|
||||
reqMaxUsage, lastUsed = s.midSessionUsage(totalUsage)
|
||||
}
|
||||
err = nil
|
||||
|
||||
maxUsage = make(map[string]time.Duration)
|
||||
for i, sr := range s.SRuns {
|
||||
reqType := sr.Event.GetStringIgnoreErrors(utils.RequestType)
|
||||
@@ -1692,8 +1700,8 @@ func (sS *SessionS) updateSession(s *Session, updtEv, opts engine.MapEvent, isMs
|
||||
switch reqType {
|
||||
case utils.MetaPrepaid, utils.MetaDynaprepaid:
|
||||
if s.debitStop == nil {
|
||||
if rplyMaxUsage, err = sS.debitSession(s, i, reqMaxUsage,
|
||||
updtEv.GetDurationPtrIgnoreErrors(utils.LastUsed)); err != nil {
|
||||
if rplyMaxUsage, err = sS.debitSession(s, i,
|
||||
reqMaxUsage, lastUsed); err != nil {
|
||||
return
|
||||
}
|
||||
break
|
||||
|
||||
@@ -782,6 +782,167 @@ func testSessionsVoiceLastUsedNotFixed(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func testSessionsVoiceTotalUsed(t *testing.T) {
|
||||
var acnt *engine.Account
|
||||
attrs := &utils.AttrGetAccount{Tenant: "cgrates.org", Account: "1001"}
|
||||
eAcntVal := 8.790000
|
||||
if err := sessionsRPC.Call(context.Background(), utils.APIerSv2GetAccount, attrs, &acnt); err != nil {
|
||||
t.Error(err)
|
||||
} else if acnt.BalanceMap[utils.MetaMonetary].GetTotalValue() != eAcntVal {
|
||||
t.Errorf("Expected: %f, received: %f", eAcntVal, acnt.BalanceMap[utils.MetaMonetary].GetTotalValue())
|
||||
}
|
||||
|
||||
usage := 2 * time.Minute
|
||||
initArgs := &V1InitSessionArgs{
|
||||
InitSession: true,
|
||||
CGREvent: &utils.CGREvent{
|
||||
Tenant: "cgrates.org",
|
||||
ID: "TestSessionsVoiceLastUsed",
|
||||
Event: map[string]any{
|
||||
utils.EventName: "TEST_EVENT",
|
||||
utils.ToR: utils.MetaVoice,
|
||||
utils.OriginID: "12350",
|
||||
utils.AccountField: "1001",
|
||||
utils.Subject: "1001",
|
||||
utils.Destination: "1006",
|
||||
utils.Category: "call",
|
||||
utils.Tenant: "cgrates.org",
|
||||
utils.RequestType: utils.MetaPrepaid,
|
||||
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,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
var initRpl *V1InitSessionReply
|
||||
if err := sessionsRPC.Call(context.Background(), utils.SessionSv1InitiateSession,
|
||||
initArgs, &initRpl); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
if initRpl.MaxUsage == nil || *initRpl.MaxUsage != usage {
|
||||
t.Errorf("Expecting : %+v, received: %+v", usage, initRpl.MaxUsage)
|
||||
}
|
||||
|
||||
eAcntVal = 7.39002
|
||||
if err := sessionsRPC.Call(context.Background(), utils.APIerSv2GetAccount, attrs, &acnt); err != nil {
|
||||
t.Error(err)
|
||||
} else if acnt.BalanceMap[utils.MetaMonetary].GetTotalValue() != eAcntVal {
|
||||
t.Errorf("Expected: %f, received: %f", eAcntVal, acnt.BalanceMap[utils.MetaMonetary].GetTotalValue())
|
||||
}
|
||||
|
||||
lastUsage := time.Minute + 30*time.Second
|
||||
updateArgs := &V1UpdateSessionArgs{
|
||||
UpdateSession: true,
|
||||
CGREvent: &utils.CGREvent{
|
||||
Tenant: "cgrates.org",
|
||||
ID: "TestSessionsVoiceLastUsed",
|
||||
Event: map[string]any{
|
||||
utils.EventName: "Update1",
|
||||
utils.ToR: utils.MetaVoice,
|
||||
utils.OriginID: "12350",
|
||||
utils.AccountField: "1001",
|
||||
utils.Subject: "1001",
|
||||
utils.Destination: "1006",
|
||||
utils.Category: "call",
|
||||
utils.Tenant: "cgrates.org",
|
||||
utils.RequestType: utils.MetaPrepaid,
|
||||
utils.Usage: usage,
|
||||
utils.LastUsed: lastUsage,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
var updateRpl *V1UpdateSessionReply
|
||||
if err := sessionsRPC.Call(context.Background(), utils.SessionSv1UpdateSession, updateArgs, &updateRpl); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
if updateRpl.MaxUsage == nil || *updateRpl.MaxUsage != usage {
|
||||
t.Errorf("Expected: %+v, received: %+v", usage, updateRpl.MaxUsage)
|
||||
}
|
||||
|
||||
eAcntVal = 7.09005
|
||||
if err := sessionsRPC.Call(context.Background(), utils.APIerSv2GetAccount, attrs, &acnt); err != nil {
|
||||
t.Error(err)
|
||||
} else if acnt.BalanceMap[utils.MetaMonetary].GetTotalValue() != eAcntVal {
|
||||
t.Errorf("Expected: %f, received: %f", eAcntVal, acnt.BalanceMap[utils.MetaMonetary].GetTotalValue())
|
||||
}
|
||||
|
||||
lastUsage = 2*time.Minute + 30*time.Second
|
||||
updateArgs = &V1UpdateSessionArgs{
|
||||
UpdateSession: true,
|
||||
CGREvent: &utils.CGREvent{
|
||||
Tenant: "cgrates.org",
|
||||
ID: "TestSessionsVoiceLastUsed",
|
||||
Event: map[string]any{
|
||||
utils.EventName: "Update2",
|
||||
utils.ToR: utils.MetaVoice,
|
||||
utils.OriginID: "12350",
|
||||
utils.AccountField: "1001",
|
||||
utils.Subject: "1001",
|
||||
utils.Destination: "1006",
|
||||
utils.Category: "call",
|
||||
utils.Tenant: "cgrates.org",
|
||||
utils.RequestType: utils.MetaPrepaid,
|
||||
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.LastUsed: lastUsage,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
if err := sessionsRPC.Call(context.Background(), utils.SessionSv1UpdateSession, updateArgs, &updateRpl); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
if updateRpl.MaxUsage == nil || *updateRpl.MaxUsage != usage {
|
||||
t.Errorf("Expected: %+v, received: %+v", usage, updateRpl.MaxUsage)
|
||||
}
|
||||
|
||||
eAcntVal = 6.590100
|
||||
if err := sessionsRPC.Call(context.Background(), utils.APIerSv2GetAccount, attrs, &acnt); err != nil {
|
||||
t.Error(err)
|
||||
} else if acnt.BalanceMap[utils.MetaMonetary].GetTotalValue() != eAcntVal {
|
||||
t.Errorf("Expected: %f, received: %f", eAcntVal, acnt.BalanceMap[utils.MetaMonetary].GetTotalValue())
|
||||
}
|
||||
|
||||
usage = time.Minute
|
||||
termArgs := &V1TerminateSessionArgs{
|
||||
TerminateSession: true,
|
||||
CGREvent: &utils.CGREvent{
|
||||
Tenant: "cgrates.org",
|
||||
ID: "TestSessionsVoiceLastUsed",
|
||||
Event: map[string]any{
|
||||
utils.EventName: "TEST_EVENT",
|
||||
utils.ToR: utils.MetaVoice,
|
||||
utils.OriginID: "12350",
|
||||
utils.AccountField: "1001",
|
||||
utils.Subject: "1001",
|
||||
utils.Destination: "1006",
|
||||
utils.Category: "call",
|
||||
utils.Tenant: "cgrates.org",
|
||||
utils.RequestType: utils.MetaPrepaid,
|
||||
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,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
var rpl string
|
||||
if err := sessionsRPC.Call(context.Background(), utils.SessionSv1TerminateSession, termArgs, &rpl); err != nil || rpl != utils.OK {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
eAcntVal = 7.59
|
||||
if err := sessionsRPC.Call(context.Background(), utils.APIerSv2GetAccount, attrs, &acnt); err != nil {
|
||||
t.Error(err)
|
||||
} else if acnt.BalanceMap[utils.MetaMonetary].GetTotalValue() != eAcntVal {
|
||||
t.Errorf("Expected: %f, received: %f",
|
||||
eAcntVal, acnt.BalanceMap[utils.MetaMonetary].GetTotalValue())
|
||||
}
|
||||
}
|
||||
|
||||
func testSessionsVoiceSessionTTL(t *testing.T) {
|
||||
var acnt *engine.Account
|
||||
attrs := &utils.AttrGetAccount{Tenant: "cgrates.org", Account: "1001"}
|
||||
|
||||
Reference in New Issue
Block a user