save the asp new time

This commit is contained in:
Radu Ioan Fericean
2012-07-25 14:44:37 +03:00
parent 50d7d15c8c
commit b2fb02b925
10 changed files with 39 additions and 180 deletions

View File

@@ -69,9 +69,16 @@ func loadActionTimings(storage timespans.StorageGetter) {
}
// recreate the queue
s.queue = timespans.ActionTimingPriotityList{}
for _, at := range actionTimings {
at.CheckForASAP()
s.queue = append(s.queue, at)
for key, ats := range actionTimings {
toBeSaved := false
for _, at := range ats {
asapFound := at.CheckForASAP()
toBeSaved = toBeSaved || asapFound
s.queue = append(s.queue, at)
}
if toBeSaved {
storage.SetActionTimings(key, ats)
}
}
sort.Sort(s.queue)
}

View File

@@ -30,8 +30,9 @@ import (
)
const (
FORMAT = "2006-1-2 15:04:05 MST"
ASAP = "*asap"
FORMAT = "2006-1-2 15:04:05 MST"
ASAP = "*asap"
ASAP_DELAY = "5m"
)
type ActionTiming struct {
@@ -176,12 +177,14 @@ func (at *ActionTiming) Execute() (err error) {
return
}
func (at *ActionTiming) CheckForASAP() {
func (at *ActionTiming) CheckForASAP() bool {
if at.Timing.StartTime == ASAP {
oneMinute, _ := time.ParseDuration("1m")
oneMinute, _ := time.ParseDuration(ASAP_DELAY)
timeTokens := strings.Split(time.Now().Add(oneMinute).Format(time.Stamp), " ")
at.Timing.StartTime = timeTokens[len(timeTokens)-1]
return true
}
return false
}
// Structure to store actions according to weight

View File

@@ -51,7 +51,7 @@ func TestActionTimingStoreRestore(t *testing.T) {
ActionsId: "Commando",
}
r := at.store()
if string(r) != "some uuid|test|one,two,three|1,2,3,4,5,6,7,8,9,10,11,12;1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31;1,2,3,4,5;18:00:00;00:00:00;10;0;1;60;1|10|Commando" {
if string(r) != "some uuid|test|one,two,three|;1,2,3,4,5,6,7,8,9,10,11,12;1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31;1,2,3,4,5;18:00:00;00:00:00;10;0;1;60;1|10|Commando" {
t.Errorf("Error serializing action timing: %v", string(r))
}
o := &ActionTiming{}
@@ -242,34 +242,9 @@ func TestActionTimingFisrtOfTheMonth(t *testing.T) {
}
func TestActionTimingIsOneTimeRunNoInterval(t *testing.T) {
at := &ActionTiming{}
if !at.IsOneTimeRun() {
t.Errorf("%v should be one time run!", at)
}
}
func TestActionTimingIsOneTimeRunNothing(t *testing.T) {
at := &ActionTiming{Timing: &Interval{}}
if !at.IsOneTimeRun() {
t.Errorf("%v should be one time run!", at)
}
}
func TestActionTimingIsOneTimeRunStartTime(t *testing.T) {
at := &ActionTiming{Timing: &Interval{
StartTime: "00:00:00",
}}
if !at.IsOneTimeRun() {
t.Errorf("%v should be one time run!", at)
}
}
func TestActionTimingIsOneTimeRunWeekDay(t *testing.T) {
at := &ActionTiming{Timing: &Interval{
WeekDays: WeekDays{time.Monday},
}}
if at.IsOneTimeRun() {
t.Errorf("%v should NOT be one time run!", at)
at := &ActionTiming{Timing: &Interval{StartTime: ASAP}}
if !at.CheckForASAP() {
t.Errorf("%v should be asap!", at)
}
}

View File

@@ -42,7 +42,7 @@ func TestApStoreRestore(t *testing.T) {
ap := &ActivationPeriod{ActivationTime: d}
ap.AddInterval(i)
result := ap.store()
expected := "1328106601000000000|2;1;3,4;14:30:00;15:00:00;0;0;0;0;0"
expected := "1328106601000000000|;2;1;3,4;14:30:00;15:00:00;0;0;0;0;0"
if result != expected {
t.Errorf("Expected %q was %q", expected, result)
}
@@ -76,7 +76,7 @@ func TestApStoreRestoreJson(t *testing.T) {
ap := &ActivationPeriod{ActivationTime: d}
ap.AddInterval(i)
result, _ := json.Marshal(ap)
expected := "{\"ActivationTime\":\"2012-02-01T14:30:01Z\",\"Intervals\":[{\"Months\":[2],\"MonthDays\":[1],\"WeekDays\":[3,4],\"StartTime\":\"14:30:00\",\"EndTime\":\"15:00:00\",\"Weight\":0,\"ConnectFee\":0,\"Price\":0,\"PricedUnits\":0,\"RateIncrements\":0}]}"
expected := "{\"ActivationTime\":\"2012-02-01T14:30:01Z\",\"Intervals\":[{\"Years\":null,\"Months\":[2],\"MonthDays\":[1],\"WeekDays\":[3,4],\"StartTime\":\"14:30:00\",\"EndTime\":\"15:00:00\",\"Weight\":0,\"ConnectFee\":0,\"Price\":0,\"PricedUnits\":0,\"RateIncrements\":0}]}"
if string(result) != expected {
t.Errorf("Expected %q was %q", expected, result)
}
@@ -93,7 +93,7 @@ func TestApStoreRestoreBlank(t *testing.T) {
ap := &ActivationPeriod{ActivationTime: d}
ap.AddInterval(i)
result, _ := json.Marshal(ap)
expected := "{\"ActivationTime\":\"2012-02-01T14:30:01Z\",\"Intervals\":[{\"Months\":null,\"MonthDays\":null,\"WeekDays\":null,\"StartTime\":\"\",\"EndTime\":\"\",\"Weight\":0,\"ConnectFee\":0,\"Price\":0,\"PricedUnits\":0,\"RateIncrements\":0}]}"
expected := "{\"ActivationTime\":\"2012-02-01T14:30:01Z\",\"Intervals\":[{\"Years\":null,\"Months\":null,\"MonthDays\":null,\"WeekDays\":null,\"StartTime\":\"\",\"EndTime\":\"\",\"Weight\":0,\"ConnectFee\":0,\"Price\":0,\"PricedUnits\":0,\"RateIncrements\":0}]}"
if string(result) != expected {
t.Errorf("Expected %q was %q", expected, result)
}

View File

@@ -25,7 +25,7 @@ import (
)
func init() {
sg, _ := NewRedixStorage("127.0.0.1:6379", 10)
sg, _ := NewRedisStorage("127.0.0.1:6379", 10)
SetStorageGetter(sg)
}
@@ -35,6 +35,7 @@ func TestSingleResultMerge(t *testing.T) {
cd := &CallDescriptor{Direction: "OUT", TOR: "0", Tenant: "vdf", Subject: "rif", Destination: "0256", TimeStart: t1, TimeEnd: t2}
cc1, _ := cd.GetCost()
t.Log(len(cd.ActivationPeriods[0].Intervals))
t.Log(cd.ActivationPeriods[0].Intervals[0])
if cc1.Cost != 60 {
t.Errorf("expected 60 was %v", cc1.Cost)
}

View File

@@ -21,6 +21,7 @@ package timespans
import (
"errors"
"fmt"
"log"
"log/syslog"
"math"
"time"
@@ -267,6 +268,7 @@ Creates a CallCost structure with the cost information calculated for the receiv
func (cd *CallDescriptor) GetCost() (*CallCost, error) {
destPrefix, err := cd.SearchStorageForPrefix()
timespans := cd.splitInTimeSpans()
log.Print(timespans[0].Interval)
cost := 0.0
connectionFee := 0.0
for i, ts := range timespans {

View File

@@ -198,6 +198,7 @@ func (rs *Responder) callMethod(key *CallDescriptor, method string) (reply float
return
}
// Reflection worker type for not standalone balancer
type ResponderWorker struct{}
func (rw *ResponderWorker) Call(serviceMethod string, args interface{}, reply interface{}) error {

View File

@@ -43,7 +43,7 @@ type StorageGetter interface {
SetUserBalance(*UserBalance) error
GetActionTimings(string) ([]*ActionTiming, error)
SetActionTimings(string, []*ActionTiming) error
GetAllActionTimings() ([]*ActionTiming, error)
GetAllActionTimings() (map[string][]*ActionTiming, error)
}
type Marshaler interface {

View File

@@ -120,19 +120,20 @@ func (rs *RedisStorage) SetActionTimings(key string, ats []*ActionTiming) (err e
return rs.db.Set(key, result)
}
func (rs *RedisStorage) GetAllActionTimings() (ats []*ActionTiming, err error) {
func (rs *RedisStorage) GetAllActionTimings() (ats map[string][]*ActionTiming, err error) {
keys, err := rs.db.Keys(ACTION_TIMING_PREFIX + "*")
if err != nil {
return
}
values, err := rs.db.Mget(keys...)
if err != nil {
return
}
for _, v := range values.BytesArray() {
for _, key := range keys {
values, err := rs.db.Get(key)
if err != nil {
continue
}
var tempAts []*ActionTiming
err = rs.ms.Unmarshal(v, &tempAts)
ats = append(ats, tempAts...)
err = rs.ms.Unmarshal(values, &tempAts)
ats[key] = tempAts
}
return
}

View File

@@ -1,131 +0,0 @@
/*
Rating system designed to be used in VoIP Carriers World
Copyright (C) 2012 Radu Ioan Fericean
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>
*/
package timespans
import (
"github.com/fzzbt/radix/redis"
)
type RedixStorage struct {
db *redis.Client
ms Marshaler
}
func NewRedixStorage(address string, db int) (*RedixStorage, error) {
ndb := redis.NewClient(redis.Config{Address: address, Database: db})
ms := &MyMarshaler{}
return &RedixStorage{db: ndb, ms: ms}, nil
}
func (rs *RedixStorage) Close() {
rs.db.Close()
}
func (rs *RedixStorage) Flush() error {
rs.db.Flushdb()
return nil
}
func (rs *RedixStorage) GetActivationPeriodsOrFallback(key string) (aps []*ActivationPeriod, fallbackKey string, err error) {
elem, err := rs.db.Get(key).Bytes()
if err != nil {
return
}
err = rs.ms.Unmarshal(elem, &aps)
if err != nil {
err = rs.ms.Unmarshal(elem, &fallbackKey)
}
return
}
func (rs *RedixStorage) SetActivationPeriodsOrFallback(key string, aps []*ActivationPeriod, fallbackKey string) (err error) {
var result []byte
if len(aps) > 0 {
result, err = rs.ms.Marshal(&aps)
} else {
result, err = rs.ms.Marshal(fallbackKey)
}
return rs.db.Set(key, result).Err
}
func (rs *RedixStorage) GetDestination(key string) (dest *Destination, err error) {
if values, err := rs.db.Get(key).Bytes(); err == nil {
dest = &Destination{Id: key}
err = rs.ms.Unmarshal(values, dest)
}
return
}
func (rs *RedixStorage) SetDestination(dest *Destination) (err error) {
result, err := rs.ms.Marshal(dest)
return rs.db.Set(dest.Id, result).Err
}
func (rs *RedixStorage) GetActions(key string) (as []*Action, err error) {
if values, err := rs.db.Get(key).Bytes(); err == nil {
err = rs.ms.Unmarshal(values, &as)
}
return
}
func (rs *RedixStorage) SetActions(key string, as []*Action) (err error) {
result, err := rs.ms.Marshal(as)
return rs.db.Set(key, result).Err
}
func (rs *RedixStorage) GetUserBalance(key string) (ub *UserBalance, err error) {
if values, err := rs.db.Get(key).Bytes(); err == nil {
ub = &UserBalance{Id: key}
err = rs.ms.Unmarshal(values, ub)
}
return
}
func (rs *RedixStorage) SetUserBalance(ub *UserBalance) (err error) {
result, err := rs.ms.Marshal(ub)
return rs.db.Set(ub.Id, result).Err
}
func (rs *RedixStorage) GetActionTimings(key string) (ats []*ActionTiming, err error) {
if values, err := rs.db.Get(key).Bytes(); err == nil {
err = rs.ms.Unmarshal(values, ats)
}
return
}
func (rs *RedixStorage) SetActionTimings(key string, ats []*ActionTiming) (err error) {
result, err := rs.ms.Marshal(ats)
return rs.db.Set(key, result).Err
}
func (rs *RedixStorage) GetAllActionTimings() (ats []*ActionTiming, err error) {
keys, err := rs.db.Keys(ACTION_TIMING_PREFIX + "*").List()
if err != nil {
return
}
values, err := rs.db.Mget(keys).List()
if err != nil {
return
}
for _, v := range values {
var tempAts []*ActionTiming
err = rs.ms.Unmarshal([]byte(v), &ats)
ats = append(ats, tempAts...)
}
return
}