keep counter value on re-init

This commit is contained in:
Radu Ioan Fericean
2016-02-02 22:14:30 +02:00
parent b8e2d3141a
commit 060a901a6a
4 changed files with 134 additions and 23 deletions

View File

@@ -569,9 +569,9 @@ func (ub *Account) refundIncrement(increment *Increment, cd *CallDescriptor, cou
}
// Scans the action trigers and execute the actions for which trigger is met
func (ub *Account) ExecuteActionTriggers(a *Action) {
ub.ActionTriggers.Sort()
for _, at := range ub.ActionTriggers {
func (acc *Account) ExecuteActionTriggers(a *Action) {
acc.ActionTriggers.Sort()
for _, at := range acc.ActionTriggers {
// sanity check
if !strings.Contains(at.ThresholdType, "counter") && !strings.Contains(at.ThresholdType, "balance") {
continue
@@ -585,45 +585,45 @@ func (ub *Account) ExecuteActionTriggers(a *Action) {
continue
}
if strings.Contains(at.ThresholdType, "counter") {
for _, uc := range ub.UnitCounters {
for _, uc := range acc.UnitCounters {
if uc.BalanceType == at.BalanceType &&
strings.Contains(at.ThresholdType, uc.CounterType[1:]) {
for _, mb := range uc.Balances {
for _, b := range uc.Balances {
if strings.HasPrefix(at.ThresholdType, "*max") {
if mb.MatchActionTrigger(at) && mb.GetValue() >= at.ThresholdValue {
at.Execute(ub, nil)
if b.MatchActionTrigger(at) && b.GetValue() >= at.ThresholdValue {
at.Execute(acc, nil)
}
} else { //MIN
if mb.MatchActionTrigger(at) && mb.GetValue() <= at.ThresholdValue {
at.Execute(ub, nil)
if b.MatchActionTrigger(at) && b.GetValue() <= at.ThresholdValue {
at.Execute(acc, nil)
}
}
}
}
}
} else { // BALANCE
for _, b := range ub.BalanceMap[at.BalanceType] {
for _, b := range acc.BalanceMap[at.BalanceType] {
if !b.dirty && at.ThresholdType != utils.TRIGGER_BALANCE_EXPIRED { // do not check clean balances
continue
}
switch at.ThresholdType {
case utils.TRIGGER_MAX_BALANCE:
if b.MatchActionTrigger(at) && b.GetValue() >= at.ThresholdValue {
at.Execute(ub, nil)
at.Execute(acc, nil)
}
case utils.TRIGGER_MIN_BALANCE:
if b.MatchActionTrigger(at) && b.GetValue() <= at.ThresholdValue {
at.Execute(ub, nil)
at.Execute(acc, nil)
}
case utils.TRIGGER_BALANCE_EXPIRED:
if b.MatchActionTrigger(at) && b.IsExpired() {
at.Execute(ub, nil)
at.Execute(acc, nil)
}
}
}
}
}
ub.CleanExpiredBalances()
acc.CleanExpiredBalances()
}
// Mark all action trigers as ready for execution
@@ -656,6 +656,7 @@ func (acc *Account) countUnits(amount float64, kind string, cc *CallCost, b *Bal
// Create counters for all triggered actions
func (acc *Account) InitCounters() {
oldUcs := acc.UnitCounters
acc.UnitCounters = nil
ucTempMap := make(map[string]*UnitCounter)
for _, at := range acc.ActionTriggers {
@@ -682,6 +683,14 @@ func (acc *Account) InitCounters() {
uc.Balances = append(uc.Balances, b)
}
}
// copy old counter values
for _, uc := range acc.UnitCounters {
for _, oldUc := range oldUcs {
if uc.CopyCounterValues(oldUc) {
break
}
}
}
}
func (acc *Account) CleanExpiredBalances() {

View File

@@ -553,14 +553,14 @@ func removeAccountAction(ub *Account, sq *StatsQueueTriggered, a *Action, acs Ac
utils.Logger.Err(fmt.Sprintf("Could not remove account Id: %s: %v", accID, err))
return err
}
// clean the account id from all action plans
allAPs, err := ratingStorage.GetAllActionPlans()
if err != nil && err != utils.ErrNotFound {
utils.Logger.Err(fmt.Sprintf("Could not get action plans: %s: %v", accID, err))
return err
}
var dirtyAps []string
_, err = Guardian.Guard(func() (interface{}, error) {
_, err := Guardian.Guard(func() (interface{}, error) {
// clean the account id from all action plans
allAPs, err := ratingStorage.GetAllActionPlans()
if err != nil && err != utils.ErrNotFound {
utils.Logger.Err(fmt.Sprintf("Could not get action plans: %s: %v", accID, err))
return 0, err
}
var dirtyAps []string
for key, ap := range allAPs {
if _, exists := ap.AccountIDs[accID]; !exists {
// save action plan
@@ -580,7 +580,6 @@ func removeAccountAction(ub *Account, sq *StatsQueueTriggered, a *Action, acs Ac
if err != nil {
return err
}
// TODO: no scheduler reload?
return nil
}

View File

@@ -27,6 +27,23 @@ type UnitCounter struct {
Balances BalanceChain // first balance is the general one (no destination)
}
// Returns true if the counters were of the same type
// Copies the value from old balances
func (uc *UnitCounter) CopyCounterValues(oldUc *UnitCounter) bool {
if uc.BalanceType+uc.CounterType != oldUc.BalanceType+oldUc.CounterType { // type check
return false
}
for _, b := range uc.Balances {
for _, oldB := range oldUc.Balances {
if b.Equal(oldB) {
b.Value = oldB.Value
break
}
}
}
return true
}
type UnitCounters []*UnitCounter
func (ucs UnitCounters) addUnits(amount float64, kind string, cc *CallCost, b *Balance) {

View File

@@ -246,6 +246,92 @@ func TestUnitCountersCountAllVoiceDestinationEvent(t *testing.T) {
}
}
func TestUnitCountersKeepValuesAfterInit(t *testing.T) {
a := &Account{
ActionTriggers: ActionTriggers{
&ActionTrigger{
UniqueID: "TestTR1",
ThresholdType: utils.TRIGGER_MAX_BALANCE_COUNTER,
BalanceType: utils.MONETARY,
BalanceDirections: utils.NewStringMap(utils.OUT),
BalanceWeight: 10,
},
&ActionTrigger{
UniqueID: "TestTR11",
ThresholdType: utils.TRIGGER_MAX_BALANCE_COUNTER,
BalanceType: utils.MONETARY,
BalanceDirections: utils.NewStringMap(utils.OUT),
BalanceWeight: 20,
},
&ActionTrigger{
UniqueID: "TestTR2",
ThresholdType: utils.TRIGGER_MAX_EVENT_COUNTER,
BalanceType: utils.VOICE,
BalanceDirections: utils.NewStringMap(utils.OUT),
BalanceDestinationIds: utils.NewStringMap("NAT"),
BalanceWeight: 10,
},
&ActionTrigger{
UniqueID: "TestTR22",
ThresholdType: utils.TRIGGER_MAX_EVENT_COUNTER,
BalanceType: utils.VOICE,
BalanceDestinationIds: utils.NewStringMap("RET"),
BalanceWeight: 10,
},
&ActionTrigger{
UniqueID: "TestTR3",
ThresholdType: utils.TRIGGER_MAX_BALANCE_COUNTER,
BalanceType: utils.VOICE,
BalanceDirections: utils.NewStringMap(utils.OUT),
BalanceWeight: 10,
},
&ActionTrigger{
UniqueID: "TestTR4",
ThresholdType: utils.TRIGGER_MAX_BALANCE_COUNTER,
BalanceType: utils.SMS,
BalanceDirections: utils.NewStringMap(utils.OUT),
BalanceWeight: 10,
},
&ActionTrigger{
UniqueID: "TestTR5",
ThresholdType: utils.TRIGGER_MAX_BALANCE,
BalanceType: utils.SMS,
BalanceDirections: utils.NewStringMap(utils.OUT),
BalanceWeight: 10,
},
},
}
a.InitCounters()
a.UnitCounters.addUnits(10, utils.VOICE, &CallCost{Destination: "0723045326"}, nil)
if len(a.UnitCounters) != 4 ||
len(a.UnitCounters[1].Balances) != 2 ||
a.UnitCounters[1].Balances[0].Value != 10 ||
a.UnitCounters[1].Balances[1].Value != 10 {
for _, uc := range a.UnitCounters {
t.Logf("UC: %+v", uc)
for _, b := range uc.Balances {
t.Logf("B: %+v", b)
}
}
t.Errorf("Error adding unit counters: %v", len(a.UnitCounters))
}
a.InitCounters()
if len(a.UnitCounters) != 4 ||
len(a.UnitCounters[1].Balances) != 2 ||
a.UnitCounters[1].Balances[0].Value != 10 ||
a.UnitCounters[1].Balances[1].Value != 10 {
for _, uc := range a.UnitCounters {
t.Logf("UC: %+v", uc)
for _, b := range uc.Balances {
t.Logf("B: %+v", b)
}
}
t.Errorf("Error keeping counter values after init: %v", len(a.UnitCounters))
}
}
func TestUnitCountersResetCounterById(t *testing.T) {
a := &Account{
ActionTriggers: ActionTriggers{