working on debit loop and mediator data

This commit is contained in:
Radu Ioan Fericean
2012-05-15 14:45:09 +03:00
parent 359f7b7ec3
commit e6b291d359
5 changed files with 59 additions and 55 deletions

View File

@@ -25,17 +25,14 @@ import (
"time"
)
const (
DEBIT_PERIOD = 10 * time.Second
)
// Session type holding the call information fields, a session delegate for specific
// actions and a channel to signal end of the debit loop.
type Session struct {
uuid, cstmId, subject, destination string
startTime time.Time // destination: startTime
sessionDelegate SessionDelegate
stopDebit chan byte
uuid string
callDescriptor *timespans.CallDescriptor
sessionDelegate SessionDelegate
stopDebit chan byte
CallCosts []*timespans.CallCost
}
// Creates a new session and starts the debit loop
@@ -45,12 +42,13 @@ func NewSession(ev *Event, ed SessionDelegate) (s *Session) {
log.Print("Error parsing answer event start time, using time.Now!")
startTime = time.Now()
}
cd := &timespans.CallDescriptor{CstmId: ev.Fields[CSTMID],
Subject: ev.Fields[SUBJECT],
DestinationPrefix: ev.Fields[DESTINATION],
TimeStart: startTime}
s = &Session{uuid: ev.Fields[UUID],
cstmId: ev.Fields[CSTMID],
subject: ev.Fields[SUBJECT],
destination: ev.Fields[DESTINATION],
startTime: startTime,
stopDebit: make(chan byte)}
callDescriptor: cd,
stopDebit: make(chan byte)}
s.sessionDelegate = ed
go s.startDebitLoop()
return
@@ -58,20 +56,25 @@ func NewSession(ev *Event, ed SessionDelegate) (s *Session) {
// the debit loop method (to be stoped by sending somenting on stopDebit channel)
func (s *Session) startDebitLoop() {
nextCd := *s.callDescriptor
for {
select {
case <-s.stopDebit:
return
default:
}
s.sessionDelegate.LoopAction()
time.Sleep(DEBIT_PERIOD)
if nextCd.TimeEnd == s.callDescriptor.TimeEnd { // first time use the session start time
nextCd.TimeStart = time.Now()
}
nextCd.TimeEnd = time.Now().Add(s.sessionDelegate.GetDebitPeriod())
s.sessionDelegate.LoopAction(s, &nextCd)
time.Sleep(s.sessionDelegate.GetDebitPeriod())
}
}
// Returns the session duration till the specified time
func (s *Session) getSessionDurationFrom(now time.Time) (d time.Duration) {
seconds := now.Sub(s.startTime).Seconds()
seconds := now.Sub(s.callDescriptor.TimeStart).Seconds()
d, err := time.ParseDuration(fmt.Sprintf("%ds", int(seconds)))
if err != nil {
log.Printf("Cannot parse session duration %v", seconds)
@@ -84,23 +87,8 @@ func (s *Session) GetSessionDuration() time.Duration {
return s.getSessionDurationFrom(time.Now())
}
// Returns the session cost till the specified time
func (s *Session) getSessionCostFrom(now time.Time) (callCosts *timespans.CallCost, err error) {
cd := &timespans.CallDescriptor{TOR: 1, CstmId: s.cstmId, Subject: s.subject, DestinationPrefix: s.destination, TimeStart: s.startTime, TimeEnd: now}
cd.SetStorageGetter(s.sessionDelegate.GetStorageGetter())
callCosts, err = cd.GetCost()
if err != nil {
log.Printf("Error getting call cost for session %v", s)
}
return
}
// Returns the session duration till now
func (s *Session) GetSessionCost() (callCosts *timespans.CallCost, err error) {
return s.getSessionCostFrom(time.Now())
}
// Stops the debit loop
func (s *Session) Close() {
s.stopDebit <- 1
s.callDescriptor.TimeEnd = time.Now()
}

View File

@@ -55,20 +55,7 @@ func TestSessionDurationSingle(t *testing.T) {
s := NewSession(newEvent, new(DirectSessionDelegate))
defer s.Close()
twoSeconds, _ := time.ParseDuration("2s")
if d := s.getSessionDurationFrom(s.startTime.Add(twoSeconds)); d.Seconds() < 2 || d.Seconds() > 3 {
if d := s.getSessionDurationFrom(s.callDescriptor.TimeStart.Add(twoSeconds)); d.Seconds() < 2 || d.Seconds() > 3 {
t.Errorf("Wrong session duration %v", d)
}
}
func TestSessionCostSingle(t *testing.T) {
s := NewSession(newEvent, new(DirectSessionDelegate))
defer s.Close()
twoSeconds, _ := time.ParseDuration("60s")
if cc, err := s.getSessionCostFrom(s.startTime.Add(twoSeconds)); err != nil {
t.Errorf("Get cost returned error %v", err)
} else {
if cc.Cost < 1 || cc.Cost > 1.1 {
t.Errorf("Expected %v got %v", "between 1 and 1.1", cc.Cost)
}
}
}

View File

@@ -21,6 +21,11 @@ package sessionmanager
import (
"github.com/rif/cgrates/timespans"
"log"
"time"
)
const (
DEBIT_PERIOD = 10 * time.Second
)
var (
@@ -37,9 +42,9 @@ type SessionDelegate interface {
// Called on freeswitch's hangup event
OnChannelHangupComplete(*Event, *Session)
// The method to be called inside the debit loop
LoopAction()
LoopAction(*Session, *timespans.CallDescriptor)
// Returns a storage getter for the sesssion to use
GetStorageGetter() timespans.StorageGetter
GetDebitPeriod() time.Duration
}
// Sample SessionDelegate calling the timespans methods directly
@@ -57,12 +62,20 @@ func (dsd *DirectSessionDelegate) OnChannelHangupComplete(ev *Event, s *Session)
log.Print("direct hangup")
}
func (dsd *DirectSessionDelegate) LoopAction() {
log.Print("Direct debit")
func (dsd *DirectSessionDelegate) LoopAction(s *Session, cd *timespans.CallDescriptor) {
cc, err := cd.Debit()
if err != nil {
log.Printf("Could not complete debit opperation: %v", err)
}
s.CallCosts = append(s.CallCosts, cc)
cd.Amount = DEBIT_PERIOD.Seconds()
if remainingSeconds, err := cd.GetMaxSessionTime(); remainingSeconds < DEBIT_PERIOD.Seconds() || err != nil {
log.Print("Not enough money for another debit period!")
}
}
func (dsd *DirectSessionDelegate) GetStorageGetter() timespans.StorageGetter {
return storageGetter
func (dsd *DirectSessionDelegate) GetDebitPeriod() time.Duration {
return DEBIT_PERIOD
}
// Sample SessionDelegate calling the timespans methods through the RPC interface
@@ -80,10 +93,10 @@ func (rsd *RPCSessionDelegate) OnChannelHangupComplete(ev *Event, s *Session) {
log.Print("rpc hangup")
}
func (rsd *RPCSessionDelegate) LoopAction() {
func (rsd *RPCSessionDelegate) LoopAction(s *Session, cd *timespans.CallDescriptor) {
log.Print("Rpc debit")
}
func (rsd *RPCSessionDelegate) GetStorageGetter() timespans.StorageGetter {
return storageGetter
func (rsd *RPCSessionDelegate) GetDebitPeriod() time.Duration {
return DEBIT_PERIOD
}

View File

@@ -295,6 +295,21 @@ func (cd *CallDescriptor) GetMaxSessionTime() (seconds float64, err error) {
return 0, nil
}
// Interface method used to add/substract an amount of cents or bonus seconds (as returned by GetCost method)
// from user's money budget.
func (cd *CallDescriptor) Debit() (cc *CallCost, err error) {
cc, err = cd.GetCost()
if userBudget, err := cd.getUserBudget(); err == nil && userBudget != nil {
if cc.Cost != 0 || cc.ConnectFee != 0 {
userBudget.debitMoneyBudget(cd.storageGetter, cc.Cost+cc.ConnectFee)
}
for _, ts := range cc.Timespans {
userBudget.debitMinutesBudget(cd.storageGetter, ts.MinuteInfo.Quantity, cd.DestinationPrefix)
}
}
return
}
/*
Interface method used to add/substract an amount of cents from user's money budget.
The amount filed has to be filled in call descriptor.

View File

@@ -34,6 +34,7 @@ type TimeSpan struct {
MinuteInfo *MinuteInfo
}
// Holds the bonus minute information related to a specified timespan
type MinuteInfo struct {
DestinationId string
Quantity float64