From 63345c3c85b88eb6cb30998a145975153a87c0e8 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Fri, 11 Dec 2020 12:28:46 +0200 Subject: [PATCH] Updated integration tests --- actions/actions.go | 2 +- apier/v1/actionprofiles.go | 2 +- apier/v1/actionprofiles_it_test.go | 18 +++-- apier/v1/apier_it_test.go | 8 +- apier/v1/triggers.go | 69 +++++++++------- .../samples/replication/internal/cgrates.json | 1 - .../replication/internal_gob/cgrates.json | 80 +++++++++---------- dispatchers/actions_it_test.go | 2 +- engine/eventcost.go | 3 +- engine/timespans.go | 21 ++--- engine/tpreader.go | 21 ++++- general_tests/export_it_test.go | 31 ++++--- services/actions.go | 8 ++ 13 files changed, 159 insertions(+), 107 deletions(-) diff --git a/actions/actions.go b/actions/actions.go index d9a189894..127a423a5 100644 --- a/actions/actions.go +++ b/actions/actions.go @@ -35,6 +35,7 @@ func NewActionS(cfg *config.CGRConfig, fltrS *engine.FilterS, dm *engine.DataMan cfg: cfg, fltrS: fltrS, dm: dm, + crn: cron.New(), } } @@ -50,7 +51,6 @@ type ActionS struct { func (aS *ActionS) ListenAndServe(stopChan, cfgRld chan struct{}) { utils.Logger.Info(fmt.Sprintf("<%s> starting <%s>", utils.CoreS, utils.ActionS)) - aS.crn = cron.New() aS.crn.Start() for { select { diff --git a/apier/v1/actionprofiles.go b/apier/v1/actionprofiles.go index fdb4dae1e..d435512b0 100644 --- a/apier/v1/actionprofiles.go +++ b/apier/v1/actionprofiles.go @@ -159,7 +159,7 @@ func (aSv1 *ActionSv1) Call(serviceMethod string, } // Ping return pong if the service is active -func (aSv1 *ActionSv1) Ping(ign *utils.CGREvent, reply *string) error { +func (aSv1 *ActionSv1) Ping(ign *utils.CGREventWithOpts, reply *string) error { *reply = utils.Pong return nil } diff --git a/apier/v1/actionprofiles_it_test.go b/apier/v1/actionprofiles_it_test.go index 70c16b0e7..d75b74bbd 100644 --- a/apier/v1/actionprofiles_it_test.go +++ b/apier/v1/actionprofiles_it_test.go @@ -192,7 +192,7 @@ func testActionSGetActionProfile(t *testing.T) { func testActionSPing(t *testing.T) { var resp string - if err := actSRPC.Call(utils.ActionSv1Ping, new(utils.CGREvent), &resp); err != nil { + if err := actSRPC.Call(utils.ActionSv1Ping, new(utils.CGREventWithOpts), &resp); err != nil { t.Error(err) } else if resp != utils.Pong { t.Error("Unexpected reply returned", resp) @@ -202,7 +202,7 @@ func testActionSPing(t *testing.T) { func testActionSSettActionProfile(t *testing.T) { actPrf = &ActionProfileWithCache{ ActionProfileWithOpts: &engine.ActionProfileWithOpts{ - &engine.ActionProfile{ + ActionProfile: &engine.ActionProfile{ Tenant: "tenant_test", ID: "id_test", FilterIDs: nil, @@ -233,12 +233,13 @@ func testActionSSettActionProfile(t *testing.T) { }, }, }, - map[string]interface{}{}, + Opts: map[string]interface{}{}, }, } var result string expErr := utils.ErrNotFound.Error() - if err := actSRPC.Call(utils.APIerSv1GetActionProfile, &utils.TenantID{Tenant: "tenant_test", ID: "id_test"}, &result); err == nil || err.Error() != expErr { + if err := actSRPC.Call(utils.APIerSv1GetActionProfile, &utils.TenantIDWithOpts{ + TenantID: &utils.TenantID{Tenant: "tenant_test", ID: "id_test"}}, &result); err == nil || err.Error() != expErr { t.Errorf("Expected error: %v received: %v", expErr, err) } var reply string @@ -248,7 +249,8 @@ func testActionSSettActionProfile(t *testing.T) { t.Error("Unexpected reply returned", reply) } var reply2 *engine.ActionProfile - if err := actSRPC.Call(utils.APIerSv1GetActionProfile, &utils.TenantID{Tenant: "tenant_test", ID: "id_test"}, &reply2); err != nil { + if err := actSRPC.Call(utils.APIerSv1GetActionProfile, &utils.TenantIDWithOpts{ + TenantID: &utils.TenantID{Tenant: "tenant_test", ID: "id_test"}}, &reply2); err != nil { t.Error(err) } else if !reflect.DeepEqual(actPrf.ActionProfile, reply2) { t.Errorf("Expecting : %+v, received: %+v", actPrf.ActionProfile, reply2) @@ -301,7 +303,8 @@ func testActionSUpdateActionProfile(t *testing.T) { t.Error("Unexpected reply returned", reply) } var reply2 *engine.ActionProfile - if err := actSRPC.Call(utils.APIerSv1GetActionProfile, &utils.TenantID{Tenant: "tenant_test", ID: "id_test"}, &reply2); err != nil { + if err := actSRPC.Call(utils.APIerSv1GetActionProfile, &utils.TenantIDWithOpts{ + TenantID: &utils.TenantID{Tenant: "tenant_test", ID: "id_test"}}, &reply2); err != nil { t.Error(err) } else if !reflect.DeepEqual(actPrf.ActionProfile, reply2) { t.Errorf("Expecting : %+v, received: %+v", actPrf.ActionProfile, reply2) @@ -317,7 +320,8 @@ func testActionSRemoveActionProfile(t *testing.T) { } var reply2 *engine.ActionProfile expErr := utils.ErrNotFound.Error() - if err := actSRPC.Call(utils.APIerSv1GetActionProfile, &utils.TenantID{Tenant: "tenant_test", ID: "id_test"}, &reply2); err == nil || err.Error() != expErr { + if err := actSRPC.Call(utils.APIerSv1GetActionProfile, &utils.TenantIDWithOpts{ + TenantID: &utils.TenantID{Tenant: "tenant_test", ID: "id_test"}}, &reply2); err == nil || err.Error() != expErr { t.Errorf("Expected error: %v received: %v", expErr, err) } if err := actSRPC.Call(utils.APIerSv1RemoveActionProfile, &utils.TenantIDWithCache{Tenant: "tenant_test", ID: "id_test"}, &reply2); err == nil || err.Error() != expErr { diff --git a/apier/v1/apier_it_test.go b/apier/v1/apier_it_test.go index 6efe1364c..6195efb4c 100644 --- a/apier/v1/apier_it_test.go +++ b/apier/v1/apier_it_test.go @@ -760,7 +760,7 @@ func testApierTPAccountActions(t *testing.T) { // Check missing params if err := rater.Call(utils.APIerSv1SetTPAccountActions, new(utils.TPAccountActions), &reply); err == nil { t.Error("Calling APIerSv1.SetTPAccountActions, expected error, received: ", reply) - } else if err.Error() != "MANDATORY_IE_MISSING: [TPid LoadId Tenant Account ActionPlanId]" { + } else if err.Error() != "MANDATORY_IE_MISSING: [TPid LoadId Account ActionPlanId]" { t.Error("Calling APIerSv1.SetTPAccountActions got unexpected error: ", err.Error()) } // Test get @@ -842,7 +842,7 @@ func testApierLoadAccountActions(t *testing.T) { expectedStats[utils.CacheAccountActionPlans].Items = 1 expectedStats[utils.CacheActionPlans].Items = 1 expectedStats[utils.CacheActions].Items = 1 - expectedStats[utils.CacheLoadIDs].Items = 6 + expectedStats[utils.CacheLoadIDs].Items = 8 expectedStats[utils.CacheRPCConnections].Items = 1 if err := rater.Call(utils.CacheSv1GetCacheStats, new(utils.AttrCacheIDsWithOpts), &rcvStats); err != nil { t.Error("Got error on CacheSv1.GetCacheStats: ", err.Error()) @@ -880,7 +880,7 @@ func testApierSetRatingProfile(t *testing.T) { expectedStats[utils.CacheActions].Items = 1 expectedStats[utils.CacheRatingProfiles].Items = 1 expectedStats[utils.CacheRPCConnections].Items = 1 - expectedStats[utils.CacheLoadIDs].Items = 6 + expectedStats[utils.CacheLoadIDs].Items = 8 if err := rater.Call(utils.CacheSv1GetCacheStats, new(utils.AttrCacheIDsWithOpts), &rcvStats); err != nil { t.Error("Got error on CacheSv1.GetCacheStats: ", err.Error()) } else if !reflect.DeepEqual(expectedStats, rcvStats) { @@ -1031,7 +1031,7 @@ func testApierReloadCache(t *testing.T) { expectedStats[utils.CacheRatingProfiles].Items = 3 expectedStats[utils.CacheRatingPlans].Items = 1 expectedStats[utils.CacheReverseDestinations].Items = 10 - expectedStats[utils.CacheLoadIDs].Items = 6 + expectedStats[utils.CacheLoadIDs].Items = 8 expectedStats[utils.CacheRPCConnections].Items = 1 if err := rater.Call(utils.CacheSv1GetCacheStats, new(utils.AttrCacheIDsWithOpts), &rcvStats); err != nil { t.Error("Got error on CacheSv1.GetCacheStats: ", err.Error()) diff --git a/apier/v1/triggers.go b/apier/v1/triggers.go index d7ccdd9c1..b51f65437 100644 --- a/apier/v1/triggers.go +++ b/apier/v1/triggers.go @@ -402,40 +402,45 @@ type AttrRemoveActionTrigger struct { UniqueID string } -func (apierSv1 *APIerSv1) RemoveActionTrigger(attr AttrRemoveActionTrigger, reply *string) error { +func (apierSv1 *APIerSv1) RemoveActionTrigger(attr AttrRemoveActionTrigger, reply *string) (err error) { if missing := utils.MissingStructFields(&attr, []string{"GroupID"}); len(missing) != 0 { return utils.NewErrMandatoryIeMissing(missing...) } if attr.UniqueID == "" { - err := apierSv1.DataManager.RemoveActionTriggers(attr.GroupID, utils.NonTransactional) + err = apierSv1.DataManager.RemoveActionTriggers(attr.GroupID, utils.NonTransactional) if err != nil { - *reply = err.Error() - } else { - *reply = utils.OK + return } - return err - } else { - atrs, err := apierSv1.DataManager.GetActionTriggers(attr.GroupID, false, utils.NonTransactional) - if err != nil { - *reply = err.Error() - return err - } - var remainingAtrs engine.ActionTriggers - for _, atr := range atrs { - if atr.UniqueID == attr.UniqueID { - continue - } + *reply = utils.OK + return + } + var atrs engine.ActionTriggers + if atrs, err = apierSv1.DataManager.GetActionTriggers(attr.GroupID, false, utils.NonTransactional); err != nil { + return + } + remainingAtrs := make(engine.ActionTriggers, 0, len(atrs)) + for _, atr := range atrs { + if atr.UniqueID != attr.UniqueID { remainingAtrs = append(remainingAtrs, atr) } - // set the cleared list back - err = apierSv1.DataManager.SetActionTriggers(attr.GroupID, remainingAtrs, utils.NonTransactional) - if err != nil { - *reply = err.Error() - } else { - *reply = utils.OK - } - return err } + // set the cleared list back + if err = apierSv1.DataManager.SetActionTriggers(attr.GroupID, remainingAtrs, utils.NonTransactional); err != nil { + return + } + // CacheReload + if err = apierSv1.ConnMgr.Call(apierSv1.Config.ApierCfg().CachesConns, nil, + utils.CacheSv1ReloadCache, utils.AttrReloadCacheWithOpts{ + ArgsCache: map[string][]string{utils.ActionTriggerIDs: {attr.GroupID}}, + }, reply); err != nil { + return + } + // generate a loadID for CacheActionTriggers and store it in database + if err = apierSv1.DataManager.SetLoadIDs(map[string]int64{utils.CacheActionTriggers: time.Now().UnixNano()}); err != nil { + return utils.APIErrorHandler(err) + } + *reply = utils.OK + return } // SetActionTrigger updates a ActionTrigger @@ -446,7 +451,7 @@ func (apierSv1 *APIerSv1) SetActionTrigger(attr AttrSetActionTrigger, reply *str atrs, _ := apierSv1.DataManager.GetActionTriggers(attr.GroupID, false, utils.NonTransactional) var newAtr *engine.ActionTrigger - if attr.UniqueID != "" { + if attr.UniqueID != utils.EmptyString { //search for exiting one for _, atr := range atrs { if atr.UniqueID == attr.UniqueID { @@ -473,7 +478,17 @@ func (apierSv1 *APIerSv1) SetActionTrigger(attr AttrSetActionTrigger, reply *str if err = apierSv1.DataManager.SetActionTriggers(attr.GroupID, atrs, utils.NonTransactional); err != nil { return } - //no cache for action triggers + // CacheReload + if err = apierSv1.ConnMgr.Call(apierSv1.Config.ApierCfg().CachesConns, nil, + utils.CacheSv1ReloadCache, utils.AttrReloadCacheWithOpts{ + ArgsCache: map[string][]string{utils.ActionTriggerIDs: {attr.GroupID}}, + }, reply); err != nil { + return + } + // generate a loadID for CacheActionTriggers and store it in database + if err = apierSv1.DataManager.SetLoadIDs(map[string]int64{utils.CacheActionTriggers: time.Now().UnixNano()}); err != nil { + return utils.APIErrorHandler(err) + } *reply = utils.OK return } diff --git a/data/conf/samples/replication/internal/cgrates.json b/data/conf/samples/replication/internal/cgrates.json index ad66dd76a..65fb9a23c 100644 --- a/data/conf/samples/replication/internal/cgrates.json +++ b/data/conf/samples/replication/internal/cgrates.json @@ -27,7 +27,6 @@ {"address": "127.0.0.1:2032", "transport":"*json"} ], } - }, diff --git a/data/conf/samples/replication/internal_gob/cgrates.json b/data/conf/samples/replication/internal_gob/cgrates.json index b829a4963..534a640ca 100644 --- a/data/conf/samples/replication/internal_gob/cgrates.json +++ b/data/conf/samples/replication/internal_gob/cgrates.json @@ -13,57 +13,59 @@ "rpc_conns": { - "conn1": { - "strategy": "*first", - "conns": [{"address": "127.0.0.1:2033", "transport":"*gob"}], - }, "conn2": { - "strategy": "*broadcast", + "strategy": "*broadcast_sync", "conns": [ {"address": "127.0.0.1:2023", "transport":"*gob"}, {"address": "127.0.0.1:2033", "transport":"*gob"} - ], + ] + }, + "connCache": { + "strategy": "*broadcast_sync",// be brodcast sync in test + "conns": [ + {"address": "127.0.0.1:2023", "transport":"*gob"}, + {"address": "127.0.0.1:2033", "transport":"*gob"} + ] } }, "data_db": { "db_type": "*internal", - "remote_conns": ["conn1"], "replication_conns": ["conn2"], "items":{ - "*accounts":{"remote":true,"replicate":true}, - "*reverse_destinations": {"remote":true,"replicate":true}, - "*destinations": {"remote":true,"replicate":true}, - "*rating_plans": {"remote":true,"replicate":true}, - "*rating_profiles":{"remote":true,"replicate":true}, - "*actions":{"remote":true,"replicate":true}, - "*action_plans": {"remote":true,"replicate":true}, - "*account_action_plans":{"remote":true,"replicate":true}, - "*action_triggers":{"remote":true,"replicate":true}, - "*shared_groups":{"remote":true,"replicate":true}, - "*timings": {"remote":true,"replicate":true}, - "*resource_profiles":{"remote":true,"replicate":true}, - "*resources":{"remote":true,"replicate":true}, - "*statqueue_profiles": {"remote":true,"replicate":true}, - "*statqueues": {"remote":true,"replicate":true}, - "*threshold_profiles": {"remote":true,"replicate":true}, - "*thresholds": {"remote":true,"replicate":true}, - "*filters": {"remote":true,"replicate":true}, - "*route_profiles":{"remote":true,"replicate":true}, - "*attribute_profiles":{"remote":true,"replicate":true}, - "*charger_profiles": {"remote":true,"replicate":true}, - "*dispatcher_profiles":{"remote":true,"replicate":true}, - "*dispatcher_hosts":{"remote":true,"replicate":true}, - "*indexes" :{"remote":true,"replicate":true}, + "*accounts":{"remote":false,"replicate":true}, + "*reverse_destinations": {"remote":false,"replicate":true}, + "*destinations": {"remote":false,"replicate":true}, + "*rating_plans": {"remote":false,"replicate":true}, + "*rating_profiles":{"remote":false,"replicate":true}, + "*actions":{"remote":false,"replicate":true}, + "*action_plans": {"remote":false,"replicate":true}, + "*account_action_plans":{"remote":false,"replicate":true}, + "*action_triggers":{"remote":false,"replicate":true}, + "*shared_groups":{"remote":false,"replicate":true}, + "*timings": {"remote":false,"replicate":true}, + "*resource_profiles":{"remote":false,"replicate":true}, + "*resources":{"remote":false,"replicate":true}, + "*statqueue_profiles": {"remote":false,"replicate":true}, + "*statqueues": {"remote":false,"replicate":true}, + "*threshold_profiles": {"remote":false,"replicate":true}, + "*thresholds": {"remote":false,"replicate":true}, + "*filters": {"remote":false,"replicate":true}, + "*route_profiles":{"remote":false,"replicate":true}, + "*attribute_profiles":{"remote":false,"replicate":true}, + "*charger_profiles": {"remote":false,"replicate":true}, + "*dispatcher_profiles":{"remote":false,"replicate":true}, + "*dispatcher_hosts":{"remote":false,"replicate":true}, + "*indexes" :{"remote":false,"replicate":true}, "*rate_profiles":{"remote":false,"replicate":true}, - "*load_ids":{"remote":true,"replicate":true}, - }, + "*load_ids":{"remote":false,"replicate":true}, + } }, "stor_db": { - "db_type": "*internal", + "db_type": "*internal", }, @@ -85,12 +87,6 @@ }, -"stats": { - "enabled": false, - "store_interval": "-1", -}, - - "schedulers": { "enabled": true, }, @@ -99,7 +95,7 @@ "apiers": { "enabled": true, "scheduler_conns": ["*internal"], -}, - + "caches_conns":["connCache"], +} } diff --git a/dispatchers/actions_it_test.go b/dispatchers/actions_it_test.go index 8ee2bdbe5..d5405cc14 100644 --- a/dispatchers/actions_it_test.go +++ b/dispatchers/actions_it_test.go @@ -59,7 +59,7 @@ func TestDspActionSIT(t *testing.T) { func testDspActPrfPing(t *testing.T) { var reply string - if err := allEngine.RPC.Call(utils.ActionSv1Ping, new(utils.CGREvent), &reply); err != nil { + if err := allEngine.RPC.Call(utils.ActionSv1Ping, new(utils.CGREventWithOpts), &reply); err != nil { t.Error(err) } else if reply != utils.Pong { t.Errorf("Received: %s", reply) diff --git a/engine/eventcost.go b/engine/eventcost.go index e6d83a7ed..eb858cbab 100644 --- a/engine/eventcost.go +++ b/engine/eventcost.go @@ -182,7 +182,8 @@ func (ec *EventCost) ratingIDForRateInterval(ri *RateInterval, rf RatingMatchedF MaxCostStrategy: ri.Rating.MaxCostStrategy, TimingID: tmID, RatesID: rtUUID, - RatingFiltersID: rfUUID}) + RatingFiltersID: rfUUID, + }) } func (ec *EventCost) rateIntervalForRatingID(ratingID string) (ri *RateInterval) { diff --git a/engine/timespans.go b/engine/timespans.go index 08ac76a83..f21fc18b6 100644 --- a/engine/timespans.go +++ b/engine/timespans.go @@ -31,15 +31,18 @@ import ( A unit in which a call will be split that has a specific price related interval attached to it. */ type TimeSpan struct { - TimeStart, TimeEnd time.Time - Cost float64 - RateInterval *RateInterval - DurationIndex time.Duration // the call duration so far till TimeEnd - Increments Increments - RoundIncrement *Increment - MatchedSubject, MatchedPrefix, MatchedDestId, RatingPlanId string - CompressFactor int - ratingInfo *RatingInfo + TimeStart, TimeEnd time.Time + Cost float64 + RateInterval *RateInterval + DurationIndex time.Duration // the call duration so far till TimeEnd + Increments Increments + RoundIncrement *Increment + MatchedSubject string + MatchedPrefix string + MatchedDestId string + RatingPlanId string + CompressFactor int + ratingInfo *RatingInfo } type Increment struct { diff --git a/engine/tpreader.go b/engine/tpreader.go index 9ca7fe4e2..4eb3c66ac 100644 --- a/engine/tpreader.go +++ b/engine/tpreader.go @@ -894,10 +894,19 @@ func (tpr *TpReader) LoadAccountActionsFiltered(qriedAA *utils.TPAccountActions) actionIDs = append(actionIDs, atr.ActionsID) } // write action triggers - err = tpr.dm.SetActionTriggers(accountAction.ActionTriggersId, actionTriggers, utils.NonTransactional) - if err != nil { + if err = tpr.dm.SetActionTriggers(accountAction.ActionTriggersId, + actionTriggers, utils.NonTransactional); err != nil { return errors.New(err.Error() + " (SetActionTriggers): " + accountAction.ActionTriggersId) } + var reply string + if err := connMgr.Call(tpr.cacheConns, nil, + utils.CacheSv1ReloadCache, utils.AttrReloadCacheWithOpts{ + ArgsCache: map[string][]string{ + utils.ActionTriggerIDs: {accountAction.ActionTriggersId}, + }, + }, &reply); err != nil { + return err + } } // actions @@ -1007,7 +1016,13 @@ func (tpr *TpReader) LoadAccountActionsFiltered(qriedAA *utils.TPAccountActions) if err = tpr.dm.SetActions(k, as, utils.NonTransactional); err != nil { return err } - if err = dm.CacheDataFromDB(utils.ACTION_PREFIX, []string{k}, true); err != nil { + var reply string + if err := connMgr.Call(tpr.cacheConns, nil, + utils.CacheSv1ReloadCache, utils.AttrReloadCacheWithOpts{ + ArgsCache: map[string][]string{ + utils.ActionIDs: {k}, + }, + }, &reply); err != nil { return err } } diff --git a/general_tests/export_it_test.go b/general_tests/export_it_test.go index 06549ca87..ecf3765ff 100644 --- a/general_tests/export_it_test.go +++ b/general_tests/export_it_test.go @@ -248,6 +248,9 @@ func testExpVerifyResources(t *testing.T) { Weight: 10, ThresholdIDs: []string{}, } + if *encoding == utils.MetaGOB { + rPrf.ThresholdIDs = nil + } var reply *engine.ResourceProfile if err := expRpc.Call(utils.APIerSv1GetResourceProfile, &utils.TenantID{Tenant: "cgrates.org", ID: "RES_ACNT_1001"}, &reply); err != nil { @@ -392,8 +395,11 @@ func testExpVerifyRateProfiles(t *testing.T) { }, } - if err := expRpc.Call(utils.APIerSv1GetRateProfile, - &utils.TenantID{Tenant: "cgrates.org", ID: "RT_SPECIAL_1002"}, &reply); err != nil { + if *encoding == utils.MetaGOB { + splPrf.FilterIDs = nil + } + if err := expRpc.Call(utils.APIerSv1GetRateProfile, &utils.TenantIDWithOpts{ + TenantID: &utils.TenantID{Tenant: "cgrates.org", ID: "RT_SPECIAL_1002"}}, &reply); err != nil { t.Fatal(err) } if !reflect.DeepEqual(splPrf, reply) { @@ -412,7 +418,7 @@ func testExpVerifyActionProfiles(t *testing.T) { Schedule: utils.ASAP, AccountIDs: utils.StringSet{"1001": {}, "1002": {}}, Actions: []*engine.APAction{ - &engine.APAction{ + { ID: "TOPUP", FilterIDs: []string{}, Type: utils.TOPUP, @@ -420,28 +426,28 @@ func testExpVerifyActionProfiles(t *testing.T) { Value: config.NewRSRParsersMustCompile("10", utils.INFIELD_SEP), }, - &engine.APAction{ + { ID: "SET_BALANCE_TEST_DATA", FilterIDs: []string{}, Type: utils.SET_BALANCE, Path: utils.DynamicDataPrefix + utils.COUNTER_BALANCE + utils.NestingSep + "TestDataBalance" + utils.NestingSep + utils.Type, Value: config.NewRSRParsersMustCompile(utils.DATA, utils.INFIELD_SEP), }, - &engine.APAction{ + { ID: "TOPUP_TEST_DATA", FilterIDs: []string{}, Type: utils.TOPUP, Path: utils.DynamicDataPrefix + utils.COUNTER_BALANCE + utils.NestingSep + "TestDataBalance" + utils.NestingSep + utils.Value, Value: config.NewRSRParsersMustCompile("1024", utils.INFIELD_SEP), }, - &engine.APAction{ + { ID: "SET_BALANCE_TEST_VOICE", FilterIDs: []string{}, Type: utils.SET_BALANCE, Path: utils.DynamicDataPrefix + utils.COUNTER_BALANCE + utils.NestingSep + "TestVoiceBalance" + utils.NestingSep + utils.Type, Value: config.NewRSRParsersMustCompile(utils.VOICE, utils.INFIELD_SEP), }, - &engine.APAction{ + { ID: "TOPUP_TEST_VOICE", FilterIDs: []string{}, Type: utils.TOPUP, @@ -450,9 +456,14 @@ func testExpVerifyActionProfiles(t *testing.T) { }, }, } - - if err := expRpc.Call(utils.APIerSv1GetActionProfile, - &utils.TenantID{Tenant: "cgrates.org", ID: "ONE_TIME_ACT"}, &reply); err != nil { + if *encoding == utils.MetaGOB { + actPrf.FilterIDs = nil + for _, act := range actPrf.Actions { + act.FilterIDs = nil + } + } + if err := expRpc.Call(utils.APIerSv1GetActionProfile, &utils.TenantIDWithOpts{ + TenantID: &utils.TenantID{Tenant: "cgrates.org", ID: "ONE_TIME_ACT"}}, &reply); err != nil { t.Fatal(err) } else { for _, act := range reply.Actions { // the path variable from RSRParsers is with lower letter and need to be compiled manually in tests to pass reflect.DeepEqual diff --git a/services/actions.go b/services/actions.go index 78eac33db..20ffd7e9e 100644 --- a/services/actions.go +++ b/services/actions.go @@ -47,6 +47,7 @@ func NewActionService(cfg *config.CGRConfig, dm *DataDBService, server: server, anz: anz, srvDep: srvDep, + rldChan: make(chan struct{}), } } @@ -59,6 +60,9 @@ type ActionService struct { filterSChan chan *engine.FilterS server *cores.Server + rldChan chan struct{} + stopChan chan struct{} + acts *actions.ActionS rpc *v1.ActionSv1 // useful on restart connChan chan rpcclient.ClientConnector // publish the internal Subsystem when available @@ -84,6 +88,8 @@ func (acts *ActionService) Start() (err error) { acts.Lock() defer acts.Unlock() acts.acts = actions.NewActionS(acts.cfg, filterS, datadb) + acts.stopChan = make(chan struct{}) + go acts.acts.ListenAndServe(acts.stopChan, acts.rldChan) utils.Logger.Info(fmt.Sprintf("<%s> starting <%s> subsystem", utils.CoreS, utils.AttributeS)) acts.rpc = v1.NewActionSv1(acts.acts) @@ -96,6 +102,7 @@ func (acts *ActionService) Start() (err error) { // Reload handles the change of config func (acts *ActionService) Reload() (err error) { + acts.rldChan <- struct{}{} return // for the moment nothing to reload } @@ -103,6 +110,7 @@ func (acts *ActionService) Reload() (err error) { func (acts *ActionService) Shutdown() (err error) { acts.Lock() defer acts.Unlock() + close(acts.stopChan) if err = acts.acts.Shutdown(); err != nil { return }