restructured action plan

This commit is contained in:
Radu Ioan Fericean
2015-12-14 22:30:36 +02:00
parent 2d1b81d850
commit 9d228d80bf
12 changed files with 262 additions and 297 deletions

View File

@@ -21,7 +21,6 @@ package engine
import (
"fmt"
"sort"
"strconv"
"time"
"github.com/cgrates/cgrates/utils"
@@ -32,20 +31,31 @@ const (
FORMAT = "2006-1-2 15:04:05 MST"
)
type ActionPlan struct {
Uuid string // uniquely identify the timing
Id string // informative purpose only
AccountIds []string
type ActionTiming struct {
Uuid string
Timing *RateInterval
Weight float64
ActionsId string
Weight float64
actions Actions
accountIDs map[string]struct{}
stCache time.Time // cached time of the next start
}
type ActionPlans []*ActionPlan
type ActionPlan struct {
Uuid string // uniquely identify the timing
Id string // informative purpose only
AccountIDs map[string]struct{}
ActionTimings []*ActionTiming
}
func (at *ActionPlan) GetNextStartTime(now time.Time) (t time.Time) {
func (apl *ActionPlan) RemoveAccountID(accID string) (found bool) {
if _, found = apl.AccountIDs[accID]; found {
delete(apl.AccountIDs, accID)
}
return
}
func (at *ActionTiming) GetNextStartTime(now time.Time) (t time.Time) {
if !at.stCache.IsZero() {
return at.stCache
}
@@ -68,7 +78,7 @@ func (at *ActionPlan) GetNextStartTime(now time.Time) (t time.Time) {
}
// To be deleted after the above solution proves reliable
func (at *ActionPlan) GetNextStartTimeOld(now time.Time) (t time.Time) {
func (at *ActionTiming) GetNextStartTimeOld(now time.Time) (t time.Time) {
if !at.stCache.IsZero() {
return at.stCache
}
@@ -218,15 +228,15 @@ YEARS:
return
}
func (at *ActionPlan) ResetStartTimeCache() {
func (at *ActionTiming) ResetStartTimeCache() {
at.stCache = time.Date(1, 1, 1, 0, 0, 0, 0, time.UTC)
}
func (at *ActionPlan) SetActions(as Actions) {
func (at *ActionTiming) SetActions(as Actions) {
at.actions = as
}
func (at *ActionPlan) getActions() (as []*Action, err error) {
func (at *ActionTiming) getActions() (as []*Action, err error) {
if at.actions == nil {
at.actions, err = ratingStorage.GetActions(at.ActionsId, false)
}
@@ -234,8 +244,8 @@ func (at *ActionPlan) getActions() (as []*Action, err error) {
return at.actions, err
}
func (at *ActionPlan) Execute() (err error) {
if len(at.AccountIds) == 0 { // nothing to do if no accounts set
func (at *ActionTiming) Execute() (err error) {
if len(at.accountIDs) == 0 { // nothing to do if no accounts set
return
}
at.ResetStartTimeCache()
@@ -244,8 +254,8 @@ func (at *ActionPlan) Execute() (err error) {
utils.Logger.Err(fmt.Sprintf("Failed to get actions for %s: %s", at.ActionsId, err))
return
}
_, err = Guardian.Guard(func() (interface{}, error) {
for _, accId := range at.AccountIds {
for accId, _ := range at.accountIDs {
_, err = Guardian.Guard(func() (interface{}, error) {
ub, err := accountingStorage.GetAccount(accId)
if err != nil {
utils.Logger.Warning(fmt.Sprintf("Could not get user balances for this id: %s. Skipping!", accId))
@@ -261,45 +271,7 @@ func (at *ActionPlan) Execute() (err error) {
if expDate, parseErr := utils.ParseDate(a.ExpirationString); (a.Balance == nil || a.Balance.ExpirationDate.IsZero()) && parseErr == nil && !expDate.IsZero() {
a.Balance.ExpirationDate = expDate
}
// handle remove action
if a.ActionType == REMOVE_ACCOUNT {
if err := accountingStorage.RemoveAccount(accId); err != nil {
utils.Logger.Err(fmt.Sprintf("Could not remove account Id: %s: %v", accId, err))
transactionFailed = true
break
}
// clean the account id from all action plans
allATs, err := ratingStorage.GetAllActionPlans()
if err != nil && err != utils.ErrNotFound {
utils.Logger.Err(fmt.Sprintf("Could not get action plans: %s: %v", accId, err))
transactionFailed = true
break
}
for key, ats := range allATs {
changed := false
for _, at := range ats {
for i := 0; i < len(at.AccountIds); i++ {
if at.AccountIds[i] == accId {
// delete without preserving order
at.AccountIds[i] = at.AccountIds[len(at.AccountIds)-1]
at.AccountIds = at.AccountIds[:len(at.AccountIds)-1]
i--
changed = true
}
}
}
if changed {
// save action plan
ratingStorage.SetActionPlans(key, ats)
// cache
ratingStorage.CacheRatingPrefixValues(map[string][]string{utils.ACTION_PLAN_PREFIX: []string{utils.ACTION_PLAN_PREFIX + key}})
}
}
toBeSaved = false
continue // do not go to getActionFunc
// TODO: maybe we should break here as the account is gone
// will leave continue for now as the next action can create another acount
}
actionFunction, exists := getActionFunc(a.ActionType)
if !exists {
// do not allow the action plan to be rescheduled
@@ -318,18 +290,18 @@ func (at *ActionPlan) Execute() (err error) {
if !transactionFailed && toBeSaved {
accountingStorage.SetAccount(ub)
}
}
return 0, nil
}, 0, at.AccountIds...)
return 0, nil
}, 0, accId)
}
if err != nil {
utils.Logger.Warning(fmt.Sprintf("Error executing action plan: %v", err))
return err
}
storageLogger.LogActionPlan(utils.SCHED_SOURCE, at, aac)
storageLogger.LogActionTiming(utils.SCHED_SOURCE, at, aac)
return
}
func (at *ActionPlan) IsASAP() bool {
func (at *ActionTiming) IsASAP() bool {
if at.Timing == nil {
return false
}
@@ -337,17 +309,17 @@ func (at *ActionPlan) IsASAP() bool {
}
// Structure to store actions according to weight
type ActionPlanPriotityList []*ActionPlan
type ActionTimingPriorityList []*ActionTiming
func (atpl ActionPlanPriotityList) Len() int {
func (atpl ActionTimingPriorityList) Len() int {
return len(atpl)
}
func (atpl ActionPlanPriotityList) Swap(i, j int) {
func (atpl ActionTimingPriorityList) Swap(i, j int) {
atpl[i], atpl[j] = atpl[j], atpl[i]
}
func (atpl ActionPlanPriotityList) Less(i, j int) bool {
func (atpl ActionTimingPriorityList) Less(i, j int) bool {
if atpl[i].GetNextStartTime(time.Now()).Equal(atpl[j].GetNextStartTime(time.Now())) {
// higher weights earlyer in the list
return atpl[i].Weight > atpl[j].Weight
@@ -355,20 +327,16 @@ func (atpl ActionPlanPriotityList) Less(i, j int) bool {
return atpl[i].GetNextStartTime(time.Now()).Before(atpl[j].GetNextStartTime(time.Now()))
}
func (atpl ActionPlanPriotityList) Sort() {
func (atpl ActionTimingPriorityList) Sort() {
sort.Sort(atpl)
}
func (at *ActionPlan) String_DISABLED() string {
return at.Id + " " + at.GetNextStartTime(time.Now()).String() + ",w: " + strconv.FormatFloat(at.Weight, 'f', -1, 64)
}
// Helper to remove ActionPlan members based on specific filters, empty data means no always match
func RemActionPlan(ats ActionPlans, actionTimingId, accountId string) ActionPlans {
for idx, at := range ats {
if len(actionTimingId) != 0 && at.Uuid != actionTimingId { // No Match for ActionPlanId, no need to move further
continue
}
/*func RemActionPlan(apl ActionPlan, actionTimingId, accountId string) ActionPlan {
if len(actionTimingId) != 0 && apl.Uuid != actionTimingId { // No Match for ActionPlanId, no need to move further
continue
}
for idx, ats := range apl.ActionTimings {
if len(accountId) == 0 { // No account defined, considered match for complete removal
if len(ats) == 1 { // Removing last item, by init empty
return make([]*ActionPlan, 0)
@@ -392,4 +360,4 @@ func RemActionPlan(ats ActionPlans, actionTimingId, accountId string) ActionPlan
}
}
return ats
}
}*/

View File

@@ -79,47 +79,6 @@ func (at *ActionTrigger) Execute(ub *Account, sq *StatsQueueTriggered) (err erro
a.Balance = &Balance{}
}
a.Balance.ExpirationDate, _ = utils.ParseDate(a.ExpirationString)
// handle remove action
if a.ActionType == REMOVE_ACCOUNT {
accId := ub.Id
if err := accountingStorage.RemoveAccount(accId); err != nil {
utils.Logger.Err(fmt.Sprintf("Could not remove account Id: %s: %v", accId, err))
transactionFailed = true
break
}
// clean the account id from all action plans
allATs, err := ratingStorage.GetAllActionPlans()
if err != nil && err != utils.ErrNotFound {
utils.Logger.Err(fmt.Sprintf("Could not get action plans: %s: %v", accId, err))
transactionFailed = true
break
}
for key, ats := range allATs {
changed := false
for _, at := range ats {
for i := 0; i < len(at.AccountIds); i++ {
if at.AccountIds[i] == accId {
// delete without preserving order
at.AccountIds[i] = at.AccountIds[len(at.AccountIds)-1]
at.AccountIds = at.AccountIds[:len(at.AccountIds)-1]
i -= 1
changed = true
}
}
}
if changed {
// save action plan
ratingStorage.SetActionPlans(key, ats)
// cache
ratingStorage.CacheRatingPrefixValues(map[string][]string{utils.ACTION_PLAN_PREFIX: []string{utils.ACTION_PLAN_PREFIX + key}})
}
}
toBeSaved = false
continue // do not go to getActionFunc
// TODO: maybe we should break here as the account is gone
// will leave continue for now as the next action can create another acount
}
actionFunction, exists := getActionFunc(a.ActionType)
if !exists {
utils.Logger.Err(fmt.Sprintf("Function type %v not available, aborting execution!", a.ActionType))

View File

@@ -38,7 +38,7 @@ var (
)
func TestActionTimingAlways(t *testing.T) {
at := &ActionPlan{Timing: &RateInterval{Timing: &RITiming{StartTime: "00:00:00"}}}
at := &ActionTiming{Timing: &RateInterval{Timing: &RITiming{StartTime: "00:00:00"}}}
st := at.GetNextStartTime(referenceDate)
y, m, d := referenceDate.Date()
expected := time.Date(y, m, d, 0, 0, 0, 0, time.Local).AddDate(0, 0, 1)
@@ -48,7 +48,7 @@ func TestActionTimingAlways(t *testing.T) {
}
func TestActionPlanNothing(t *testing.T) {
at := &ActionPlan{}
at := &ActionTiming{}
st := at.GetNextStartTime(referenceDate)
expected := time.Date(1, 1, 1, 0, 0, 0, 0, time.UTC)
if !st.Equal(expected) {
@@ -57,7 +57,7 @@ func TestActionPlanNothing(t *testing.T) {
}
func TestActionTimingMidnight(t *testing.T) {
at := &ActionPlan{Timing: &RateInterval{Timing: &RITiming{StartTime: "00:00:00"}}}
at := &ActionTiming{Timing: &RateInterval{Timing: &RITiming{StartTime: "00:00:00"}}}
y, m, d := referenceDate.Date()
now := time.Date(y, m, d, 0, 0, 1, 0, time.Local)
st := at.GetNextStartTime(now)
@@ -68,7 +68,7 @@ func TestActionTimingMidnight(t *testing.T) {
}
func TestActionPlanOnlyHour(t *testing.T) {
at := &ActionPlan{Timing: &RateInterval{Timing: &RITiming{StartTime: "10:01:00"}}}
at := &ActionTiming{Timing: &RateInterval{Timing: &RITiming{StartTime: "10:01:00"}}}
st := at.GetNextStartTime(referenceDate)
y, m, d := now.Date()
@@ -82,7 +82,7 @@ func TestActionPlanOnlyHour(t *testing.T) {
}
func TestActionPlanHourYear(t *testing.T) {
at := &ActionPlan{Timing: &RateInterval{Timing: &RITiming{Years: utils.Years{2022}, StartTime: "10:01:00"}}}
at := &ActionTiming{Timing: &RateInterval{Timing: &RITiming{Years: utils.Years{2022}, StartTime: "10:01:00"}}}
st := at.GetNextStartTime(referenceDate)
expected := time.Date(2022, 1, 1, 10, 1, 0, 0, time.Local)
if !st.Equal(expected) {
@@ -91,7 +91,7 @@ func TestActionPlanHourYear(t *testing.T) {
}
func TestActionPlanOnlyWeekdays(t *testing.T) {
at := &ActionPlan{Timing: &RateInterval{Timing: &RITiming{WeekDays: []time.Weekday{time.Monday}}}}
at := &ActionTiming{Timing: &RateInterval{Timing: &RITiming{WeekDays: []time.Weekday{time.Monday}}}}
st := at.GetNextStartTime(referenceDate)
y, m, d := now.Date()
@@ -112,7 +112,7 @@ func TestActionPlanOnlyWeekdays(t *testing.T) {
}
func TestActionPlanHourWeekdays(t *testing.T) {
at := &ActionPlan{Timing: &RateInterval{Timing: &RITiming{WeekDays: []time.Weekday{time.Monday}, StartTime: "10:01:00"}}}
at := &ActionTiming{Timing: &RateInterval{Timing: &RITiming{WeekDays: []time.Weekday{time.Monday}, StartTime: "10:01:00"}}}
st := at.GetNextStartTime(referenceDate)
y, m, d := now.Date()
@@ -135,7 +135,7 @@ func TestActionPlanOnlyMonthdays(t *testing.T) {
y, m, d := now.Date()
tomorrow := time.Date(y, m, d, 0, 0, 0, 0, time.Local).AddDate(0, 0, 1)
at := &ActionPlan{Timing: &RateInterval{Timing: &RITiming{MonthDays: utils.MonthDays{1, 25, 2, tomorrow.Day()}}}}
at := &ActionTiming{Timing: &RateInterval{Timing: &RITiming{MonthDays: utils.MonthDays{1, 25, 2, tomorrow.Day()}}}}
st := at.GetNextStartTime(referenceDate)
expected := tomorrow
if !st.Equal(expected) {
@@ -151,7 +151,7 @@ func TestActionPlanHourMonthdays(t *testing.T) {
if now.After(testTime) {
y, m, d = tomorrow.Date()
}
at := &ActionPlan{Timing: &RateInterval{Timing: &RITiming{MonthDays: utils.MonthDays{now.Day(), tomorrow.Day()}, StartTime: "10:01:00"}}}
at := &ActionTiming{Timing: &RateInterval{Timing: &RITiming{MonthDays: utils.MonthDays{now.Day(), tomorrow.Day()}, StartTime: "10:01:00"}}}
st := at.GetNextStartTime(referenceDate)
expected := time.Date(y, m, d, 10, 1, 0, 0, time.Local)
if !st.Equal(expected) {
@@ -163,7 +163,7 @@ func TestActionPlanOnlyMonths(t *testing.T) {
y, m, _ := now.Date()
nextMonth := time.Date(y, m, 1, 0, 0, 0, 0, time.Local).AddDate(0, 1, 0)
at := &ActionPlan{Timing: &RateInterval{Timing: &RITiming{Months: utils.Months{time.February, time.May, nextMonth.Month()}}}}
at := &ActionTiming{Timing: &RateInterval{Timing: &RITiming{Months: utils.Months{time.February, time.May, nextMonth.Month()}}}}
st := at.GetNextStartTime(referenceDate)
expected := time.Date(nextMonth.Year(), nextMonth.Month(), 1, 0, 0, 0, 0, time.Local)
if !st.Equal(expected) {
@@ -186,7 +186,7 @@ func TestActionPlanHourMonths(t *testing.T) {
y = nextMonth.Year()
}
at := &ActionPlan{Timing: &RateInterval{Timing: &RITiming{
at := &ActionTiming{Timing: &RateInterval{Timing: &RITiming{
Months: utils.Months{now.Month(), nextMonth.Month()},
StartTime: "10:01:00"}}}
st := at.GetNextStartTime(referenceDate)
@@ -216,7 +216,7 @@ func TestActionPlanHourMonthdaysMonths(t *testing.T) {
month = nextMonth.Month()
}
}
at := &ActionPlan{Timing: &RateInterval{
at := &ActionTiming{Timing: &RateInterval{
Timing: &RITiming{
Months: utils.Months{now.Month(), nextMonth.Month()},
MonthDays: utils.MonthDays{now.Day(), tomorrow.Day()},
@@ -234,7 +234,7 @@ func TestActionPlanFirstOfTheMonth(t *testing.T) {
y, m, _ := now.Date()
nextMonth := time.Date(y, m, 1, 0, 0, 0, 0, time.Local).AddDate(0, 1, 0)
at := &ActionPlan{Timing: &RateInterval{
at := &ActionTiming{Timing: &RateInterval{
Timing: &RITiming{
MonthDays: utils.MonthDays{1},
},
@@ -249,7 +249,7 @@ func TestActionPlanFirstOfTheMonth(t *testing.T) {
func TestActionPlanOnlyYears(t *testing.T) {
y, _, _ := referenceDate.Date()
nextYear := time.Date(y, 1, 1, 0, 0, 0, 0, time.Local).AddDate(1, 0, 0)
at := &ActionPlan{Timing: &RateInterval{Timing: &RITiming{Years: utils.Years{now.Year(), nextYear.Year()}}}}
at := &ActionTiming{Timing: &RateInterval{Timing: &RITiming{Years: utils.Years{now.Year(), nextYear.Year()}}}}
st := at.GetNextStartTime(referenceDate)
expected := nextYear
if !st.Equal(expected) {
@@ -258,7 +258,7 @@ func TestActionPlanOnlyYears(t *testing.T) {
}
func TestActionPlanPast(t *testing.T) {
at := &ActionPlan{Timing: &RateInterval{Timing: &RITiming{Years: utils.Years{2023}}}}
at := &ActionTiming{Timing: &RateInterval{Timing: &RITiming{Years: utils.Years{2023}}}}
st := at.GetNextStartTime(referenceDate)
expected := time.Date(2023, 1, 1, 0, 0, 0, 0, time.Local)
if !st.Equal(expected) {
@@ -267,7 +267,7 @@ func TestActionPlanPast(t *testing.T) {
}
func TestActionPlanHourYears(t *testing.T) {
at := &ActionPlan{Timing: &RateInterval{Timing: &RITiming{Years: utils.Years{referenceDate.Year(), referenceDate.Year() + 1}, StartTime: "10:01:00"}}}
at := &ActionTiming{Timing: &RateInterval{Timing: &RITiming{Years: utils.Years{referenceDate.Year(), referenceDate.Year() + 1}, StartTime: "10:01:00"}}}
st := at.GetNextStartTime(referenceDate)
expected := time.Date(referenceDate.Year(), 1, 1, 10, 1, 0, 0, time.Local)
if referenceDate.After(expected) {
@@ -292,7 +292,7 @@ func TestActionPlanHourMonthdaysYear(t *testing.T) {
expected = tomorrow
}
}
at := &ActionPlan{Timing: &RateInterval{
at := &ActionTiming{Timing: &RateInterval{
Timing: &RITiming{
Years: utils.Years{now.Year(), nextYear.Year()},
MonthDays: utils.MonthDays{now.Day(), tomorrow.Day()},
@@ -332,7 +332,7 @@ func TestActionPlanHourMonthdaysMonthYear(t *testing.T) {
year = nextYear.Year()
}
}
at := &ActionPlan{Timing: &RateInterval{
at := &ActionTiming{Timing: &RateInterval{
Timing: &RITiming{
Years: utils.Years{now.Year(), nextYear.Year()},
Months: utils.Months{now.Month(), nextMonth.Month()},
@@ -350,7 +350,7 @@ func TestActionPlanHourMonthdaysMonthYear(t *testing.T) {
func TestActionPlanFirstOfTheYear(t *testing.T) {
y, _, _ := now.Date()
nextYear := time.Date(y, 1, 1, 0, 0, 0, 0, time.Local).AddDate(1, 0, 0)
at := &ActionPlan{Timing: &RateInterval{
at := &ActionTiming{Timing: &RateInterval{
Timing: &RITiming{
Years: utils.Years{nextYear.Year()},
Months: utils.Months{time.January},
@@ -371,7 +371,7 @@ func TestActionPlanFirstMonthOfTheYear(t *testing.T) {
if referenceDate.After(expected) {
expected = expected.AddDate(1, 0, 0)
}
at := &ActionPlan{Timing: &RateInterval{
at := &ActionTiming{Timing: &RateInterval{
Timing: &RITiming{
Months: utils.Months{time.January},
},
@@ -388,7 +388,7 @@ func TestActionPlanFirstMonthOfTheYearSecondDay(t *testing.T) {
if referenceDate.After(expected) {
expected = expected.AddDate(1, 0, 0)
}
at := &ActionPlan{Timing: &RateInterval{
at := &ActionTiming{Timing: &RateInterval{
Timing: &RITiming{
Months: utils.Months{time.January},
MonthDays: utils.MonthDays{2},
@@ -401,7 +401,7 @@ func TestActionPlanFirstMonthOfTheYearSecondDay(t *testing.T) {
}
func TestActionPlanCheckForASAP(t *testing.T) {
at := &ActionPlan{Timing: &RateInterval{Timing: &RITiming{StartTime: utils.ASAP}}}
at := &ActionTiming{Timing: &RateInterval{Timing: &RITiming{StartTime: utils.ASAP}}}
if !at.IsASAP() {
t.Errorf("%v should be asap!", at)
}
@@ -413,7 +413,7 @@ func TestActionPlanLogFunction(t *testing.T) {
BalanceType: "test",
Balance: &Balance{Value: 1.1},
}
at := &ActionPlan{
at := &ActionTiming{
actions: []*Action{a},
}
err := at.Execute()
@@ -428,8 +428,8 @@ func TestActionPlanFunctionNotAvailable(t *testing.T) {
BalanceType: "test",
Balance: &Balance{Value: 1.1},
}
at := &ActionPlan{
AccountIds: []string{"cgrates.org:dy"},
at := &ActionTiming{
accountIDs: map[string]struct{}{"cgrates.org:dy": struct{}{}},
Timing: &RateInterval{},
actions: []*Action{a},
}
@@ -439,8 +439,8 @@ func TestActionPlanFunctionNotAvailable(t *testing.T) {
}
}
func TestActionPlanPriotityListSortByWeight(t *testing.T) {
at1 := &ActionPlan{Timing: &RateInterval{
func TestActionTimingPriorityListSortByWeight(t *testing.T) {
at1 := &ActionTiming{Timing: &RateInterval{
Timing: &RITiming{
Years: utils.Years{2020},
Months: utils.Months{time.January, time.February, time.March, time.April, time.May, time.June, time.July, time.August, time.September, time.October, time.November, time.December},
@@ -449,7 +449,7 @@ func TestActionPlanPriotityListSortByWeight(t *testing.T) {
},
Weight: 20,
}}
at2 := &ActionPlan{Timing: &RateInterval{
at2 := &ActionTiming{Timing: &RateInterval{
Timing: &RITiming{
Years: utils.Years{2020},
Months: utils.Months{time.January, time.February, time.March, time.April, time.May, time.June, time.July, time.August, time.September, time.October, time.November, time.December},
@@ -458,7 +458,7 @@ func TestActionPlanPriotityListSortByWeight(t *testing.T) {
},
Weight: 10,
}}
var atpl ActionPlanPriotityList
var atpl ActionTimingPriorityList
atpl = append(atpl, at2, at1)
atpl.Sort()
if atpl[0] != at1 || atpl[1] != at2 {
@@ -466,8 +466,8 @@ func TestActionPlanPriotityListSortByWeight(t *testing.T) {
}
}
func TestActionPlanPriotityListWeight(t *testing.T) {
at1 := &ActionPlan{
func TestActionTimingPriorityListWeight(t *testing.T) {
at1 := &ActionTiming{
Timing: &RateInterval{
Timing: &RITiming{
Months: utils.Months{time.January, time.February, time.March, time.April, time.May, time.June, time.July, time.August, time.September, time.October, time.November, time.December},
@@ -477,7 +477,7 @@ func TestActionPlanPriotityListWeight(t *testing.T) {
},
Weight: 20,
}
at2 := &ActionPlan{
at2 := &ActionTiming{
Timing: &RateInterval{
Timing: &RITiming{
Months: utils.Months{time.January, time.February, time.March, time.April, time.May, time.June, time.July, time.August, time.September, time.October, time.November, time.December},
@@ -487,7 +487,7 @@ func TestActionPlanPriotityListWeight(t *testing.T) {
},
Weight: 10,
}
var atpl ActionPlanPriotityList
var atpl ActionTimingPriorityList
atpl = append(atpl, at2, at1)
atpl.Sort()
if atpl[0] != at1 || atpl[1] != at2 {
@@ -495,17 +495,18 @@ func TestActionPlanPriotityListWeight(t *testing.T) {
}
}
/*
func TestActionPlansRemoveMember(t *testing.T) {
at1 := &ActionPlan{
Uuid: "some uuid",
Id: "test",
AccountIds: []string{"one", "two", "three"},
AccountIDs: []string{"one", "two", "three"},
ActionsId: "TEST_ACTIONS",
}
at2 := &ActionPlan{
Uuid: "some uuid22",
Id: "test2",
AccountIds: []string{"three", "four"},
AccountIDs: []string{"three", "four"},
ActionsId: "TEST_ACTIONS2",
}
ats := ActionPlans{at1, at2}
@@ -522,7 +523,7 @@ func TestActionPlansRemoveMember(t *testing.T) {
if ats2 = RemActionPlan(ats2, "", ""); len(ats2) != 0 {
t.Error("Should have no members anymore", ats2)
}
}
}*/
func TestActionTriggerMatchNil(t *testing.T) {
at := &ActionTrigger{
@@ -1056,10 +1057,8 @@ func TestActionPlanLogging(t *testing.T) {
Rates: RateGroups{&Rate{0, 1.0, 1 * time.Second, 60 * time.Second}},
},
}
at := &ActionPlan{
Uuid: "some uuid",
Id: "test",
AccountIds: []string{"one", "two", "three"},
at := &ActionTiming{
accountIDs: map[string]struct{}{"one": struct{}{}, "two": struct{}{}, "three": struct{}{}},
Timing: i,
Weight: 10.0,
ActionsId: "TEST_ACTIONS",
@@ -1068,7 +1067,7 @@ func TestActionPlanLogging(t *testing.T) {
if err != nil {
t.Error("Error getting actions for the action trigger: ", err)
}
storageLogger.LogActionPlan(utils.SCHED_SOURCE, at, as)
storageLogger.LogActionTiming(utils.SCHED_SOURCE, at, as)
//expected := "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|TEST_ACTIONS*|TOPUP|MONETARY|OUT|10|0"
var key string
atMap, _ := ratingStorage.GetAllActionPlans()
@@ -1104,8 +1103,8 @@ func TestRemoveAction(t *testing.T) {
ActionType: REMOVE_ACCOUNT,
}
at := &ActionPlan{
AccountIds: []string{"cgrates.org:remo"},
at := &ActionTiming{
accountIDs: map[string]struct{}{"cgrates.org:remo": struct{}{}},
actions: Actions{a},
}
at.Execute()
@@ -1123,8 +1122,8 @@ func TestTopupAction(t *testing.T) {
Balance: &Balance{Value: 25, DestinationIds: utils.NewStringMap("RET"), Directions: utils.NewStringMap(utils.OUT), Weight: 20},
}
at := &ActionPlan{
AccountIds: []string{"vdf:minu"},
at := &ActionTiming{
accountIDs: map[string]struct{}{"vdf:minu": struct{}{}},
actions: Actions{a},
}
@@ -1145,8 +1144,8 @@ func TestTopupActionLoaded(t *testing.T) {
Balance: &Balance{Value: 25, DestinationIds: utils.NewStringMap("RET"), Directions: utils.NewStringMap(utils.OUT), Weight: 20},
}
at := &ActionPlan{
AccountIds: []string{"vdf:minitsboy"},
at := &ActionTiming{
accountIDs: map[string]struct{}{"vdf:minitsboy": struct{}{}},
actions: Actions{a},
}
@@ -1297,8 +1296,8 @@ func TestActionTransactionFuncType(t *testing.T) {
if err != nil {
t.Error("Error setting account: ", err)
}
at := &ActionPlan{
AccountIds: []string{"cgrates.org:trans"},
at := &ActionTiming{
accountIDs: map[string]struct{}{"cgrates.org:trans": struct{}{}},
Timing: &RateInterval{},
actions: []*Action{
&Action{
@@ -1335,8 +1334,8 @@ func TestActionTransactionBalanceType(t *testing.T) {
if err != nil {
t.Error("Error setting account: ", err)
}
at := &ActionPlan{
AccountIds: []string{"cgrates.org:trans"},
at := &ActionTiming{
accountIDs: map[string]struct{}{"cgrates.org:trans": struct{}{}},
Timing: &RateInterval{},
actions: []*Action{
&Action{
@@ -1373,8 +1372,8 @@ func TestActionWithExpireWithoutExpire(t *testing.T) {
if err != nil {
t.Error("Error setting account: ", err)
}
at := &ActionPlan{
AccountIds: []string{"cgrates.org:exp"},
at := &ActionTiming{
accountIDs: map[string]struct{}{"cgrates.org:exp": struct{}{}},
Timing: &RateInterval{},
actions: []*Action{
&Action{
@@ -1428,8 +1427,8 @@ func TestActionRemoveBalance(t *testing.T) {
if err != nil {
t.Error("Error setting account: ", err)
}
at := &ActionPlan{
AccountIds: []string{"cgrates.org:rembal"},
at := &ActionTiming{
accountIDs: map[string]struct{}{"cgrates.org:rembal": struct{}{}},
Timing: &RateInterval{},
actions: []*Action{
&Action{

View File

@@ -487,8 +487,9 @@ func TestMaxSessionTimeWithAccount(t *testing.T) {
}
func TestMaxSessionTimeWithMaxRate(t *testing.T) {
ap, _ := ratingStorage.GetActionPlans("TOPUP10_AT", false)
for _, at := range ap {
ap, _ := ratingStorage.GetActionPlan("TOPUP10_AT", false)
for _, at := range ap.ActionTimings {
at.accountIDs = ap.AccountIDs
at.Execute()
}
//acc, _ := accountingStorage.GetAccount("cgrates.org:12345")
@@ -513,8 +514,9 @@ func TestMaxSessionTimeWithMaxRate(t *testing.T) {
}
func TestMaxSessionTimeWithMaxCost(t *testing.T) {
ap, _ := ratingStorage.GetActionPlans("TOPUP10_AT", false)
for _, at := range ap {
ap, _ := ratingStorage.GetActionPlan("TOPUP10_AT", false)
for _, at := range ap.ActionTimings {
at.accountIDs = ap.AccountIDs
at.Execute()
}
cd := &CallDescriptor{
@@ -536,8 +538,9 @@ func TestMaxSessionTimeWithMaxCost(t *testing.T) {
}
func TestGetCostWithMaxCost(t *testing.T) {
ap, _ := ratingStorage.GetActionPlans("TOPUP10_AT", false)
for _, at := range ap {
ap, _ := ratingStorage.GetActionPlan("TOPUP10_AT", false)
for _, at := range ap.ActionTimings {
at.accountIDs = ap.AccountIDs
at.Execute()
}
cd := &CallDescriptor{
@@ -558,8 +561,9 @@ func TestGetCostWithMaxCost(t *testing.T) {
}
}
func TestGetCostRoundingIssue(t *testing.T) {
ap, _ := ratingStorage.GetActionPlans("TOPUP10_AT", false)
for _, at := range ap {
ap, _ := ratingStorage.GetActionPlan("TOPUP10_AT", false)
for _, at := range ap.ActionTimings {
at.accountIDs = ap.AccountIDs
at.Execute()
}
cd := &CallDescriptor{
@@ -582,8 +586,9 @@ func TestGetCostRoundingIssue(t *testing.T) {
}
func TestGetCostRatingInfoOnZeroTime(t *testing.T) {
ap, _ := ratingStorage.GetActionPlans("TOPUP10_AT", false)
for _, at := range ap {
ap, _ := ratingStorage.GetActionPlan("TOPUP10_AT", false)
for _, at := range ap.ActionTimings {
at.accountIDs = ap.AccountIDs
at.Execute()
}
cd := &CallDescriptor{
@@ -609,8 +614,9 @@ func TestGetCostRatingInfoOnZeroTime(t *testing.T) {
}
func TestDebitRatingInfoOnZeroTime(t *testing.T) {
ap, _ := ratingStorage.GetActionPlans("TOPUP10_AT", false)
for _, at := range ap {
ap, _ := ratingStorage.GetActionPlan("TOPUP10_AT", false)
for _, at := range ap.ActionTimings {
at.accountIDs = ap.AccountIDs
at.Execute()
}
cd := &CallDescriptor{
@@ -637,8 +643,9 @@ func TestDebitRatingInfoOnZeroTime(t *testing.T) {
}
func TestMaxDebitRatingInfoOnZeroTime(t *testing.T) {
ap, _ := ratingStorage.GetActionPlans("TOPUP10_AT", false)
for _, at := range ap {
ap, _ := ratingStorage.GetActionPlan("TOPUP10_AT", false)
for _, at := range ap.ActionTimings {
at.accountIDs = ap.AccountIDs
at.Execute()
}
cd := &CallDescriptor{
@@ -664,8 +671,9 @@ func TestMaxDebitRatingInfoOnZeroTime(t *testing.T) {
}
func TestMaxDebitUnknowDest(t *testing.T) {
ap, _ := ratingStorage.GetActionPlans("TOPUP10_AT", false)
for _, at := range ap {
ap, _ := ratingStorage.GetActionPlan("TOPUP10_AT", false)
for _, at := range ap.ActionTimings {
at.accountIDs = ap.AccountIDs
at.Execute()
}
cd := &CallDescriptor{
@@ -686,8 +694,9 @@ func TestMaxDebitUnknowDest(t *testing.T) {
}
func TestGetCostMaxDebitRoundingIssue(t *testing.T) {
ap, _ := ratingStorage.GetActionPlans("TOPUP10_AT", false)
for _, at := range ap {
ap, _ := ratingStorage.GetActionPlan("TOPUP10_AT", false)
for _, at := range ap.ActionTimings {
at.accountIDs = ap.AccountIDs
at.Execute()
}
cd := &CallDescriptor{
@@ -718,8 +727,9 @@ func TestGetCostMaxDebitRoundingIssue(t *testing.T) {
}
func TestMaxSessionTimeWithMaxCostFree(t *testing.T) {
ap, _ := ratingStorage.GetActionPlans("TOPUP10_AT", false)
for _, at := range ap {
ap, _ := ratingStorage.GetActionPlan("TOPUP10_AT", false)
for _, at := range ap.ActionTimings {
at.accountIDs = ap.AccountIDs
at.Execute()
}
cd := &CallDescriptor{
@@ -741,8 +751,9 @@ func TestMaxSessionTimeWithMaxCostFree(t *testing.T) {
}
func TestMaxDebitWithMaxCostFree(t *testing.T) {
ap, _ := ratingStorage.GetActionPlans("TOPUP10_AT", false)
for _, at := range ap {
ap, _ := ratingStorage.GetActionPlan("TOPUP10_AT", false)
for _, at := range ap.ActionTimings {
at.accountIDs = ap.AccountIDs
at.Execute()
}
cd := &CallDescriptor{
@@ -764,8 +775,9 @@ func TestMaxDebitWithMaxCostFree(t *testing.T) {
}
func TestGetCostWithMaxCostFree(t *testing.T) {
ap, _ := ratingStorage.GetActionPlans("TOPUP10_AT", false)
for _, at := range ap {
ap, _ := ratingStorage.GetActionPlan("TOPUP10_AT", false)
for _, at := range ap.ActionTimings {
at.accountIDs = ap.AccountIDs
at.Execute()
}
cd := &CallDescriptor{
@@ -818,12 +830,14 @@ func TestMaxSessionTimeWithAccountAlias(t *testing.T) {
}
func TestMaxSessionTimeWithAccountShared(t *testing.T) {
ap, _ := ratingStorage.GetActionPlans("TOPUP_SHARED0_AT", false)
for _, at := range ap {
ap, _ := ratingStorage.GetActionPlan("TOPUP_SHARED0_AT", false)
for _, at := range ap.ActionTimings {
at.accountIDs = ap.AccountIDs
at.Execute()
}
ap, _ = ratingStorage.GetActionPlans("TOPUP_SHARED10_AT", false)
for _, at := range ap {
ap, _ = ratingStorage.GetActionPlan("TOPUP_SHARED10_AT", false)
for _, at := range ap.ActionTimings {
at.accountIDs = ap.AccountIDs
at.Execute()
}
@@ -857,12 +871,14 @@ func TestMaxSessionTimeWithAccountShared(t *testing.T) {
}
func TestMaxDebitWithAccountShared(t *testing.T) {
ap, _ := ratingStorage.GetActionPlans("TOPUP_SHARED0_AT", false)
for _, at := range ap {
ap, _ := ratingStorage.GetActionPlan("TOPUP_SHARED0_AT", false)
for _, at := range ap.ActionTimings {
at.accountIDs = ap.AccountIDs
at.Execute()
}
ap, _ = ratingStorage.GetActionPlans("TOPUP_SHARED10_AT", false)
for _, at := range ap {
ap, _ = ratingStorage.GetActionPlan("TOPUP_SHARED10_AT", false)
for _, at := range ap.ActionTimings {
at.accountIDs = ap.AccountIDs
at.Execute()
}
@@ -1077,8 +1093,9 @@ func TestMaxSesionTimeLongerThanMoney(t *testing.T) {
}
func TestDebitFromShareAndNormal(t *testing.T) {
ap, _ := ratingStorage.GetActionPlans("TOPUP_SHARED10_AT", false)
for _, at := range ap {
ap, _ := ratingStorage.GetActionPlan("TOPUP_SHARED10_AT", false)
for _, at := range ap.ActionTimings {
at.accountIDs = ap.AccountIDs
at.Execute()
}
@@ -1105,8 +1122,9 @@ func TestDebitFromShareAndNormal(t *testing.T) {
}
func TestDebitFromEmptyShare(t *testing.T) {
ap, _ := ratingStorage.GetActionPlans("TOPUP_EMPTY_AT", false)
for _, at := range ap {
ap, _ := ratingStorage.GetActionPlan("TOPUP_EMPTY_AT", false)
for _, at := range ap.ActionTimings {
at.accountIDs = ap.AccountIDs
at.Execute()
}
@@ -1133,8 +1151,9 @@ func TestDebitFromEmptyShare(t *testing.T) {
}
func TestDebitNegatve(t *testing.T) {
ap, _ := ratingStorage.GetActionPlans("POST_AT", false)
for _, at := range ap {
ap, _ := ratingStorage.GetActionPlan("POST_AT", false)
for _, at := range ap.ActionTimings {
at.accountIDs = ap.AccountIDs
at.Execute()
}
@@ -1172,8 +1191,9 @@ func TestDebitNegatve(t *testing.T) {
}
func TestMaxDebitZeroDefinedRate(t *testing.T) {
ap, _ := ratingStorage.GetActionPlans("TOPUP10_AT", false)
for _, at := range ap {
ap, _ := ratingStorage.GetActionPlan("TOPUP10_AT", false)
for _, at := range ap.ActionTimings {
at.accountIDs = ap.AccountIDs
at.Execute()
}
cd1 := &CallDescriptor{
@@ -1200,8 +1220,9 @@ func TestMaxDebitZeroDefinedRate(t *testing.T) {
}
func TestMaxDebitZeroDefinedRateOnlyMinutes(t *testing.T) {
ap, _ := ratingStorage.GetActionPlans("TOPUP10_AT", false)
for _, at := range ap {
ap, _ := ratingStorage.GetActionPlan("TOPUP10_AT", false)
for _, at := range ap.ActionTimings {
at.accountIDs = ap.AccountIDs
at.Execute()
}
cd1 := &CallDescriptor{
@@ -1228,8 +1249,9 @@ func TestMaxDebitZeroDefinedRateOnlyMinutes(t *testing.T) {
}
func TestMaxDebitConsumesMinutes(t *testing.T) {
ap, _ := ratingStorage.GetActionPlans("TOPUP10_AT", false)
for _, at := range ap {
ap, _ := ratingStorage.GetActionPlan("TOPUP10_AT", false)
for _, at := range ap.ActionTimings {
at.accountIDs = ap.AccountIDs
at.Execute()
}
cd1 := &CallDescriptor{

View File

@@ -985,25 +985,42 @@ func TestLoadActionTimings(t *testing.T) {
if len(csvr.actionPlans) != 6 {
t.Error("Failed to load action timings: ", len(csvr.actionPlans))
}
atm := csvr.actionPlans["MORE_MINUTES"][0]
atm := csvr.actionPlans["MORE_MINUTES"]
expected := &ActionPlan{
Uuid: atm.Uuid,
Id: "MORE_MINUTES",
AccountIds: []string{"vdf:minitsboy"},
Timing: &RateInterval{
Timing: &RITiming{
Years: utils.Years{2012},
Months: utils.Months{},
MonthDays: utils.MonthDays{},
WeekDays: utils.WeekDays{},
StartTime: utils.ASAP,
AccountIDs: map[string]struct{}{"vdf:minitsboy": struct{}{}},
ActionTimings: []*ActionTiming{
&ActionTiming{
Timing: &RateInterval{
Timing: &RITiming{
Years: utils.Years{2012},
Months: utils.Months{},
MonthDays: utils.MonthDays{},
WeekDays: utils.WeekDays{},
StartTime: utils.ASAP,
},
},
Weight: 10,
ActionsId: "MINI",
},
&ActionTiming{
Timing: &RateInterval{
Timing: &RITiming{
Years: utils.Years{2012},
Months: utils.Months{},
MonthDays: utils.MonthDays{},
WeekDays: utils.WeekDays{},
StartTime: utils.ASAP,
},
},
Weight: 10,
ActionsId: "SHARED",
},
},
Weight: 10,
ActionsId: "MINI",
}
if !reflect.DeepEqual(atm, expected) {
t.Errorf("Error loading action timing:\n%+v", atm)
t.Errorf("Error loading action timing:\n%+v", atm.ActionTimings[1].Timing)
}
}

View File

@@ -63,9 +63,9 @@ type RatingStorage interface {
SetSharedGroup(*SharedGroup) error
GetActionTriggers(string) (ActionTriggers, error)
SetActionTriggers(string, ActionTriggers) error
GetActionPlans(string, bool) (ActionPlans, error)
SetActionPlans(string, ActionPlans) error
GetAllActionPlans() (map[string]ActionPlans, error)
GetActionPlan(string, bool) (*ActionPlan, error)
SetActionPlan(string, *ActionPlan) error
GetAllActionPlans() (map[string]*ActionPlan, error)
}
type AccountingStorage interface {
@@ -106,7 +106,7 @@ type LogStorage interface {
Storage
//GetAllActionTimingsLogs() (map[string]ActionsTimings, error)
LogActionTrigger(ubId, source string, at *ActionTrigger, as Actions) error
LogActionPlan(source string, at *ActionPlan, as Actions) error
LogActionTiming(source string, at *ActionTiming, as Actions) error
}
type LoadStorage interface {

View File

@@ -178,7 +178,7 @@ func (ms *MapStorage) cacheRating(dKeys, rpKeys, rpfKeys, lcrKeys, dcsKeys, actK
}
if strings.HasPrefix(k, utils.ACTION_PLAN_PREFIX) {
cache2go.RemKey(k)
if _, err := ms.GetActionPlans(k[len(utils.ACTION_PLAN_PREFIX):], true); err != nil {
if _, err := ms.GetActionPlan(k[len(utils.ACTION_PLAN_PREFIX):], true); err != nil {
cache2go.RollbackTransaction()
return err
}
@@ -645,11 +645,11 @@ func (ms *MapStorage) SetActionTriggers(key string, atrs ActionTriggers) (err er
return
}
func (ms *MapStorage) GetActionPlans(key string, skipCache bool) (ats ActionPlans, err error) {
func (ms *MapStorage) GetActionPlan(key string, skipCache bool) (ats *ActionPlan, err error) {
key = utils.ACTION_PLAN_PREFIX + key
if !skipCache {
if x, err := cache2go.Get(key); err == nil {
return x.(ActionPlans), nil
return x.(*ActionPlan), nil
} else {
return nil, err
}
@@ -663,8 +663,8 @@ func (ms *MapStorage) GetActionPlans(key string, skipCache bool) (ats ActionPlan
return
}
func (ms *MapStorage) SetActionPlans(key string, ats ActionPlans) (err error) {
if len(ats) == 0 {
func (ms *MapStorage) SetActionPlan(key string, ats *ActionPlan) (err error) {
if len(ats.ActionTimings) == 0 {
// delete the key
delete(ms.dict, utils.ACTION_PLAN_PREFIX+key)
cache2go.RemKey(utils.ACTION_PLAN_PREFIX + key)
@@ -675,15 +675,15 @@ func (ms *MapStorage) SetActionPlans(key string, ats ActionPlans) (err error) {
return
}
func (ms *MapStorage) GetAllActionPlans() (ats map[string]ActionPlans, err error) {
func (ms *MapStorage) GetAllActionPlans() (ats map[string]*ActionPlan, err error) {
apls, err := cache2go.GetAllEntries(utils.ACTION_PLAN_PREFIX)
if err != nil {
return nil, err
}
ats = make(map[string]ActionPlans, len(apls))
ats = make(map[string]*ActionPlan, len(apls))
for key, value := range apls {
apl := value.(ActionPlans)
apl := value.(*ActionPlan)
ats[key] = apl
}
@@ -774,7 +774,7 @@ func (ms *MapStorage) LogActionTrigger(ubId, source string, at *ActionTrigger, a
return
}
func (ms *MapStorage) LogActionPlan(source string, at *ActionPlan, as Actions) (err error) {
func (ms *MapStorage) LogActionTiming(source string, at *ActionTiming, as Actions) (err error) {
mat, err := ms.ms.Marshal(at)
if err != nil {
return

View File

@@ -451,7 +451,7 @@ func (ms *MongoStorage) cacheRating(dKeys, rpKeys, rpfKeys, lcrKeys, dcsKeys, ac
}
for _, key := range aplKeys {
cache2go.RemKey(key)
if _, err = ms.GetActionPlans(key[len(utils.ACTION_PLAN_PREFIX):], true); err != nil {
if _, err = ms.GetActionPlan(key[len(utils.ACTION_PLAN_PREFIX):], true); err != nil {
cache2go.RollbackTransaction()
return err
}
@@ -1026,17 +1026,17 @@ func (ms *MongoStorage) SetActionTriggers(key string, atrs ActionTriggers) (err
return err
}
func (ms *MongoStorage) GetActionPlans(key string, skipCache bool) (ats ActionPlans, err error) {
func (ms *MongoStorage) GetActionPlan(key string, skipCache bool) (ats *ActionPlan, err error) {
if !skipCache {
if x, err := cache2go.Get(utils.ACTION_PLAN_PREFIX + key); err == nil {
return x.(ActionPlans), nil
return x.(*ActionPlan), nil
} else {
return nil, err
}
}
var kv struct {
Key string
Value ActionPlans
Value *ActionPlan
}
err = ms.db.C(colApl).Find(bson.M{"key": key}).One(&kv)
if err == nil {
@@ -1046,8 +1046,8 @@ func (ms *MongoStorage) GetActionPlans(key string, skipCache bool) (ats ActionPl
return
}
func (ms *MongoStorage) SetActionPlans(key string, ats ActionPlans) error {
if len(ats) == 0 {
func (ms *MongoStorage) SetActionPlan(key string, ats *ActionPlan) error {
if len(ats.ActionTimings) == 0 {
cache2go.RemKey(utils.ACTION_PLAN_PREFIX + key)
err := ms.db.C(colApl).Remove(bson.M{"key": key})
if err != mgo.ErrNotFound {
@@ -1057,20 +1057,20 @@ func (ms *MongoStorage) SetActionPlans(key string, ats ActionPlans) error {
}
_, err := ms.db.C(colApl).Upsert(bson.M{"key": key}, &struct {
Key string
Value ActionPlans
Value *ActionPlan
}{Key: key, Value: ats})
return err
}
func (ms *MongoStorage) GetAllActionPlans() (ats map[string]ActionPlans, err error) {
func (ms *MongoStorage) GetAllActionPlans() (ats map[string]*ActionPlan, err error) {
apls, err := cache2go.GetAllEntries(utils.ACTION_PLAN_PREFIX)
if err != nil {
return nil, err
}
ats = make(map[string]ActionPlans, len(apls))
ats = make(map[string]*ActionPlan, len(apls))
for key, value := range apls {
apl := value.(ActionPlans)
apl := value.(*ActionPlan)
ats[key] = apl
}

View File

@@ -689,9 +689,9 @@ func (ms *MongoStorage) LogActionTrigger(ubId, source string, at *ActionTrigger,
}{ubId, at, as, time.Now(), source})
}
func (ms *MongoStorage) LogActionPlan(source string, at *ActionPlan, as Actions) (err error) {
func (ms *MongoStorage) LogActionTiming(source string, at *ActionTiming, as Actions) (err error) {
return ms.db.C(colLogApl).Insert(&struct {
ActionPlan *ActionPlan
ActionPlan *ActionTiming
Actions Actions
LogTime time.Time
Source string

View File

@@ -282,7 +282,7 @@ func (rs *RedisStorage) cacheRating(dKeys, rpKeys, rpfKeys, lcrKeys, dcsKeys, ac
}
for _, key := range aplKeys {
cache2go.RemKey(key)
if _, err = rs.GetActionPlans(key[len(utils.ACTION_PLAN_PREFIX):], true); err != nil {
if _, err = rs.GetActionPlan(key[len(utils.ACTION_PLAN_PREFIX):], true); err != nil {
cache2go.RollbackTransaction()
return err
}
@@ -893,11 +893,11 @@ func (rs *RedisStorage) SetActionTriggers(key string, atrs ActionTriggers) (err
return conn.Cmd("SET", utils.ACTION_TRIGGER_PREFIX+key, result).Err
}
func (rs *RedisStorage) GetActionPlans(key string, skipCache bool) (ats ActionPlans, err error) {
func (rs *RedisStorage) GetActionPlan(key string, skipCache bool) (ats *ActionPlan, err error) {
key = utils.ACTION_PLAN_PREFIX + key
if !skipCache {
if x, err := cache2go.Get(key); err == nil {
return x.(ActionPlans), nil
return x.(*ActionPlan), nil
} else {
return nil, err
}
@@ -911,8 +911,8 @@ func (rs *RedisStorage) GetActionPlans(key string, skipCache bool) (ats ActionPl
return
}
func (rs *RedisStorage) SetActionPlans(key string, ats ActionPlans) (err error) {
if len(ats) == 0 {
func (rs *RedisStorage) SetActionPlan(key string, ats *ActionPlan) (err error) {
if len(ats.ActionTimings) == 0 {
// delete the key
err = rs.db.Cmd("DEL", utils.ACTION_PLAN_PREFIX+key).Err
cache2go.RemKey(utils.ACTION_PLAN_PREFIX + key)
@@ -925,15 +925,15 @@ func (rs *RedisStorage) SetActionPlans(key string, ats ActionPlans) (err error)
return rs.db.Cmd("SET", utils.ACTION_PLAN_PREFIX+key, result).Err
}
func (rs *RedisStorage) GetAllActionPlans() (ats map[string]ActionPlans, err error) {
func (rs *RedisStorage) GetAllActionPlans() (ats map[string]*ActionPlan, err error) {
apls, err := cache2go.GetAllEntries(utils.ACTION_PLAN_PREFIX)
if err != nil {
return nil, err
}
ats = make(map[string]ActionPlans, len(apls))
ats = make(map[string]*ActionPlan, len(apls))
for key, value := range apls {
apl := value.(ActionPlans)
apl := value.(*ActionPlan)
ats[key] = apl
}

View File

@@ -592,7 +592,7 @@ func (self *SQLStorage) GetCallCostLog(cgrid, source, runid string) (*CallCost,
func (self *SQLStorage) LogActionTrigger(ubId, source string, at *ActionTrigger, as Actions) (err error) {
return
}
func (self *SQLStorage) LogActionPlan(source string, at *ActionPlan, as Actions) (err error) {
func (self *SQLStorage) LogActionTiming(source string, at *ActionTiming, as Actions) (err error) {
return
}

View File

@@ -19,7 +19,7 @@ type TpReader struct {
accountingStorage AccountingStorage
lr LoadReader
actions map[string][]*Action
actionPlans map[string][]*ActionPlan
actionPlans map[string]*ActionPlan
actionsTriggers map[string]ActionTriggers
accountActions map[string]*Account
dirtyRpAliases []*TenantRatingSubject // used to clean aliases that might have changed
@@ -73,7 +73,7 @@ func NewTpReader(rs RatingStorage, as AccountingStorage, lr LoadReader, tpid, ti
func (tpr *TpReader) Init() {
tpr.actions = make(map[string][]*Action)
tpr.actionPlans = make(map[string][]*ActionPlan)
tpr.actionPlans = make(map[string]*ActionPlan)
tpr.actionsTriggers = make(map[string]ActionTriggers)
tpr.rates = make(map[string]*utils.TPRate)
tpr.destinations = make(map[string]*Destination)
@@ -575,9 +575,14 @@ func (tpr *TpReader) LoadActionPlans() (err error) {
if !exists {
return fmt.Errorf("[ActionPlans] Could not load the timing for tag: %v", at.TimingId)
}
actPln := &ActionPlan{
Uuid: utils.GenUUID(),
Id: atId,
var actPln *ActionPlan
if actPln, exists = tpr.actionPlans[atId]; !exists {
actPln = &ActionPlan{
Uuid: utils.GenUUID(),
Id: atId,
}
}
actPln.ActionTimings = append(actPln.ActionTimings, &ActionTiming{
Weight: at.Weight,
Timing: &RateInterval{
Timing: &RITiming{
@@ -589,8 +594,9 @@ func (tpr *TpReader) LoadActionPlans() (err error) {
},
},
ActionsId: at.ActionsId,
}
tpr.actionPlans[atId] = append(tpr.actionPlans[atId], actPln)
})
tpr.actionPlans[atId] = actPln
}
}
@@ -660,11 +666,10 @@ func (tpr *TpReader) LoadAccountActionsFiltered(qriedAA *TpAccountAction) error
// action timings
if accountAction.ActionPlanId != "" {
// get old userBalanceIds
var exitingAccountIds []string
existingActionPlans, err := tpr.ratingStorage.GetActionPlans(accountAction.ActionPlanId, true)
if err == nil && len(existingActionPlans) > 0 {
// all action timings from a specific tag shuld have the same list of user balances from the first one
exitingAccountIds = existingActionPlans[0].AccountIds
var exitingAccountIds map[string]struct{}
existingActionPlan, err := tpr.ratingStorage.GetActionPlan(accountAction.ActionPlanId, true)
if err == nil && existingActionPlan != nil {
exitingAccountIds = existingActionPlan.AccountIDs
}
tpap, err := tpr.lr.GetTpActionPlans(tpr.tpid, accountAction.ActionPlanId)
@@ -677,7 +682,7 @@ func (tpr *TpReader) LoadAccountActionsFiltered(qriedAA *TpAccountAction) error
if err != nil {
return err
}
var actionTimings []*ActionPlan
var actionPlan *ActionPlan
ats := aps[accountAction.ActionPlanId]
for _, at := range ats {
// Check action exists before saving it inside actionTiming key
@@ -703,9 +708,13 @@ func (tpr *TpReader) LoadAccountActionsFiltered(qriedAA *TpAccountAction) error
} else {
t = tpr.timings[at.TimingId] // *asap
}
actPln := &ActionPlan{
Uuid: utils.GenUUID(),
Id: accountAction.ActionPlanId,
if actionPlan == nil {
actionPlan = &ActionPlan{
Uuid: utils.GenUUID(),
Id: accountAction.ActionPlanId,
}
}
actionPlan.ActionTimings = append(actionPlan.ActionTimings, &ActionTiming{
Weight: at.Weight,
Timing: &RateInterval{
Timing: &RITiming{
@@ -716,25 +725,15 @@ func (tpr *TpReader) LoadAccountActionsFiltered(qriedAA *TpAccountAction) error
},
},
ActionsId: at.ActionsId,
}
})
// collect action ids from timings
actionsIds = append(actionsIds, actPln.ActionsId)
//add user balance id if no already in
found := false
for _, ubId := range exitingAccountIds {
if ubId == id {
found = true
break
}
}
if !found {
actPln.AccountIds = append(exitingAccountIds, id)
}
actionTimings = append(actionTimings, actPln)
actionsIds = append(actionsIds, at.ActionsId)
exitingAccountIds[id] = struct{}{}
actionPlan.AccountIDs = exitingAccountIds
}
// write action triggers
err = tpr.ratingStorage.SetActionPlans(accountAction.ActionPlanId, actionTimings)
// write action plan
err = tpr.ratingStorage.SetActionPlan(accountAction.ActionPlanId, actionPlan)
if err != nil {
return errors.New(err.Error() + " (SetActionPlan): " + accountAction.ActionPlanId)
}
@@ -883,14 +882,15 @@ func (tpr *TpReader) LoadAccountActions() (err error) {
}
ub.InitCounters()
tpr.accountActions[aa.KeyId()] = ub
aTimings, exists := tpr.actionPlans[aa.ActionPlanId]
actionPlan, exists := tpr.actionPlans[aa.ActionPlanId]
if !exists {
log.Printf("could not get action plan for tag %v", aa.ActionPlanId)
// must not continue here
}
for _, at := range aTimings {
at.AccountIds = append(at.AccountIds, aa.KeyId())
if actionPlan.AccountIDs == nil {
actionPlan.AccountIDs = make(map[string]struct{})
}
actionPlan.AccountIDs[aa.KeyId()] = struct{}{}
}
return nil
}
@@ -1319,7 +1319,7 @@ func (tpr *TpReader) WriteToDatabase(flush, verbose bool) (err error) {
log.Print("Action Plans:")
}
for k, ats := range tpr.actionPlans {
err = tpr.ratingStorage.SetActionPlans(k, ats)
err = tpr.ratingStorage.SetActionPlan(k, ats)
if err != nil {
return err
}