mirror of
https://github.com/cgrates/cgrates.git
synced 2026-02-11 18:16:24 +05:00
SMG handling of subsessions, fix for usage, added *data balance to tutorial files
This commit is contained in:
@@ -798,10 +798,10 @@ func TestDmtAgentSendDataGrpUpdate(t *testing.T) {
|
||||
AVP: []*diam.AVP{
|
||||
diam.NewAVP(446, avp.Mbit, 0, &diam.GroupedAVP{ // Used-Service-Unit
|
||||
AVP: []*diam.AVP{
|
||||
diam.NewAVP(452, avp.Mbit, 0, datatype.Enumerated(0)), // Tariff-Change-Usage
|
||||
diam.NewAVP(420, avp.Mbit, 0, datatype.Unsigned32(20)), // CC-Time
|
||||
diam.NewAVP(412, avp.Mbit, 0, datatype.Unsigned64(1)), // CC-Input-Octets
|
||||
diam.NewAVP(414, avp.Mbit, 0, datatype.Unsigned64(2)), // CC-Output-Octets
|
||||
diam.NewAVP(452, avp.Mbit, 0, datatype.Enumerated(0)), // Tariff-Change-Usage
|
||||
diam.NewAVP(420, avp.Mbit, 0, datatype.Unsigned32(20)), // CC-Time
|
||||
diam.NewAVP(412, avp.Mbit, 0, datatype.Unsigned64(1000)), // CC-Input-Octets
|
||||
diam.NewAVP(414, avp.Mbit, 0, datatype.Unsigned64(24)), // CC-Output-Octets
|
||||
},
|
||||
}),
|
||||
diam.NewAVP(432, avp.Mbit, 0, datatype.Unsigned32(1)), // Data session for group 1
|
||||
@@ -811,10 +811,10 @@ func TestDmtAgentSendDataGrpUpdate(t *testing.T) {
|
||||
AVP: []*diam.AVP{
|
||||
diam.NewAVP(446, avp.Mbit, 0, &diam.GroupedAVP{ // Used-Service-Unit
|
||||
AVP: []*diam.AVP{
|
||||
diam.NewAVP(452, avp.Mbit, 0, datatype.Enumerated(0)), // Tariff-Change-Usage
|
||||
diam.NewAVP(420, avp.Mbit, 0, datatype.Unsigned32(20)), // CC-Time
|
||||
diam.NewAVP(412, avp.Mbit, 0, datatype.Unsigned64(1)), // CC-Input-Octets
|
||||
diam.NewAVP(414, avp.Mbit, 0, datatype.Unsigned64(1)), // CC-Output-Octets
|
||||
diam.NewAVP(452, avp.Mbit, 0, datatype.Enumerated(0)), // Tariff-Change-Usage
|
||||
diam.NewAVP(420, avp.Mbit, 0, datatype.Unsigned32(20)), // CC-Time
|
||||
diam.NewAVP(412, avp.Mbit, 0, datatype.Unsigned64(1024)), // CC-Input-Octets
|
||||
diam.NewAVP(414, avp.Mbit, 0, datatype.Unsigned64(512)), // CC-Output-Octets
|
||||
},
|
||||
}),
|
||||
diam.NewAVP(432, avp.Mbit, 0, datatype.Unsigned32(2)), // Data session for group 2
|
||||
@@ -892,10 +892,10 @@ func TestDmtAgentSendDataGrpTerminate(t *testing.T) {
|
||||
AVP: []*diam.AVP{
|
||||
diam.NewAVP(446, avp.Mbit, 0, &diam.GroupedAVP{ // Used-Service-Unit
|
||||
AVP: []*diam.AVP{
|
||||
diam.NewAVP(452, avp.Mbit, 0, datatype.Enumerated(0)), // Tariff-Change-Usage
|
||||
diam.NewAVP(420, avp.Mbit, 0, datatype.Unsigned32(20)), // CC-Time
|
||||
diam.NewAVP(412, avp.Mbit, 0, datatype.Unsigned64(1)), // CC-Input-Octets
|
||||
diam.NewAVP(414, avp.Mbit, 0, datatype.Unsigned64(2)), // CC-Output-Octets
|
||||
diam.NewAVP(452, avp.Mbit, 0, datatype.Enumerated(0)), // Tariff-Change-Usage
|
||||
diam.NewAVP(420, avp.Mbit, 0, datatype.Unsigned32(20)), // CC-Time
|
||||
diam.NewAVP(412, avp.Mbit, 0, datatype.Unsigned64(512)), // CC-Input-Octets
|
||||
diam.NewAVP(414, avp.Mbit, 0, datatype.Unsigned64(0)), // CC-Output-Octets
|
||||
},
|
||||
}),
|
||||
},
|
||||
|
||||
@@ -116,7 +116,7 @@ func TestSMGV1CacheStats(t *testing.T) {
|
||||
}
|
||||
var rcvStats *utils.CacheStats
|
||||
|
||||
expectedStats := &utils.CacheStats{Destinations: 4, RatingPlans: 4, RatingProfiles: 9, Actions: 7, ActionPlans: 4, SharedGroups: 1, Aliases: 1,
|
||||
expectedStats := &utils.CacheStats{Destinations: 4, RatingPlans: 4, RatingProfiles: 9, Actions: 8, ActionPlans: 4, SharedGroups: 1, Aliases: 1,
|
||||
DerivedChargers: 1, LcrProfiles: 5, CdrStats: 6, Users: 3, LastLoadId: smgV1LoadInst.LoadId, LastLoadTime: smgV1LoadInst.LoadTime.Format(time.RFC3339)}
|
||||
var args utils.AttrCacheStats
|
||||
if err := smgV1Rpc.Call("ApierV2.GetCacheStats", args, &rcvStats); err != nil {
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
{"tag": "Destination", "field_id": "Destination", "type": "*constant", "value": "data"},
|
||||
{"tag": "SetupTime", "field_id": "SetupTime", "type": "*composed", "value": "Event-Timestamp", "mandatory": true},
|
||||
{"tag": "AnswerTime", "field_id": "AnswerTime", "type": "*composed", "value": "Event-Timestamp", "mandatory": true},
|
||||
{"tag": "Usage", "field_id": "Usage", "type": "*constant", "value": "3"},
|
||||
{"tag": "Usage", "field_id": "Usage", "type": "*constant", "value": "2048"},
|
||||
],
|
||||
"cca_fields": [
|
||||
{"tag": "ResultCode", "field_id": "Result-Code", "type": "*constant", "value": "^2001"},
|
||||
@@ -44,7 +44,7 @@
|
||||
{"tag": "Destination", "field_id": "Destination", "type": "*constant", "value": "data"},
|
||||
{"tag": "SetupTime", "field_id": "SetupTime", "type": "*composed", "value": "Event-Timestamp", "mandatory": true},
|
||||
{"tag": "AnswerTime", "field_id": "AnswerTime", "type": "*composed", "value": "Event-Timestamp", "mandatory": true},
|
||||
{"tag": "Usage", "field_id": "Usage", "type": "*constant", "value": "3"},
|
||||
{"tag": "Usage", "field_id": "Usage", "type": "*constant", "value": "2048"},
|
||||
{"tag": "LastUsed", "field_id": "LastUsed", "field_filter":"Multiple-Services-Credit-Control>Rating-Group(1)", "type": "*handler", "handler_id": "*sum",
|
||||
"value": "Multiple-Services-Credit-Control>Used-Service-Unit>CC-Input-Octets;^|;Multiple-Services-Credit-Control>Used-Service-Unit>CC-Output-Octets"},
|
||||
],
|
||||
@@ -71,7 +71,7 @@
|
||||
{"tag": "Destination", "field_id": "Destination", "type": "*constant", "value": "data"},
|
||||
{"tag": "SetupTime", "field_id": "SetupTime", "type": "*composed", "value": "Event-Timestamp", "mandatory": true},
|
||||
{"tag": "AnswerTime", "field_id": "AnswerTime", "type": "*composed", "value": "Event-Timestamp", "mandatory": true},
|
||||
{"tag": "Usage", "field_id": "Usage", "type": "*constant", "value": "3"},
|
||||
{"tag": "Usage", "field_id": "Usage", "type": "*constant", "value": "2048"},
|
||||
{"tag": "LastUsed", "field_id": "LastUsed", "field_filter":"Multiple-Services-Credit-Control>Rating-Group(2)", "type": "*handler", "handler_id": "*sum",
|
||||
"value": "Multiple-Services-Credit-Control>Used-Service-Unit>CC-Input-Octets;^|;Multiple-Services-Credit-Control>Used-Service-Unit>CC-Output-Octets"},
|
||||
],
|
||||
|
||||
@@ -6,3 +6,4 @@ USE_SHARED_A,SHARED_A_0,*asap,10
|
||||
PACKAGE_1001,TOPUP_RST_5,*asap,10
|
||||
PACKAGE_1001,TOPUP_RST_SHARED_5,*asap,10
|
||||
PACKAGE_1001,TOPUP_120_DST1003,*asap,10
|
||||
PACKAGE_1001,TOPUP_RST_DATA_100,*asap,10
|
||||
|
||||
|
@@ -5,6 +5,7 @@ TOPUP_RST_5,*topup_reset,,,,*voice,*out,,DST_1002,SPECIAL_1002,,*unlimited,,90,2
|
||||
TOPUP_120_DST1003,*topup_reset,,,,*voice,*out,,DST_1003,,,*unlimited,,120,20,false,false,10
|
||||
TOPUP_RST_SHARED_5,*topup,,,,*monetary,*out,,*any,,SHARED_A,*unlimited,,5,10,false,false,10
|
||||
SHARED_A_0,*topup_reset,,,,*monetary,*out,,*any,,SHARED_A,*unlimited,,0,10,false,false,10
|
||||
TOPUP_RST_DATA_100,*topup_reset,,,,*data,*out,,*any,,,*unlimited,,102400,10,false,false,10
|
||||
LOG_WARNING,*log,,,,,,,,,,,,,,false,false,10
|
||||
DISABLE_AND_LOG,*log,,,,,,,,,,,,,,false,false,10
|
||||
DISABLE_AND_LOG,*disable_account,,,,,,,,,,,,,,false,false,10
|
||||
|
||||
|
@@ -114,7 +114,7 @@ func TestTutSMGCacheStats(t *testing.T) {
|
||||
}
|
||||
var rcvStats *utils.CacheStats
|
||||
|
||||
expectedStats := &utils.CacheStats{Destinations: 4, RatingPlans: 4, RatingProfiles: 9, Actions: 7, ActionPlans: 4, SharedGroups: 1, Aliases: 1,
|
||||
expectedStats := &utils.CacheStats{Destinations: 4, RatingPlans: 4, RatingProfiles: 9, Actions: 8, ActionPlans: 4, SharedGroups: 1, Aliases: 1,
|
||||
DerivedChargers: 1, LcrProfiles: 5, CdrStats: 6, Users: 3, LastLoadId: smgLoadInst.LoadId, LastLoadTime: smgLoadInst.LoadTime.Format(time.RFC3339)}
|
||||
var args utils.AttrCacheStats
|
||||
if err := tutSMGRpc.Call("ApierV2.GetCacheStats", args, &rcvStats); err != nil {
|
||||
|
||||
@@ -115,7 +115,7 @@ func TestTutLocalCacheStats(t *testing.T) {
|
||||
}
|
||||
var rcvStats *utils.CacheStats
|
||||
|
||||
expectedStats := &utils.CacheStats{Destinations: 4, RatingPlans: 4, RatingProfiles: 9, Actions: 7, ActionPlans: 4, SharedGroups: 1, Aliases: 1,
|
||||
expectedStats := &utils.CacheStats{Destinations: 4, RatingPlans: 4, RatingProfiles: 9, Actions: 8, ActionPlans: 4, SharedGroups: 1, Aliases: 1,
|
||||
DerivedChargers: 1, LcrProfiles: 5, CdrStats: 6, Users: 3, LastLoadId: loadInst.LoadId, LastLoadTime: loadInst.LoadTime.Format(time.RFC3339)}
|
||||
var args utils.AttrCacheStats
|
||||
if err := tutLocalRpc.Call("ApierV2.GetCacheStats", args, &rcvStats); err != nil {
|
||||
|
||||
@@ -115,7 +115,7 @@ func (self *SMGeneric) sessionStart(evStart SMGenericEvent, connId string) error
|
||||
}
|
||||
}
|
||||
return nil, nil
|
||||
}, time.Duration(3)*time.Second, sessionId)
|
||||
}, time.Duration(2)*time.Second, sessionId)
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -206,6 +206,14 @@ func (self *SMGeneric) GetLcrSuppliers(gev SMGenericEvent, clnt *rpc2.Client) ([
|
||||
return lcr.SuppliersSlice()
|
||||
}
|
||||
|
||||
// Called on session start
|
||||
func (self *SMGeneric) SessionStart(gev SMGenericEvent, clnt *rpc2.Client) (time.Duration, error) {
|
||||
if err := self.sessionStart(gev, getClientConnId(clnt)); err != nil {
|
||||
return nilDuration, err
|
||||
}
|
||||
return self.SessionUpdate(gev, clnt)
|
||||
}
|
||||
|
||||
// Execute debits for usage/maxUsage
|
||||
func (self *SMGeneric) SessionUpdate(gev SMGenericEvent, clnt *rpc2.Client) (time.Duration, error) {
|
||||
if initialID, err := gev.GetFieldAsString(utils.InitialOriginID); err == nil {
|
||||
@@ -238,14 +246,6 @@ func (self *SMGeneric) SessionUpdate(gev SMGenericEvent, clnt *rpc2.Client) (tim
|
||||
return evMaxUsage, nil
|
||||
}
|
||||
|
||||
// Called on session start
|
||||
func (self *SMGeneric) SessionStart(gev SMGenericEvent, clnt *rpc2.Client) (time.Duration, error) {
|
||||
if err := self.sessionStart(gev, getClientConnId(clnt)); err != nil {
|
||||
return nilDuration, err
|
||||
}
|
||||
return self.SessionUpdate(gev, clnt)
|
||||
}
|
||||
|
||||
// Called on session end, should stop debit loop
|
||||
func (self *SMGeneric) SessionEnd(gev SMGenericEvent, clnt *rpc2.Client) error {
|
||||
if initialID, err := gev.GetFieldAsString(utils.InitialOriginID); err == nil {
|
||||
@@ -261,34 +261,33 @@ func (self *SMGeneric) SessionEnd(gev SMGenericEvent, clnt *rpc2.Client) error {
|
||||
if sessionIDPrefix, err := gev.GetFieldAsString(utils.OriginIDPrefix); err == nil { // OriginIDPrefix is present, OriginID will not be anymore considered
|
||||
sessionIDs = self.getSessionIDsForPrefix(sessionIDPrefix)
|
||||
}
|
||||
usage, err := gev.GetUsage(utils.META_DEFAULT)
|
||||
if err != nil {
|
||||
if err != utils.ErrNotFound {
|
||||
return err
|
||||
usage, errUsage := gev.GetUsage(utils.META_DEFAULT)
|
||||
var lastUsed time.Duration
|
||||
if errUsage != nil {
|
||||
if errUsage != utils.ErrNotFound {
|
||||
return errUsage
|
||||
}
|
||||
lastUsed, err := gev.GetLastUsed(utils.META_DEFAULT)
|
||||
var err error
|
||||
lastUsed, err = gev.GetLastUsed(utils.META_DEFAULT)
|
||||
if err != nil {
|
||||
if err == utils.ErrNotFound {
|
||||
err = utils.ErrMandatoryIeMissing
|
||||
}
|
||||
return err
|
||||
}
|
||||
var s *SMGSession
|
||||
for _, sID := range sessionIDs {
|
||||
for _, s = range self.getSession(sID) {
|
||||
break
|
||||
}
|
||||
if s != nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
if s == nil {
|
||||
return nil
|
||||
}
|
||||
usage = s.TotalUsage() + lastUsed
|
||||
}
|
||||
var interimError error
|
||||
for _, sessionID := range sessionIDs {
|
||||
if errUsage != nil {
|
||||
var s *SMGSession
|
||||
for _, s = range self.getSession(sessionID) {
|
||||
break
|
||||
}
|
||||
if s == nil {
|
||||
continue // No session active, will not be able to close it anyway
|
||||
}
|
||||
usage = s.TotalUsage() + lastUsed
|
||||
}
|
||||
if err := self.sessionEnd(sessionID, usage); err != nil {
|
||||
interimError = err // Last error will be the one returned as API result
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user