From b2fb02b925f3c09986eed129edf1fcb9e3ea7210 Mon Sep 17 00:00:00 2001 From: Radu Ioan Fericean Date: Wed, 25 Jul 2012 14:44:37 +0300 Subject: [PATCH] save the asp new time --- cmd/cgr-rater/scheduler.go | 13 ++- timespans/action_timing.go | 11 ++- timespans/actions_test.go | 33 +------- timespans/activationperiod_test.go | 6 +- timespans/callcost_test.go | 3 +- timespans/calldesc.go | 2 + timespans/responder.go | 1 + timespans/storage_interface.go | 2 +- timespans/storage_redis.go | 17 ++-- timespans/storage_redix.go | 131 ----------------------------- 10 files changed, 39 insertions(+), 180 deletions(-) delete mode 100644 timespans/storage_redix.go diff --git a/cmd/cgr-rater/scheduler.go b/cmd/cgr-rater/scheduler.go index d78f401f0..5cda72fcd 100644 --- a/cmd/cgr-rater/scheduler.go +++ b/cmd/cgr-rater/scheduler.go @@ -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) } diff --git a/timespans/action_timing.go b/timespans/action_timing.go index a17552cbf..0fbe59782 100644 --- a/timespans/action_timing.go +++ b/timespans/action_timing.go @@ -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 diff --git a/timespans/actions_test.go b/timespans/actions_test.go index 23ab5c9fb..309838c73 100644 --- a/timespans/actions_test.go +++ b/timespans/actions_test.go @@ -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) } } diff --git a/timespans/activationperiod_test.go b/timespans/activationperiod_test.go index 20e15e068..327db203a 100644 --- a/timespans/activationperiod_test.go +++ b/timespans/activationperiod_test.go @@ -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) } diff --git a/timespans/callcost_test.go b/timespans/callcost_test.go index 31cf89043..afb1b38ac 100644 --- a/timespans/callcost_test.go +++ b/timespans/callcost_test.go @@ -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) } diff --git a/timespans/calldesc.go b/timespans/calldesc.go index a8d9e54b1..284f246a8 100644 --- a/timespans/calldesc.go +++ b/timespans/calldesc.go @@ -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 { diff --git a/timespans/responder.go b/timespans/responder.go index 582d60654..ecd19c2ed 100644 --- a/timespans/responder.go +++ b/timespans/responder.go @@ -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 { diff --git a/timespans/storage_interface.go b/timespans/storage_interface.go index 5a2b3c23c..6a315e9b7 100644 --- a/timespans/storage_interface.go +++ b/timespans/storage_interface.go @@ -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 { diff --git a/timespans/storage_redis.go b/timespans/storage_redis.go index 8e098887b..cee56c397 100644 --- a/timespans/storage_redis.go +++ b/timespans/storage_redis.go @@ -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 } diff --git a/timespans/storage_redix.go b/timespans/storage_redix.go deleted file mode 100644 index c3084fd36..000000000 --- a/timespans/storage_redix.go +++ /dev/null @@ -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 -*/ - -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 -}