From 078587435721d91e3eaae3607dc90b7f0922b045 Mon Sep 17 00:00:00 2001 From: Radu Ioan Fericean Date: Tue, 6 Aug 2013 22:11:03 +0300 Subject: [PATCH] call duration fixes and switch relative start/end time --- engine/calldesc.go | 8 ++++---- engine/timespans.go | 16 +++++++++++++--- sessionmanager/fssessionmanager.go | 8 +++++--- sessionmanager/session.go | 25 +++++++++++++------------ 4 files changed, 35 insertions(+), 22 deletions(-) diff --git a/engine/calldesc.go b/engine/calldesc.go index 7995d0965..27c5f3db4 100644 --- a/engine/calldesc.go +++ b/engine/calldesc.go @@ -97,8 +97,8 @@ type CallDescriptor struct { TOR string Tenant, Subject, Account, Destination string TimeStart, TimeEnd time.Time - LoopIndex float64 // indicates the postion of this segment in a cost request loop - CallDuration float64 // the call duration so far (partial or final) + LoopIndex float64 // indicates the postion of this segment in a cost request loop + CallDuration time.Duration // the call duration so far (partial or final) Amount float64 FallbackSubject string // the subject to check for destination if not found on primary subject ActivationPeriods []*ActivationPeriod @@ -188,7 +188,7 @@ Splits the received timespan into sub time spans according to the activation per */ func (cd *CallDescriptor) splitInTimeSpans(firstSpan *TimeSpan) (timespans []*TimeSpan) { if firstSpan == nil { - firstSpan = &TimeSpan{TimeStart: cd.TimeStart, TimeEnd: cd.TimeEnd} + firstSpan = &TimeSpan{TimeStart: cd.TimeStart, TimeEnd: cd.TimeEnd, CallDuration: cd.CallDuration.Seconds()} } timespans = append(timespans, firstSpan) // split on (free) minute buckets @@ -317,7 +317,7 @@ func (cd *CallDescriptor) GetMaxSessionTime() (seconds float64, err error) { Logger.Debug(fmt.Sprintf("available sec: %v credit: %v", availableSeconds, availableCredit)) } } else { - Logger.Err(fmt.Sprintf("Could not get user balance for %s.", cd.GetUserBalanceKey())) + Logger.Err(fmt.Sprintf("Could not get user balance for %s: %s.", cd.GetUserBalanceKey(), err.Error())) return cd.Amount, err } // check for zero balance diff --git a/engine/timespans.go b/engine/timespans.go index d0381bad9..b21395edd 100644 --- a/engine/timespans.go +++ b/engine/timespans.go @@ -118,7 +118,7 @@ func (ts *TimeSpan) SplitByInterval(i *Interval) (nts *TimeSpan) { ts.TimeEnd = splitTime nts.SetInterval(i) nts.CallDuration = ts.CallDuration - ts.CallDuration = math.Max(0, ts.CallDuration-nts.GetDuration().Seconds()) + ts.SetNewCallDuration(nts) return } @@ -141,7 +141,7 @@ func (ts *TimeSpan) SplitByInterval(i *Interval) (nts *TimeSpan) { nts = &TimeSpan{TimeStart: splitTime, TimeEnd: ts.TimeEnd} ts.TimeEnd = splitTime nts.CallDuration = ts.CallDuration - ts.CallDuration = math.Max(0, ts.CallDuration-nts.GetDuration().Seconds()) + ts.SetNewCallDuration(nts) return } @@ -157,7 +157,7 @@ func (ts *TimeSpan) SplitByInterval(i *Interval) (nts *TimeSpan) { nts.SetInterval(i) nts.CallDuration = ts.CallDuration - ts.CallDuration = math.Max(0, ts.CallDuration-nts.GetDuration().Seconds()) + ts.SetNewCallDuration(nts) return } @@ -172,7 +172,9 @@ func (ts *TimeSpan) SplitByActivationPeriod(ap *ActivationPeriod) (newTs *TimeSp return nil } newTs = &TimeSpan{TimeStart: ap.ActivationTime, TimeEnd: ts.TimeEnd, ActivationPeriod: ap} + newTs.CallDuration = ts.CallDuration ts.TimeEnd = ap.ActivationTime + ts.SetNewCallDuration(newTs) return } @@ -189,7 +191,9 @@ func (ts *TimeSpan) SplitByMinuteBucket(mb *MinuteBucket) (newTs *TimeSpan) { if !mb.ExpirationDate.IsZero() && ts.TimeEnd.After(mb.ExpirationDate) { newTs = &TimeSpan{TimeStart: mb.ExpirationDate, TimeEnd: ts.TimeEnd} + newTs.CallDuration = ts.CallDuration ts.TimeEnd = mb.ExpirationDate + ts.SetNewCallDuration(newTs) } s := ts.GetDuration().Seconds() @@ -203,7 +207,9 @@ func (ts *TimeSpan) SplitByMinuteBucket(mb *MinuteBucket) (newTs *TimeSpan) { newTimeEnd := ts.TimeStart.Add(secDuration) newTs = &TimeSpan{TimeStart: newTimeEnd, TimeEnd: ts.TimeEnd} ts.TimeEnd = newTimeEnd + newTs.CallDuration = ts.CallDuration ts.MinuteInfo.Quantity = mb.Seconds + ts.SetNewCallDuration(newTs) mb.Seconds = 0 return @@ -216,3 +222,7 @@ func (ts *TimeSpan) GetGroupStart() float64 { func (ts *TimeSpan) GetGroupEnd() float64 { return ts.CallDuration } + +func (ts *TimeSpan) SetNewCallDuration(nts *TimeSpan) { + ts.CallDuration = math.Max(0, ts.CallDuration-nts.GetDuration().Seconds()) +} diff --git a/sessionmanager/fssessionmanager.go b/sessionmanager/fssessionmanager.go index eea13efc4..39dafacad 100644 --- a/sessionmanager/fssessionmanager.go +++ b/sessionmanager/fssessionmanager.go @@ -194,7 +194,7 @@ func (sm *FSSessionManager) OnChannelHangupComplete(ev Event) { if s == nil { // Not handled by us return } - defer s.Close() // Stop loop and save the costs deducted so far to database + defer s.Close(ev) // Stop loop and save the costs deducted so far to database if ev.GetReqType() == utils.POSTPAID { startTime, err := ev.GetStartTime(START_TIME) if err != nil { @@ -213,7 +213,7 @@ func (sm *FSSessionManager) OnChannelHangupComplete(ev Event) { Subject: ev.GetSubject(), Account: ev.GetAccount(), LoopIndex: 0, - CallDuration: endTime.Sub(startTime).Seconds(), + CallDuration: endTime.Sub(startTime), Destination: ev.GetDestination(), TimeStart: startTime, TimeEnd: endTime, @@ -310,7 +310,7 @@ func (sm *FSSessionManager) LoopAction(s *Session, cd *engine.CallDescriptor, in cc := &engine.CallCost{} cd.LoopIndex = index cd.Amount = sm.debitPeriod.Seconds() - cd.CallDuration += cd.Amount + cd.CallDuration += time.Duration(cd.Amount) * time.Second err := sm.connector.MaxDebit(*cd, cc) if err != nil { engine.Logger.Err(fmt.Sprintf("Could not complete debit opperation: %v", err)) @@ -330,9 +330,11 @@ func (sm *FSSessionManager) LoopAction(s *Session, cd *engine.CallDescriptor, in } s.CallCosts = append(s.CallCosts, cc) } + func (sm *FSSessionManager) GetDebitPeriod() time.Duration { return sm.debitPeriod } + func (sm *FSSessionManager) GetDbLogger() engine.DataStorage { return sm.loggerDB } diff --git a/sessionmanager/session.go b/sessionmanager/session.go index 72bd7da38..b666889b4 100644 --- a/sessionmanager/session.go +++ b/sessionmanager/session.go @@ -81,18 +81,18 @@ func NewSession(ev Event, sm SessionManager) (s *Session) { func (s *Session) startDebitLoop() { nextCd := *s.callDescriptor index := 0.0 + ticker := time.NewTicker(s.sessionManager.GetDebitPeriod()) for { select { case <-s.stopDebit: return - default: + case <-ticker.C: } - if nextCd.TimeEnd != s.callDescriptor.TimeEnd { // first time use the session start time - nextCd.TimeStart = time.Now() + if index > 0 { // first time use the session start time + nextCd.TimeStart = nextCd.TimeEnd } - nextCd.TimeEnd = time.Now().Add(s.sessionManager.GetDebitPeriod()) + nextCd.TimeEnd = nextCd.TimeStart.Add(s.sessionManager.GetDebitPeriod()) s.sessionManager.LoopAction(s, &nextCd, index) - time.Sleep(s.sessionManager.GetDebitPeriod()) index++ } } @@ -107,19 +107,20 @@ func (s *Session) getSessionDurationFrom(now time.Time) (d time.Duration) { return } -// Returns the session duration till now -func (s *Session) GetSessionDuration() time.Duration { - return s.getSessionDurationFrom(time.Now()) -} - // Stops the debit loop -func (s *Session) Close() { +func (s *Session) Close(ev Event) { engine.Logger.Debug(fmt.Sprintf("Stopping debit for %s", s.uuid)) if s == nil { return } s.stopDebit <- true - s.callDescriptor.TimeEnd = time.Now() + //s.callDescriptor.TimeEnd = time.Now() + endTime, err := ev.GetEndTime() + if err != nil { + engine.Logger.Err("Error parsing answer event stop time.") + endTime = s.callDescriptor.TimeStart.Add(s.callDescriptor.CallDuration) + } + s.callDescriptor.TimeEnd = endTime s.SaveOperations() s.sessionManager.RemoveSession(s) }