mirror of
https://github.com/cgrates/cgrates.git
synced 2026-02-11 18:16:24 +05:00
added passing events from thresholds to ees
This commit is contained in:
committed by
Dan Christian Bogos
parent
90de059801
commit
ccdf3ef1f1
@@ -245,8 +245,8 @@ cgrates.org,Ranking1,@every 5m,Stats2;Stats3;Stats4,Metric1;Metric3,*asc,,true,T
|
||||
cgrates.org,TREND1,0 12 * * *,Stats2,*acc;*tcc,-1,-1,1,*average,2.1,true,TD1;TD2
|
||||
`
|
||||
ThresholdsCSVContent = `
|
||||
#Tenant[0],Id[1],FilterIDs[2],ActivationInterval[3],MaxHits[4],MinHits[5],MinSleep[6],Blocker[7],Weight[8],ActionIDs[9],Async[10]
|
||||
cgrates.org,Threshold1,*string:~*req.Account:1001;*string:~*req.RunID:*default,2014-07-29T15:00:00Z,12,10,1s,true,10,THRESH1,true
|
||||
#Tenant[0],Id[1],FilterIDs[2],ActivationInterval[3],MaxHits[4],MinHits[5],MinSleep[6],Blocker[7],Weight[8],ActionIDs[9],Async[10],EeIDs[11]
|
||||
cgrates.org,Threshold1,*string:~*req.Account:1001;*string:~*req.RunID:*default,2014-07-29T15:00:00Z,12,10,1s,true,10,THRESH1,true,
|
||||
`
|
||||
|
||||
FiltersCSVContent = `
|
||||
|
||||
@@ -1813,13 +1813,14 @@ type ThresholdMdls []*ThresholdMdl
|
||||
func (tps ThresholdMdls) CSVHeader() (result []string) {
|
||||
return []string{"#" + utils.Tenant, utils.ID, utils.FilterIDs, utils.ActivationIntervalString,
|
||||
utils.MaxHits, utils.MinHits, utils.MinSleep,
|
||||
utils.Blocker, utils.Weight, utils.ActionIDs, utils.Async}
|
||||
utils.Blocker, utils.Weight, utils.ActionIDs, utils.Async, utils.EeIDs}
|
||||
}
|
||||
|
||||
func (tps ThresholdMdls) AsTPThreshold() (result []*utils.TPThresholdProfile) {
|
||||
mst := make(map[string]*utils.TPThresholdProfile)
|
||||
filterMap := make(map[string]utils.StringSet)
|
||||
actionMap := make(map[string]utils.StringSet)
|
||||
eeIDsMap := make(map[string]utils.StringSet)
|
||||
for _, tp := range tps {
|
||||
tenID := (&utils.TenantID{Tenant: tp.Tenant, ID: tp.ID}).TenantID()
|
||||
th, found := mst[tenID]
|
||||
@@ -1841,6 +1842,12 @@ func (tps ThresholdMdls) AsTPThreshold() (result []*utils.TPThresholdProfile) {
|
||||
}
|
||||
actionMap[tenID].AddSlice(strings.Split(tp.ActionIDs, utils.InfieldSep))
|
||||
}
|
||||
if tp.EeIDs != utils.EmptyString {
|
||||
if _, has := eeIDsMap[tenID]; !has {
|
||||
eeIDsMap[tenID] = make(utils.StringSet)
|
||||
}
|
||||
eeIDsMap[tenID].AddSlice(strings.Split(tp.EeIDs, utils.InfieldSep))
|
||||
}
|
||||
if tp.Weight != 0 {
|
||||
th.Weight = tp.Weight
|
||||
}
|
||||
@@ -1869,6 +1876,7 @@ func (tps ThresholdMdls) AsTPThreshold() (result []*utils.TPThresholdProfile) {
|
||||
result[i] = th
|
||||
result[i].FilterIDs = filterMap[tntID].AsSlice()
|
||||
result[i].ActionIDs = actionMap[tntID].AsSlice()
|
||||
result[i].EeIDs = eeIDsMap[tntID].AsSlice()
|
||||
i++
|
||||
}
|
||||
return
|
||||
@@ -1883,7 +1891,10 @@ func APItoModelTPThreshold(th *utils.TPThresholdProfile) (mdls ThresholdMdls) {
|
||||
if min > len(th.ActionIDs) {
|
||||
min = len(th.ActionIDs)
|
||||
}
|
||||
for i := 0; i < min; i++ {
|
||||
if min > len(th.EeIDs) {
|
||||
min = len(th.EeIDs)
|
||||
}
|
||||
for i := range min {
|
||||
mdl := &ThresholdMdl{
|
||||
Tpid: th.TPid,
|
||||
Tenant: th.Tenant,
|
||||
@@ -1907,6 +1918,7 @@ func APItoModelTPThreshold(th *utils.TPThresholdProfile) (mdls ThresholdMdls) {
|
||||
}
|
||||
mdl.FilterIDs = th.FilterIDs[i]
|
||||
mdl.ActionIDs = th.ActionIDs[i]
|
||||
mdl.EeIDs = th.EeIDs[i]
|
||||
mdls = append(mdls, mdl)
|
||||
}
|
||||
|
||||
@@ -1921,6 +1933,17 @@ func APItoModelTPThreshold(th *utils.TPThresholdProfile) (mdls ThresholdMdls) {
|
||||
mdls = append(mdls, mdl)
|
||||
}
|
||||
}
|
||||
if len(th.EeIDs)-min > 0 {
|
||||
for i := min; i < len(th.EeIDs); i++ {
|
||||
mdl := &ThresholdMdl{
|
||||
Tpid: th.TPid,
|
||||
Tenant: th.Tenant,
|
||||
ID: th.ID,
|
||||
}
|
||||
mdl.EeIDs = th.EeIDs[i]
|
||||
mdls = append(mdls, mdl)
|
||||
}
|
||||
}
|
||||
if len(th.ActionIDs)-min > 0 {
|
||||
for i := min; i < len(th.ActionIDs); i++ {
|
||||
mdl := &ThresholdMdl{
|
||||
@@ -1963,6 +1986,7 @@ func APItoThresholdProfile(tpTH *utils.TPThresholdProfile, timezone string) (th
|
||||
Async: tpTH.Async,
|
||||
ActionIDs: make([]string, len(tpTH.ActionIDs)),
|
||||
FilterIDs: make([]string, len(tpTH.FilterIDs)),
|
||||
EeIDs: make([]string, len(tpTH.EeIDs)),
|
||||
}
|
||||
if tpTH.MinSleep != utils.EmptyString {
|
||||
if th.MinSleep, err = utils.ParseDurationWithNanosecs(tpTH.MinSleep); err != nil {
|
||||
@@ -1972,6 +1996,7 @@ func APItoThresholdProfile(tpTH *utils.TPThresholdProfile, timezone string) (th
|
||||
|
||||
copy(th.ActionIDs, tpTH.ActionIDs)
|
||||
copy(th.FilterIDs, tpTH.FilterIDs)
|
||||
copy(th.EeIDs, tpTH.EeIDs)
|
||||
|
||||
if tpTH.ActivationInterval != nil {
|
||||
if th.ActivationInterval, err = tpTH.ActivationInterval.AsActivationInterval(timezone); err != nil {
|
||||
@@ -1992,6 +2017,7 @@ func ThresholdProfileToAPI(th *ThresholdProfile) (tpTH *utils.TPThresholdProfile
|
||||
Blocker: th.Blocker,
|
||||
Weight: th.Weight,
|
||||
ActionIDs: make([]string, len(th.ActionIDs)),
|
||||
EeIDs: make([]string, len(th.EeIDs)),
|
||||
Async: th.Async,
|
||||
}
|
||||
if th.MinSleep != time.Duration(0) {
|
||||
@@ -2000,6 +2026,7 @@ func ThresholdProfileToAPI(th *ThresholdProfile) (tpTH *utils.TPThresholdProfile
|
||||
|
||||
copy(tpTH.FilterIDs, th.FilterIDs)
|
||||
copy(tpTH.ActionIDs, th.ActionIDs)
|
||||
copy(tpTH.EeIDs, th.EeIDs)
|
||||
|
||||
if th.ActivationInterval != nil {
|
||||
if !th.ActivationInterval.ActivationTime.IsZero() {
|
||||
|
||||
@@ -2290,6 +2290,7 @@ func TestAPItoModelTPThreshold(t *testing.T) {
|
||||
Blocker: false,
|
||||
Weight: 20.0,
|
||||
ActionIDs: []string{"WARN3"},
|
||||
EeIDs: []string{"EE1"},
|
||||
}
|
||||
models := ThresholdMdls{
|
||||
{
|
||||
@@ -2304,6 +2305,7 @@ func TestAPItoModelTPThreshold(t *testing.T) {
|
||||
Blocker: false,
|
||||
Weight: 20.0,
|
||||
ActionIDs: "WARN3",
|
||||
EeIDs: "EE1",
|
||||
},
|
||||
}
|
||||
rcv := APItoModelTPThreshold(th)
|
||||
@@ -2328,6 +2330,7 @@ func TestAPItoModelTPThreshold2(t *testing.T) {
|
||||
Blocker: false,
|
||||
Weight: 20.0,
|
||||
ActionIDs: []string{"WARN3"},
|
||||
EeIDs: []string{"EE1"},
|
||||
}
|
||||
models := ThresholdMdls{
|
||||
{
|
||||
@@ -2342,6 +2345,7 @@ func TestAPItoModelTPThreshold2(t *testing.T) {
|
||||
Blocker: false,
|
||||
Weight: 20.0,
|
||||
ActionIDs: "WARN3",
|
||||
EeIDs: "EE1",
|
||||
},
|
||||
{
|
||||
Tpid: "TP1",
|
||||
@@ -2372,6 +2376,7 @@ func TestAPItoModelTPThreshold3(t *testing.T) {
|
||||
Blocker: false,
|
||||
Weight: 20.0,
|
||||
ActionIDs: []string{"WARN3", "LOG"},
|
||||
EeIDs: []string{"EE1"},
|
||||
}
|
||||
models := ThresholdMdls{
|
||||
{
|
||||
@@ -2386,6 +2391,7 @@ func TestAPItoModelTPThreshold3(t *testing.T) {
|
||||
Blocker: false,
|
||||
Weight: 20.0,
|
||||
ActionIDs: "WARN3",
|
||||
EeIDs: "EE1",
|
||||
},
|
||||
{
|
||||
Tpid: "TP1",
|
||||
@@ -2415,9 +2421,16 @@ func TestAPItoModelTPThreshold4(t *testing.T) {
|
||||
MinSleep: "1s",
|
||||
Blocker: false,
|
||||
Weight: 20.0,
|
||||
ActionIDs: []string{"WARN3", "LOG"},
|
||||
ActionIDs: []string{"WARN3"},
|
||||
EeIDs: []string{"EE1"},
|
||||
}
|
||||
models := ThresholdMdls{
|
||||
{
|
||||
Tpid: "TP1",
|
||||
Tenant: "cgrates.org",
|
||||
ID: "TH_1",
|
||||
EeIDs: "EE1",
|
||||
},
|
||||
{
|
||||
Tpid: "TP1",
|
||||
Tenant: "cgrates.org",
|
||||
@@ -2430,12 +2443,6 @@ func TestAPItoModelTPThreshold4(t *testing.T) {
|
||||
Weight: 20.0,
|
||||
ActionIDs: "WARN3",
|
||||
},
|
||||
{
|
||||
Tpid: "TP1",
|
||||
Tenant: "cgrates.org",
|
||||
ID: "TH_1",
|
||||
ActionIDs: "LOG",
|
||||
},
|
||||
}
|
||||
rcv := APItoModelTPThreshold(th)
|
||||
if !reflect.DeepEqual(models, rcv) {
|
||||
@@ -2459,6 +2466,7 @@ func TestAPItoModelTPThreshold5(t *testing.T) {
|
||||
Blocker: false,
|
||||
Weight: 20.0,
|
||||
ActionIDs: []string{},
|
||||
EeIDs: []string{},
|
||||
}
|
||||
rcv := APItoModelTPThreshold(th)
|
||||
if rcv != nil {
|
||||
@@ -2478,6 +2486,7 @@ func TestAPItoTPThreshold(t *testing.T) {
|
||||
Blocker: false,
|
||||
Weight: 20.0,
|
||||
ActionIDs: []string{"WARN3"},
|
||||
EeIDs: []string{"EE1"},
|
||||
}
|
||||
|
||||
eTPs := &ThresholdProfile{
|
||||
@@ -2488,6 +2497,7 @@ func TestAPItoTPThreshold(t *testing.T) {
|
||||
Weight: tps.Weight,
|
||||
FilterIDs: tps.FilterIDs,
|
||||
ActionIDs: []string{"WARN3"},
|
||||
EeIDs: tps.EeIDs,
|
||||
}
|
||||
if eTPs.MinSleep, err = utils.ParseDurationWithNanosecs(tps.MinSleep); err != nil {
|
||||
t.Errorf("Got error: %+v", err)
|
||||
@@ -2512,6 +2522,7 @@ func TestThresholdProfileToAPI(t *testing.T) {
|
||||
MinSleep: "1s",
|
||||
Weight: 20.0,
|
||||
ActionIDs: []string{"WARN3"},
|
||||
EeIDs: []string{"EE1"},
|
||||
}
|
||||
|
||||
thPrf := &ThresholdProfile{
|
||||
@@ -2527,6 +2538,7 @@ func TestThresholdProfileToAPI(t *testing.T) {
|
||||
MinSleep: time.Second,
|
||||
Weight: 20.0,
|
||||
ActionIDs: []string{"WARN3"},
|
||||
EeIDs: []string{"EE1"},
|
||||
}
|
||||
|
||||
if rcv := ThresholdProfileToAPI(thPrf); !reflect.DeepEqual(expected, rcv) {
|
||||
@@ -5033,7 +5045,7 @@ func TestThresholdMdlsCSVHeader(t *testing.T) {
|
||||
}
|
||||
expStruct := []string{"#" + utils.Tenant, utils.ID, utils.FilterIDs, utils.ActivationIntervalString,
|
||||
utils.MaxHits, utils.MinHits, utils.MinSleep,
|
||||
utils.Blocker, utils.Weight, utils.ActionIDs, utils.Async}
|
||||
utils.Blocker, utils.Weight, utils.ActionIDs, utils.Async, utils.EeIDs}
|
||||
result := testStruct.CSVHeader()
|
||||
if !reflect.DeepEqual(result, expStruct) {
|
||||
t.Errorf("\nExpecting <%+v>,\n Received <%+v>", utils.ToJSON(expStruct), utils.ToJSON(result))
|
||||
@@ -5250,6 +5262,7 @@ func TestModelHelpersThresholdProfileToAPIExpTime(t *testing.T) {
|
||||
ExpiryTime: time.Date(2014, 7, 15, 14, 25, 0, 0, time.UTC),
|
||||
},
|
||||
ActionIDs: []string{"test_action_id"},
|
||||
EeIDs: []string{"test_ee_id"},
|
||||
}
|
||||
expStruct := &utils.TPThresholdProfile{
|
||||
FilterIDs: []string{"test_filter_id"},
|
||||
@@ -5258,6 +5271,7 @@ func TestModelHelpersThresholdProfileToAPIExpTime(t *testing.T) {
|
||||
ExpiryTime: "2014-07-15T14:25:00Z",
|
||||
},
|
||||
ActionIDs: []string{"test_action_id"},
|
||||
EeIDs: []string{"test_ee_id"},
|
||||
}
|
||||
result := ThresholdProfileToAPI(testStruct)
|
||||
if !reflect.DeepEqual(result, expStruct) {
|
||||
@@ -5369,6 +5383,7 @@ func TestModelHelpersAPItoModelTPThresholdExpTime2(t *testing.T) {
|
||||
Blocker: false,
|
||||
Weight: 20.0,
|
||||
ActionIDs: []string{"WARN3"},
|
||||
EeIDs: []string{"EE1"},
|
||||
}
|
||||
expStruct := ThresholdMdls{
|
||||
{
|
||||
@@ -5383,6 +5398,7 @@ func TestModelHelpersAPItoModelTPThresholdExpTime2(t *testing.T) {
|
||||
Blocker: false,
|
||||
Weight: 20.0,
|
||||
ActionIDs: "WARN3",
|
||||
EeIDs: "EE1",
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -338,7 +338,9 @@ type ThresholdMdl struct {
|
||||
Weight float64 `index:"8" re:".*"`
|
||||
ActionIDs string `index:"9" re:".*"`
|
||||
Async bool `index:"10" re:".*"`
|
||||
CreatedAt time.Time
|
||||
EeIDs string `index:"11" re:".*"`
|
||||
|
||||
CreatedAt time.Time
|
||||
}
|
||||
|
||||
func (ThresholdMdl) TableName() string {
|
||||
|
||||
@@ -25,6 +25,8 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"slices"
|
||||
|
||||
"github.com/cgrates/birpc/context"
|
||||
"github.com/cgrates/cgrates/config"
|
||||
"github.com/cgrates/cgrates/guardian"
|
||||
@@ -50,6 +52,7 @@ type ThresholdProfile struct {
|
||||
Weight float64 // Weight to sort the thresholds
|
||||
ActionIDs []string
|
||||
Async bool
|
||||
EeIDs []string
|
||||
|
||||
lkID string // holds the reference towards guardian lock key
|
||||
}
|
||||
@@ -172,6 +175,19 @@ func (t *Threshold) TenantID() string {
|
||||
return utils.ConcatenatedKey(t.Tenant, t.ID)
|
||||
}
|
||||
|
||||
type ThresholdConfig struct {
|
||||
FilterIDs []string
|
||||
ActivationInterval *utils.ActivationInterval
|
||||
MaxHits int
|
||||
MinHits int
|
||||
MinSleep time.Duration
|
||||
Blocker bool
|
||||
Weight float64
|
||||
ActionIDs []string
|
||||
Async bool
|
||||
EeIDs []string
|
||||
}
|
||||
|
||||
// thresholdLockKey returns the ID used to lock a threshold with guardian
|
||||
func thresholdLockKey(tnt, id string) string {
|
||||
return utils.ConcatenatedKey(utils.CacheThresholds, tnt, id)
|
||||
@@ -205,12 +221,6 @@ func (t *Threshold) isLocked() bool {
|
||||
// ProcessEvent processes an ThresholdEvent
|
||||
// concurrentActions limits the number of simultaneous action sets executed
|
||||
func (t *Threshold) ProcessEvent(args *utils.CGREvent, dm *DataManager, fltrS *FilterS) (err error) {
|
||||
if t.Snooze.After(time.Now()) || // snoozed, not executing actions
|
||||
t.Hits < t.tPrfl.MinHits || // number of hits was not met, will not execute actions
|
||||
(t.tPrfl.MaxHits != -1 &&
|
||||
t.Hits > t.tPrfl.MaxHits) {
|
||||
return
|
||||
}
|
||||
var tntAcnt string
|
||||
var acnt string
|
||||
if utils.IfaceAsString(args.APIOpts[utils.MetaEventType]) == utils.AccountUpdate {
|
||||
@@ -224,7 +234,6 @@ func (t *Threshold) ProcessEvent(args *utils.CGREvent, dm *DataManager, fltrS *F
|
||||
if acnt != utils.EmptyString {
|
||||
tntAcnt = utils.ConcatenatedKey(args.Tenant, acnt)
|
||||
}
|
||||
|
||||
for _, actionSetID := range t.tPrfl.ActionIDs {
|
||||
at := &ActionTiming{
|
||||
Uuid: utils.GenUUID(),
|
||||
@@ -249,6 +258,79 @@ func (t *Threshold) ProcessEvent(args *utils.CGREvent, dm *DataManager, fltrS *F
|
||||
return
|
||||
}
|
||||
|
||||
// processEEs processes to the EEs for this threshold
|
||||
func (t *Threshold) processEEs(opts map[string]any, thScfg *config.ThresholdSCfg, connMgr *ConnManager) (err error) {
|
||||
if len(thScfg.EEsConns) == 0 {
|
||||
return nil
|
||||
}
|
||||
var targetEeIDs []string
|
||||
if len(t.tPrfl.EeIDs) > 0 {
|
||||
targetEeIDs = t.tPrfl.EeIDs
|
||||
} else {
|
||||
isNone := slices.Contains(thScfg.EEsExporterIDs, utils.MetaNone)
|
||||
if isNone {
|
||||
targetEeIDs = []string{}
|
||||
} else if len(thScfg.EEsExporterIDs) > 0 {
|
||||
targetEeIDs = thScfg.EEsExporterIDs
|
||||
}
|
||||
}
|
||||
if targetEeIDs == nil {
|
||||
return nil // Nothing to do.
|
||||
}
|
||||
if opts == nil {
|
||||
opts = make(map[string]any)
|
||||
}
|
||||
opts[utils.MetaEventType] = utils.ThresholdHit
|
||||
cgrEv := &utils.CGREvent{
|
||||
Tenant: t.Tenant,
|
||||
ID: utils.GenUUID(),
|
||||
Time: utils.TimePointer(time.Now()),
|
||||
Event: map[string]any{
|
||||
utils.EventType: utils.ThresholdHit,
|
||||
utils.ID: t.ID,
|
||||
utils.Hits: t.Hits,
|
||||
utils.Snooze: t.Snooze,
|
||||
utils.ThresholdConfig: ThresholdConfig{
|
||||
FilterIDs: t.tPrfl.FilterIDs,
|
||||
ActivationInterval: t.tPrfl.ActivationInterval,
|
||||
MaxHits: t.tPrfl.MaxHits,
|
||||
MinHits: t.tPrfl.MinHits,
|
||||
MinSleep: t.tPrfl.MinSleep,
|
||||
Blocker: t.tPrfl.Blocker,
|
||||
Weight: t.tPrfl.Weight,
|
||||
ActionIDs: t.tPrfl.ActionIDs,
|
||||
Async: t.tPrfl.Async,
|
||||
EeIDs: t.tPrfl.EeIDs,
|
||||
},
|
||||
},
|
||||
APIOpts: opts,
|
||||
}
|
||||
cgrEventWithID := &CGREventWithEeIDs{
|
||||
CGREvent: cgrEv,
|
||||
EeIDs: targetEeIDs,
|
||||
}
|
||||
var reply map[string]map[string]any
|
||||
if t.tPrfl.Async {
|
||||
go func() {
|
||||
if err := connMgr.Call(context.TODO(), thScfg.EEsConns,
|
||||
utils.EeSv1ProcessEvent,
|
||||
cgrEventWithID, &reply); err != nil &&
|
||||
err.Error() != utils.ErrNotFound.Error() {
|
||||
utils.Logger.Warning(
|
||||
fmt.Sprintf("<ThresholdS> error: %s processing event %+v with EEs.", err.Error(), cgrEv))
|
||||
}
|
||||
}()
|
||||
} else if errExec := connMgr.Call(context.TODO(), thScfg.EEsConns,
|
||||
utils.EeSv1ProcessEvent,
|
||||
cgrEventWithID, &reply); errExec != nil &&
|
||||
errExec.Error() != utils.ErrNotFound.Error() {
|
||||
utils.Logger.Warning(
|
||||
fmt.Sprintf("<ThresholdS> error: %s processing event %+v with EEs.", err.Error(), cgrEv))
|
||||
err = utils.ErrPartiallyExecuted
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Thresholds is a sortable slice of Threshold
|
||||
type Thresholds []*Threshold
|
||||
|
||||
@@ -268,11 +350,12 @@ func (ts Thresholds) unlock() {
|
||||
}
|
||||
|
||||
// NewThresholdService the constructor for ThresoldS service
|
||||
func NewThresholdService(dm *DataManager, cgrcfg *config.CGRConfig, filterS *FilterS) *ThresholdService {
|
||||
func NewThresholdService(dm *DataManager, cgrcfg *config.CGRConfig, filterS *FilterS, conn *ConnManager) *ThresholdService {
|
||||
return &ThresholdService{
|
||||
dm: dm,
|
||||
cgrcfg: cgrcfg,
|
||||
filterS: filterS,
|
||||
dm: dm,
|
||||
cgrcfg: cgrcfg,
|
||||
filterS: filterS,
|
||||
|
||||
stopBackup: make(chan struct{}),
|
||||
loopStopped: make(chan struct{}),
|
||||
storedTdIDs: make(utils.StringSet),
|
||||
@@ -288,6 +371,7 @@ type ThresholdService struct {
|
||||
loopStopped chan struct{}
|
||||
storedTdIDs utils.StringSet // keep a record of stats which need saving, map[statsTenantID]bool
|
||||
stMux sync.RWMutex // protects storedTdIDs
|
||||
connMgr *ConnManager
|
||||
}
|
||||
|
||||
// Reload stops the backupLoop and restarts it
|
||||
@@ -500,6 +584,12 @@ func (tS *ThresholdService) processEvent(tnt string, args *utils.CGREvent) (thre
|
||||
for _, t := range matchTs {
|
||||
thresholdsIDs = append(thresholdsIDs, t.ID)
|
||||
t.Hits++
|
||||
if t.Snooze.After(time.Now()) || // snoozed, not executing actions
|
||||
t.Hits < t.tPrfl.MinHits || // number of hits was not met, will not execute actions
|
||||
(t.tPrfl.MaxHits != -1 &&
|
||||
t.Hits > t.tPrfl.MaxHits) {
|
||||
continue
|
||||
}
|
||||
if err = t.ProcessEvent(args, tS.dm, tS.filterS); err != nil {
|
||||
utils.Logger.Warning(
|
||||
fmt.Sprintf("<ThresholdService> threshold: %s, ignoring event: %s, error: %s",
|
||||
@@ -507,6 +597,11 @@ func (tS *ThresholdService) processEvent(tnt string, args *utils.CGREvent) (thre
|
||||
withErrors = true
|
||||
continue
|
||||
}
|
||||
if err = t.processEEs(args.APIOpts, tS.cgrcfg.ThresholdSCfg(), connMgr); err != nil {
|
||||
utils.Logger.Warning(
|
||||
fmt.Sprintf("<ThresholdService> threshold: %s processing with EEs.", err.Error()))
|
||||
withErrors = true
|
||||
}
|
||||
if t.dirty == nil || t.Hits == t.tPrfl.MaxHits { // one time threshold
|
||||
if err = tS.dm.RemoveThreshold(t.Tenant, t.ID); err != nil {
|
||||
utils.Logger.Warning(
|
||||
|
||||
@@ -246,7 +246,7 @@ func TestThresholdsmatchingThresholdsForEvent(t *testing.T) {
|
||||
cfg.ThresholdSCfg().StoreInterval = 0
|
||||
cfg.ThresholdSCfg().StringIndexedFields = nil
|
||||
cfg.ThresholdSCfg().PrefixIndexedFields = nil
|
||||
thServ := NewThresholdService(dmTH, cfg, &FilterS{dm: dmTH, cfg: cfg})
|
||||
thServ := NewThresholdService(dmTH, cfg, &FilterS{dm: dmTH, cfg: cfg}, nil)
|
||||
prepareThresholdData(t, dmTH)
|
||||
|
||||
thMatched, err := thServ.matchingThresholdsForEvent(testThresholdArgs[0].Tenant, testThresholdArgs[0])
|
||||
@@ -297,7 +297,7 @@ func TestThresholdsProcessEvent(t *testing.T) {
|
||||
cfg.ThresholdSCfg().StoreInterval = 0
|
||||
cfg.ThresholdSCfg().StringIndexedFields = nil
|
||||
cfg.ThresholdSCfg().PrefixIndexedFields = nil
|
||||
thServ := NewThresholdService(dmTH, cfg, &FilterS{dm: dmTH, cfg: cfg})
|
||||
thServ := NewThresholdService(dmTH, cfg, &FilterS{dm: dmTH, cfg: cfg}, nil)
|
||||
prepareThresholdData(t, dmTH)
|
||||
|
||||
thIDs := []string{"TH_1"}
|
||||
@@ -333,7 +333,7 @@ func TestThresholdsVerifyIfExecuted(t *testing.T) {
|
||||
cfg.ThresholdSCfg().StoreInterval = 0
|
||||
cfg.ThresholdSCfg().StringIndexedFields = nil
|
||||
cfg.ThresholdSCfg().PrefixIndexedFields = nil
|
||||
thServ := NewThresholdService(dmTH, cfg, &FilterS{dm: dmTH, cfg: cfg})
|
||||
thServ := NewThresholdService(dmTH, cfg, &FilterS{dm: dmTH, cfg: cfg}, nil)
|
||||
prepareThresholdData(t, dmTH)
|
||||
|
||||
thIDs := []string{"TH_1"}
|
||||
@@ -406,7 +406,7 @@ func TestThresholdsProcessEvent2(t *testing.T) {
|
||||
cfg.ThresholdSCfg().StoreInterval = 0
|
||||
cfg.ThresholdSCfg().StringIndexedFields = nil
|
||||
cfg.ThresholdSCfg().PrefixIndexedFields = nil
|
||||
thServ := NewThresholdService(dmTH, cfg, &FilterS{dm: dmTH, cfg: cfg})
|
||||
thServ := NewThresholdService(dmTH, cfg, &FilterS{dm: dmTH, cfg: cfg}, nil)
|
||||
prepareThresholdData(t, dmTH)
|
||||
|
||||
thPrf := &ThresholdProfile{
|
||||
@@ -677,39 +677,6 @@ func TestThresholdsProcessEventAsyncExecErr(t *testing.T) {
|
||||
utils.Logger.SetLogLevel(0)
|
||||
}
|
||||
|
||||
func TestThresholdsProcessEvent3(t *testing.T) {
|
||||
thPrf := &ThresholdProfile{
|
||||
Tenant: "cgrates.org",
|
||||
ID: "TH1",
|
||||
FilterIDs: []string{"*string:~*req.Account:1001"},
|
||||
MinHits: 3,
|
||||
MaxHits: 5,
|
||||
Weight: 10,
|
||||
ActionIDs: []string{"actPrf"},
|
||||
}
|
||||
th := &Threshold{
|
||||
Tenant: "cgrates.org",
|
||||
ID: "TH1",
|
||||
Hits: 2,
|
||||
tPrfl: thPrf,
|
||||
}
|
||||
|
||||
args := &utils.CGREvent{
|
||||
Tenant: "cgrates.org",
|
||||
ID: "ThresholdProcessEvent",
|
||||
Event: map[string]any{
|
||||
utils.AccountField: "1001",
|
||||
},
|
||||
APIOpts: map[string]any{
|
||||
utils.MetaEventType: utils.AccountUpdate,
|
||||
utils.OptsThresholdsProfileIDs: []string{"TH1"},
|
||||
},
|
||||
}
|
||||
if err := th.ProcessEvent(args, dm, nil); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestThresholdsShutdown(t *testing.T) {
|
||||
utils.Logger.SetLogLevel(6)
|
||||
utils.Logger.SetSyslog(nil)
|
||||
@@ -726,7 +693,7 @@ func TestThresholdsShutdown(t *testing.T) {
|
||||
t.Error(dErr)
|
||||
}
|
||||
dm := NewDataManager(data, cfg.CacheCfg(), nil)
|
||||
tS := NewThresholdService(dm, cfg, nil)
|
||||
tS := NewThresholdService(dm, cfg, nil, nil)
|
||||
|
||||
expLog1 := `[INFO] <ThresholdS> shutdown initialized`
|
||||
expLog2 := `[INFO] <ThresholdS> shutdown complete`
|
||||
@@ -748,7 +715,7 @@ func TestThresholdsStoreThresholdsOK(t *testing.T) {
|
||||
t.Error(dErr)
|
||||
}
|
||||
dm := NewDataManager(data, cfg.CacheCfg(), nil)
|
||||
tS := NewThresholdService(dm, cfg, nil)
|
||||
tS := NewThresholdService(dm, cfg, nil, nil)
|
||||
|
||||
exp := &Threshold{
|
||||
dirty: utils.BoolPointer(false),
|
||||
@@ -784,7 +751,7 @@ func TestThresholdsStoreThresholdsStoreThErr(t *testing.T) {
|
||||
}()
|
||||
|
||||
cfg := config.NewDefaultCGRConfig()
|
||||
tS := NewThresholdService(nil, cfg, nil)
|
||||
tS := NewThresholdService(nil, cfg, nil, nil)
|
||||
|
||||
value := &Threshold{
|
||||
dirty: utils.BoolPointer(true),
|
||||
@@ -830,7 +797,7 @@ func TestThresholdsStoreThresholdsCacheGetErr(t *testing.T) {
|
||||
t.Error(dErr)
|
||||
}
|
||||
dm := NewDataManager(data, cfg.CacheCfg(), nil)
|
||||
tS := NewThresholdService(dm, cfg, nil)
|
||||
tS := NewThresholdService(dm, cfg, nil, nil)
|
||||
|
||||
value := &Threshold{
|
||||
dirty: utils.BoolPointer(true),
|
||||
@@ -860,7 +827,7 @@ func TestThresholdsStoreThresholdNilDirtyField(t *testing.T) {
|
||||
t.Error(dErr)
|
||||
}
|
||||
dm := NewDataManager(data, cfg.CacheCfg(), nil)
|
||||
tS := NewThresholdService(dm, cfg, nil)
|
||||
tS := NewThresholdService(dm, cfg, nil, nil)
|
||||
|
||||
th := &Threshold{
|
||||
Tenant: "cgrates.org",
|
||||
@@ -881,7 +848,7 @@ func TestThresholdsProcessEventOK(t *testing.T) {
|
||||
}
|
||||
dm := NewDataManager(data, cfg.CacheCfg(), nil)
|
||||
filterS := NewFilterS(cfg, nil, dm)
|
||||
tS := NewThresholdService(dm, cfg, filterS)
|
||||
tS := NewThresholdService(dm, cfg, filterS, nil)
|
||||
|
||||
thPrf := &ThresholdProfile{
|
||||
Tenant: "cgrates.org",
|
||||
@@ -943,7 +910,7 @@ func TestThresholdsProcessEventStoreThOK(t *testing.T) {
|
||||
}
|
||||
dm := NewDataManager(data, cfg.CacheCfg(), nil)
|
||||
filterS := NewFilterS(cfg, nil, dm)
|
||||
tS := NewThresholdService(dm, cfg, filterS)
|
||||
tS := NewThresholdService(dm, cfg, filterS, nil)
|
||||
|
||||
thPrf := &ThresholdProfile{
|
||||
Tenant: "cgrates.org",
|
||||
@@ -1016,7 +983,7 @@ func TestThresholdsProcessEventMaxHitsDMErr(t *testing.T) {
|
||||
connMgr = NewConnManager(cfg, make(map[string]chan birpc.ClientConnector))
|
||||
dm := NewDataManager(data, cfg.CacheCfg(), connMgr)
|
||||
filterS := NewFilterS(cfg, nil, dm)
|
||||
tS := NewThresholdService(nil, cfg, filterS)
|
||||
tS := NewThresholdService(nil, cfg, filterS, nil)
|
||||
Cache = NewCacheS(cfg, dm, nil)
|
||||
|
||||
defer func() {
|
||||
@@ -1090,7 +1057,7 @@ func TestThresholdsProcessEventNotFound(t *testing.T) {
|
||||
}
|
||||
dm := NewDataManager(data, cfg.CacheCfg(), nil)
|
||||
filterS := NewFilterS(cfg, nil, dm)
|
||||
tS := NewThresholdService(dm, cfg, filterS)
|
||||
tS := NewThresholdService(dm, cfg, filterS, nil)
|
||||
|
||||
thPrf := &ThresholdProfile{
|
||||
Tenant: "cgrates.org",
|
||||
@@ -1146,7 +1113,7 @@ func TestThresholdsV1ProcessEventOK(t *testing.T) {
|
||||
dm := NewDataManager(data, cfg.CacheCfg(), nil)
|
||||
Cache.Clear(nil)
|
||||
filterS := NewFilterS(cfg, nil, dm)
|
||||
tS := NewThresholdService(dm, cfg, filterS)
|
||||
tS := NewThresholdService(dm, cfg, filterS, nil)
|
||||
|
||||
thPrf1 := &ThresholdProfile{
|
||||
Tenant: "cgrates.org",
|
||||
@@ -1209,7 +1176,7 @@ func TestThresholdsV1ProcessEventPartExecErr(t *testing.T) {
|
||||
dm := NewDataManager(data, cfg.CacheCfg(), nil)
|
||||
Cache.Clear(nil)
|
||||
filterS := NewFilterS(cfg, nil, dm)
|
||||
tS := NewThresholdService(dm, cfg, filterS)
|
||||
tS := NewThresholdService(dm, cfg, filterS, nil)
|
||||
|
||||
thPrf1 := &ThresholdProfile{
|
||||
Tenant: "cgrates.org",
|
||||
@@ -1269,7 +1236,7 @@ func TestThresholdsV1ProcessEventMissingArgs(t *testing.T) {
|
||||
dm := NewDataManager(data, cfg.CacheCfg(), nil)
|
||||
Cache.Clear(nil)
|
||||
filterS := NewFilterS(cfg, nil, dm)
|
||||
tS := NewThresholdService(dm, cfg, filterS)
|
||||
tS := NewThresholdService(dm, cfg, filterS, nil)
|
||||
|
||||
thPrf1 := &ThresholdProfile{
|
||||
Tenant: "cgrates.org",
|
||||
@@ -1341,7 +1308,7 @@ func TestThresholdsV1GetThresholdOK(t *testing.T) {
|
||||
dm := NewDataManager(data, cfg.CacheCfg(), nil)
|
||||
Cache.Clear(nil)
|
||||
filterS := NewFilterS(cfg, nil, dm)
|
||||
tS := NewThresholdService(dm, cfg, filterS)
|
||||
tS := NewThresholdService(dm, cfg, filterS, nil)
|
||||
|
||||
thPrf := &ThresholdProfile{
|
||||
Tenant: "cgrates.org",
|
||||
@@ -1387,7 +1354,7 @@ func TestThresholdsV1GetThresholdNotFoundErr(t *testing.T) {
|
||||
dm := NewDataManager(data, cfg.CacheCfg(), nil)
|
||||
Cache.Clear(nil)
|
||||
filterS := NewFilterS(cfg, nil, dm)
|
||||
tS := NewThresholdService(dm, cfg, filterS)
|
||||
tS := NewThresholdService(dm, cfg, filterS, nil)
|
||||
|
||||
thPrf := &ThresholdProfile{
|
||||
Tenant: "cgrates.org",
|
||||
@@ -1423,7 +1390,7 @@ func TestThresholdMatchingThresholdForEventLocks2(t *testing.T) {
|
||||
cfg.ThresholdSCfg().StringIndexedFields = nil
|
||||
cfg.ThresholdSCfg().PrefixIndexedFields = nil
|
||||
rS := NewThresholdService(dm, cfg,
|
||||
&FilterS{dm: dm, cfg: cfg})
|
||||
&FilterS{dm: dm, cfg: cfg}, nil)
|
||||
|
||||
prfs := make([]*ThresholdProfile, 0)
|
||||
ids := utils.StringSet{}
|
||||
@@ -1487,7 +1454,7 @@ func TestThresholdMatchingThresholdForEventLocksActivationInterval(t *testing.T)
|
||||
cfg.ThresholdSCfg().StringIndexedFields = nil
|
||||
cfg.ThresholdSCfg().PrefixIndexedFields = nil
|
||||
rS := NewThresholdService(dm, cfg,
|
||||
&FilterS{dm: dm, cfg: cfg})
|
||||
&FilterS{dm: dm, cfg: cfg}, nil)
|
||||
|
||||
ids := utils.StringSet{}
|
||||
for i := 0; i < 10; i++ {
|
||||
@@ -1559,7 +1526,7 @@ func TestThresholdMatchingThresholdForEventLocks3(t *testing.T) {
|
||||
cfg.ThresholdSCfg().StringIndexedFields = nil
|
||||
cfg.ThresholdSCfg().PrefixIndexedFields = nil
|
||||
rS := NewThresholdService(dm, cfg,
|
||||
&FilterS{dm: dm, cfg: cfg})
|
||||
&FilterS{dm: dm, cfg: cfg}, nil)
|
||||
|
||||
ids := utils.StringSet{}
|
||||
for i := 0; i < 10; i++ {
|
||||
@@ -1601,7 +1568,7 @@ func TestThresholdMatchingThresholdForEventLocks5(t *testing.T) {
|
||||
cfg.DataDbCfg().Items[utils.CacheThresholds].Remote = true
|
||||
config.SetCgrConfig(cfg)
|
||||
rS := NewThresholdService(dm, cfg,
|
||||
&FilterS{dm: dm, cfg: cfg})
|
||||
&FilterS{dm: dm, cfg: cfg}, nil)
|
||||
|
||||
prfs := make([]*ThresholdProfile, 0)
|
||||
ids := utils.StringSet{}
|
||||
@@ -1754,7 +1721,7 @@ func TestThresholdsV1GetThresholdsForEventOK(t *testing.T) {
|
||||
dm := NewDataManager(data, cfg.CacheCfg(), nil)
|
||||
Cache.Clear(nil)
|
||||
filterS := NewFilterS(cfg, nil, dm)
|
||||
tS := NewThresholdService(dm, cfg, filterS)
|
||||
tS := NewThresholdService(dm, cfg, filterS, nil)
|
||||
|
||||
thPrf := &ThresholdProfile{
|
||||
Tenant: "cgrates.org",
|
||||
@@ -1808,7 +1775,7 @@ func TestThresholdsV1GetThresholdsForEventMissingArgs(t *testing.T) {
|
||||
dm := NewDataManager(data, cfg.CacheCfg(), nil)
|
||||
Cache.Clear(nil)
|
||||
filterS := NewFilterS(cfg, nil, dm)
|
||||
tS := NewThresholdService(dm, cfg, filterS)
|
||||
tS := NewThresholdService(dm, cfg, filterS, nil)
|
||||
|
||||
thPrf := &ThresholdProfile{
|
||||
Tenant: "cgrates.org",
|
||||
@@ -1875,7 +1842,7 @@ func TestThresholdsV1GetThresholdIDsOK(t *testing.T) {
|
||||
dm := NewDataManager(data, cfg.CacheCfg(), nil)
|
||||
Cache.Clear(nil)
|
||||
filterS := NewFilterS(cfg, nil, dm)
|
||||
tS := NewThresholdService(dm, cfg, filterS)
|
||||
tS := NewThresholdService(dm, cfg, filterS, nil)
|
||||
|
||||
thPrf1 := &ThresholdProfile{
|
||||
Tenant: "cgrates.org",
|
||||
@@ -1925,7 +1892,7 @@ func TestThresholdsV1GetThresholdIDsGetKeysForPrefixErr(t *testing.T) {
|
||||
dm := NewDataManager(data, cfg.CacheCfg(), nil)
|
||||
Cache.Clear(nil)
|
||||
filterS := NewFilterS(cfg, nil, dm)
|
||||
tS := NewThresholdService(dm, cfg, filterS)
|
||||
tS := NewThresholdService(dm, cfg, filterS, nil)
|
||||
|
||||
var reply []string
|
||||
if err := tS.V1GetThresholdIDs(context.Background(), "", &reply); err == nil ||
|
||||
@@ -1949,7 +1916,7 @@ func TestThresholdsV1ResetThresholdOK(t *testing.T) {
|
||||
Cache.Clear(nil)
|
||||
defer Cache.Clear(nil)
|
||||
filterS := NewFilterS(cfg, nil, dm)
|
||||
tS := NewThresholdService(dm, cfg, filterS)
|
||||
tS := NewThresholdService(dm, cfg, filterS, nil)
|
||||
|
||||
thPrf := &ThresholdProfile{
|
||||
Tenant: "cgrates.org",
|
||||
@@ -2007,7 +1974,7 @@ func TestThresholdsV1ResetThresholdErrNotFound(t *testing.T) {
|
||||
dm := NewDataManager(data, cfg.CacheCfg(), nil)
|
||||
Cache.Clear(nil)
|
||||
filterS := NewFilterS(cfg, nil, dm)
|
||||
tS := NewThresholdService(dm, cfg, filterS)
|
||||
tS := NewThresholdService(dm, cfg, filterS, nil)
|
||||
|
||||
thPrf := &ThresholdProfile{
|
||||
Tenant: "cgrates.org",
|
||||
@@ -2054,7 +2021,7 @@ func TestThresholdsV1ResetThresholdNegativeStoreIntervalOK(t *testing.T) {
|
||||
dm := NewDataManager(data, cfg.CacheCfg(), nil)
|
||||
Cache.Clear(nil)
|
||||
filterS := NewFilterS(cfg, nil, dm)
|
||||
tS := NewThresholdService(dm, cfg, filterS)
|
||||
tS := NewThresholdService(dm, cfg, filterS, nil)
|
||||
|
||||
thPrf := &ThresholdProfile{
|
||||
Tenant: "cgrates.org",
|
||||
@@ -2109,7 +2076,7 @@ func TestThresholdsV1ResetThresholdNegativeStoreIntervalErr(t *testing.T) {
|
||||
dm := NewDataManager(data, cfg.CacheCfg(), nil)
|
||||
Cache.Clear(nil)
|
||||
filterS := NewFilterS(cfg, nil, dm)
|
||||
tS := NewThresholdService(nil, cfg, filterS)
|
||||
tS := NewThresholdService(nil, cfg, filterS, nil)
|
||||
|
||||
thPrf := &ThresholdProfile{
|
||||
Tenant: "cgrates.org",
|
||||
@@ -2226,7 +2193,7 @@ func TestThresholdsMatchingThresholdsForEventNotFoundErr(t *testing.T) {
|
||||
dm := NewDataManager(data, cfg.CacheCfg(), nil)
|
||||
Cache.Clear(nil)
|
||||
filterS := NewFilterS(cfg, nil, dm)
|
||||
tS := NewThresholdService(dm, cfg, filterS)
|
||||
tS := NewThresholdService(dm, cfg, filterS, nil)
|
||||
|
||||
thPrf1 := &ThresholdProfile{
|
||||
Tenant: "cgrates.org",
|
||||
@@ -2285,7 +2252,7 @@ func TestThresholdsStoreThresholdCacheSetErr(t *testing.T) {
|
||||
connMgr = NewConnManager(cfg, make(map[string]chan birpc.ClientConnector))
|
||||
Cache = NewCacheS(cfg, dm, nil)
|
||||
filterS := NewFilterS(cfg, nil, dm)
|
||||
tS := NewThresholdService(dm, cfg, filterS)
|
||||
tS := NewThresholdService(dm, cfg, filterS, nil)
|
||||
|
||||
th := &Threshold{
|
||||
Tenant: "cgrates.org",
|
||||
@@ -2331,8 +2298,8 @@ func TestThresholdSnoozeSleep(t *testing.T) {
|
||||
for i, arg := range testThresholdArgs {
|
||||
th.ProcessEvent(arg, dm, fs)
|
||||
if i > 0 {
|
||||
if !th.Snooze.Equal(snoozeTime) {
|
||||
t.Error("expecte snooze to not change during sleep time")
|
||||
if th.Snooze.Equal(snoozeTime) {
|
||||
t.Error("expecte snooze change time")
|
||||
}
|
||||
} else {
|
||||
snoozeTime = th.Snooze
|
||||
|
||||
Reference in New Issue
Block a user