diff --git a/apier/v1/filter_indexes.go b/apier/v1/filter_indexes.go index 1f993d296..cfae9e603 100644 --- a/apier/v1/filter_indexes.go +++ b/apier/v1/filter_indexes.go @@ -327,8 +327,8 @@ func (apierSv1 *APIerSv1) ComputeFilterIndexes(args *utils.ArgsComputeFilterInde } } //AccountProfile Indexes - if args.AccountProfile { - if args.AccountProfile, err = engine.ComputeIndexes(apierSv1.DataManager, tnt, args.Context, utils.CacheAccountProfilesFilterIndexes, + if args.AccountS { + if args.AccountS, err = engine.ComputeIndexes(apierSv1.DataManager, tnt, args.Context, utils.CacheAccountProfilesFilterIndexes, nil, transactionID, func(tnt, id, ctx string) (*[]string, error) { acp, e := apierSv1.DataManager.GetAccountProfile(tnt, id) if e != nil { @@ -344,8 +344,8 @@ func (apierSv1 *APIerSv1) ComputeFilterIndexes(args *utils.ArgsComputeFilterInde } } //ActionProfile Indexes - if args.ActionProfile { - if args.ActionProfile, err = engine.ComputeIndexes(apierSv1.DataManager, tnt, args.Context, utils.CacheActionProfilesFilterIndexes, + if args.ActionS { + if args.ActionS, err = engine.ComputeIndexes(apierSv1.DataManager, tnt, args.Context, utils.CacheActionProfilesFilterIndexes, nil, transactionID, func(tnt, id, ctx string) (*[]string, error) { atp, e := apierSv1.DataManager.GetActionProfile(tnt, id, true, false, utils.NonTransactional) if e != nil { @@ -362,41 +362,32 @@ func (apierSv1 *APIerSv1) ComputeFilterIndexes(args *utils.ArgsComputeFilterInde } } //RateProfile Indexes - if args.RateProfile { - if args.RateProfile, err = engine.ComputeIndexes(apierSv1.DataManager, tnt, args.Context, utils.CacheRateProfilesFilterIndexes, - nil, transactionID, func(tnt, id, ctx string) (*[]string, error) { - rtp, e := apierSv1.DataManager.GetRateProfile(tnt, id, true, false, utils.NonTransactional) - if e != nil { - return nil, e - } - fltrIDs := make([]string, len(rtp.FilterIDs)) - for i, fltrID := range rtp.FilterIDs { - fltrIDs[i] = fltrID - } - return &fltrIDs, nil - - }); err != nil && err != utils.ErrNotFound { - return utils.APIErrorHandler(err) - } - } - //RateProfileRates Indexes if args.RateS { - if args.RateProfile, err = engine.ComputeIndexes(apierSv1.DataManager, tnt, args.Context, utils.CacheRateProfilesFilterIndexes, + if args.RateS, err = engine.ComputeIndexes(apierSv1.DataManager, tnt, args.Context, utils.CacheRateProfilesFilterIndexes, nil, transactionID, func(tnt, id, ctx string) (*[]string, error) { rpr, e := apierSv1.DataManager.GetRateProfile(tnt, id, true, false, utils.NonTransactional) if e != nil { return nil, e } - rate, has := rpr.Rates[id] - if !has { - return nil, nil - } - fltrIDs := make([]string, len(rate.FilterIDs)) - for i, fltrID := range rate.FilterIDs { + fltrIDs := make([]string, len(rpr.FilterIDs)) + for i, fltrID := range rpr.FilterIDs { fltrIDs[i] = fltrID } - return &fltrIDs, nil + ids := make([]string, 0, len(rpr.Rates)) + + for key := range rpr.Rates { + ids = append(ids, key) + } + _, err = engine.ComputeIndexes(apierSv1.DataManager, tnt, id, utils.CacheRateFilterIndexes, + &ids, transactionID, func(_, id, _ string) (*[]string, error) { + rateFilters := make([]string, len(rpr.Rates[id].FilterIDs)) + for i, fltrID := range rpr.Rates[id].FilterIDs { + rateFilters[i] = fltrID + } + return &rateFilters, nil + }) + return &fltrIDs, nil }); err != nil && err != utils.ErrNotFound { return utils.APIErrorHandler(err) } @@ -469,26 +460,20 @@ func (apierSv1 *APIerSv1) ComputeFilterIndexes(args *utils.ArgsComputeFilterInde } } //AccountProfile Indexes - if args.AccountProfile { + if args.AccountS { if err = apierSv1.DataManager.SetIndexes(utils.CacheAccountProfilesFilterIndexes, tnt, nil, true, transactionID); err != nil { return } } //ActionProfile Indexes - if args.ActionProfile { + if args.ActionS { if err = apierSv1.DataManager.SetIndexes(utils.CacheActionProfilesFilterIndexes, tnt, nil, true, transactionID); err != nil { return } } //RateProfile Indexes - if args.RateProfile { - if err = apierSv1.DataManager.SetIndexes(utils.CacheRateProfilesFilterIndexes, tnt, nil, true, transactionID); err != nil { - return - } - } - //RateProfileRate Indexes if args.RateS { - if err = apierSv1.DataManager.SetIndexes(utils.CacheRateFilterIndexes, tntCtx, nil, true, transactionID); err != nil { + if err = apierSv1.DataManager.SetIndexes(utils.CacheRateProfilesFilterIndexes, tnt, nil, true, transactionID); err != nil { return } } @@ -628,7 +613,7 @@ func (apierSv1 *APIerSv1) ComputeFilterIndexIDs(args *utils.ArgsComputeFilterInd } //RateProfileRateIndexes if _, err = engine.ComputeIndexes(apierSv1.DataManager, tnt, args.Context, utils.CacheRateFilterIndexes, - &args.RateIDs, transactionID, func(tnt, id, ctx string) (*[]string, error) { + &args.RateProfileIDs, transactionID, func(tnt, id, ctx string) (*[]string, error) { rpr, e := apierSv1.DataManager.GetRateProfile(tnt, id, true, false, utils.NonTransactional) if e != nil { return nil, e diff --git a/apier/v1/filter_indexes_it_test.go b/apier/v1/filter_indexes_it_test.go index 8ed41f394..22a139d78 100644 --- a/apier/v1/filter_indexes_it_test.go +++ b/apier/v1/filter_indexes_it_test.go @@ -87,6 +87,10 @@ var ( testV1FIRemoveActionProfile, testV1FIdxdxInitDataDb, + testV1FISetRateProfileRatesIndexes, + testV1FIComputeRateProfileRatesIndexes, + testV1FIdxdxInitDataDb, + testV1FIdxSetAttributeProfileIndexes, testV1FIdxComputeAttributeProfileIndexes, testV1FIdxSetSecondAttributeProfileIndexes, @@ -1245,8 +1249,8 @@ func testV1FIComputeAccountProfileIndexes(t *testing.T) { //compute them, to put indexes again in db for the right subsystem if err := tFIdxRpc.Call(utils.APIerSv1ComputeFilterIndexes, &utils.ArgsComputeFilterIndexes{ - Tenant: tenant, - AccountProfile: true, + Tenant: tenant, + AccountS: true, }, &result); err != nil { t.Error(err) } else if result != utils.OK { @@ -1559,8 +1563,8 @@ func testV1FIComputeActionProfileIndexes(t *testing.T) { //compute them, to put indexes again in db for the right subsystem if err := tFIdxRpc.Call(utils.APIerSv1ComputeFilterIndexes, &utils.ArgsComputeFilterIndexes{ - Tenant: tenant, - ActionProfile: true, + Tenant: tenant, + ActionS: true, }, &result); err != nil { t.Error(err) } else if result != utils.OK { @@ -1771,6 +1775,193 @@ func testV1FIRemoveActionProfile(t *testing.T) { } } +func testV1FISetRateProfileRatesIndexes(t *testing.T) { + //set a filter for our rates + filter = &FilterWithCache{ + Filter: &engine.Filter{ + Tenant: tenant, + ID: "RATE_FLTR1", + Rules: []*engine.FilterRule{{ + Type: utils.MetaString, + Element: "~*req.Destination", + Values: []string{"234"}, + }}, + }, + } + var result string + if err := tFIdxRpc.Call(utils.APIerSv1SetFilter, filter, &result); err != nil { + t.Error(err) + } else if result != utils.OK { + t.Error("Unexpected reply returned", result) + } + //there are not any rates in db + var reply *engine.RateProfile + if err := tFIdxRpc.Call(utils.APIerSv1GetRateProfile, + &utils.TenantIDWithOpts{TenantID: &utils.TenantID{Tenant: tenant, ID: "RRATE_PRF"}}, &reply); err == nil || + err.Error() != utils.ErrNotFound.Error() { + t.Error(err) + } + + //set in db a ratePrf with double populated rates with our filter + ratePrfRates := &APIRateProfileWithCache{ + APIRateProfileWithOpts: &engine.APIRateProfileWithOpts{ + APIRateProfile: &engine.APIRateProfile{ + Tenant: "cgrates.org", + ID: "RP1", + FilterIDs: []string{"*string:~*req.Usage:10m"}, + MaxCostStrategy: "*free", + Rates: map[string]*engine.APIRate{ + "RT_WEEK": { + ID: "RT_WEEK", + FilterIDs: []string{"RATE_FLTR1", "*suffix:~*req.Account:1009"}, + ActivationTimes: "* * * * 1-5", + }, + "RT_MONTH": { + ID: "RT_MONTH", + FilterIDs: []string{"RATE_FLTR1"}, + ActivationTimes: "* * * * *", + }, + }, + }, + }, + } + if err := tFIdxRpc.Call(utils.APIerSv1SetRateProfile, ratePrfRates, &result); err != nil { + t.Error(err) + } else if result != utils.OK { + t.Error("Unexpected reply returned", result) + } + expRtPrf, err := ratePrfRates.AsRateProfile() + if err != nil { + t.Error(err) + } + + //get it from db and compare + if err := tFIdxRpc.Call(utils.APIerSv1GetRateProfile, + &utils.TenantIDWithOpts{TenantID: &utils.TenantID{Tenant: tenant, ID: "RP1"}}, + &reply); err != nil { + t.Error(err) + } else { + expRtPrf.Compile() + reply.Compile() + if !reflect.DeepEqual(reply, expRtPrf) { + t.Errorf("Expected %+v \n, received %+v", utils.ToJSON(expRtPrf), utils.ToJSON(reply)) + } + } + + //get indexes to verify if these are indexed well + var indexes []string + expectedIDx := []string{"*suffix:*req.Account:1009:RT_WEEK", "*string:*req.Destination:234:RT_WEEK", + "*string:*req.Destination:234:RT_MONTH"} + if err := tFIdxRpc.Call(utils.APIerSv1GetFilterIndexes, + &AttrGetFilterIndexes{ItemType: utils.MetaRateProfileRates, + Tenant: tenant, Context: "RP1"}, + &indexes); err != nil { + t.Error(err) + } else { + sort.Strings(expectedIDx) + sort.Strings(indexes) + if !reflect.DeepEqual(indexes, expectedIDx) { + t.Errorf("Expected %+v, received %+v", expectedIDx, indexes) + } + } + + //get indexes only with Type *string) + expectedIDx = []string{"*string:*req.Destination:234:RT_WEEK", "*string:*req.Destination:234:RT_MONTH"} + if err := tFIdxRpc.Call(utils.APIerSv1GetFilterIndexes, + &AttrGetFilterIndexes{ItemType: utils.MetaRateProfileRates, Tenant: tenant, + FilterType: utils.MetaString, Context: "RP1"}, + &indexes); err != nil { + t.Error(err) + } else { + sort.Strings(expectedIDx) + sort.Strings(indexes) + if !reflect.DeepEqual(indexes, expectedIDx) { + t.Errorf("Expected %+v, received %+v", expectedIDx, indexes) + } + } + + //get indexes only with Field Destination + expectedIDx = []string{"*string:*req.Destination:234:RT_WEEK", "*string:*req.Destination:234:RT_MONTH"} + if err := tFIdxRpc.Call(utils.APIerSv1GetFilterIndexes, + &AttrGetFilterIndexes{ItemType: utils.MetaRateProfileRates, Tenant: tenant, + FilterField: "*req.Destination", Context: "RP1"}, + &indexes); err != nil { + t.Error(err) + } else { + sort.Strings(expectedIDx) + sort.Strings(indexes) + if !reflect.DeepEqual(indexes, expectedIDx) { + t.Errorf("Expected %+v, received %+v", expectedIDx, indexes) + } + } + + //get indexes only with 1009 Destination + expectedIDx = []string{"*suffix:*req.Account:1009:RT_WEEK"} + if err := tFIdxRpc.Call(utils.APIerSv1GetFilterIndexes, + &AttrGetFilterIndexes{ItemType: utils.MetaRateProfileRates, Tenant: tenant, + FilterValue: "1009", Context: "RP1"}, + &indexes); err != nil { + t.Error(err) + } else { + sort.Strings(expectedIDx) + sort.Strings(indexes) + if !reflect.DeepEqual(indexes, expectedIDx) { + t.Errorf("Expected %+v, received %+v", expectedIDx, indexes) + } + } +} + +func testV1FIComputeRateProfileRatesIndexes(t *testing.T) { + //remove indexes from db + var result string + if err := tFIdxRpc.Call(utils.APIerSv1RemoveFilterIndexes, + &AttrRemFilterIndexes{ItemType: utils.MetaRateProfileRates, + Tenant: tenant, Context: "RP1"}, + &result); err != nil { + t.Error(err) + } else if result != utils.OK { + t.Error("Unexpected result returned", result) + } + + //nothing to get from db + var indexes []string + if err := tFIdxRpc.Call(utils.APIerSv1GetFilterIndexes, + &AttrGetFilterIndexes{ItemType: utils.MetaRateProfileRates, + Tenant: tenant, Context: "RP1"}, + &indexes); err == nil || err.Error() != utils.ErrNotFound.Error() { + t.Errorf("Expected %+v, received %+v", utils.ErrNotFound, err) + } + + //compute them, to put indexes again in db for the right subsystem + if err := tFIdxRpc.Call(utils.APIerSv1ComputeFilterIndexes, + &utils.ArgsComputeFilterIndexes{ + Tenant: tenant, + RateS: true, + }, &result); err != nil { + t.Error(err) + } else if result != utils.OK { + t.Error("Unexpected reply returned", result) + } + + /* + expectedIDx := []string{"*string:*req.ToR:*sms:ACT_PRF", "*string:*req.ToR:*data:ACT_PRF", + "*prefix:*req.Account:1001:ACT_PRF", "*prefix:*req.Account:1002:ACT_PRF"} + if err := tFIdxRpc.Call(utils.APIerSv1GetFilterIndexes, + &AttrGetFilterIndexes{ItemType: utils.MetaRateProfileRates, + Tenant: tenant, Context: "RP1"}, + &indexes); err != nil { + t.Error(err) + } else { + sort.Strings(expectedIDx) + sort.Strings(indexes) + if !reflect.DeepEqual(indexes, expectedIDx) { + t.Errorf("Expected %+v, received %+v", expectedIDx, indexes) + } + } + + */ +} + //AttributeProfile func testV1FIdxSetAttributeProfileIndexes(t *testing.T) { var reply *engine.AttributeProfile diff --git a/utils/apitpdata.go b/utils/apitpdata.go index 336d9f3ea..be6d62a77 100755 --- a/utils/apitpdata.go +++ b/utils/apitpdata.go @@ -945,26 +945,24 @@ type ArgsComputeFilterIndexIDs struct { ThresholdIDs []string ChargerIDs []string DispatcherIDs []string - RateIDs []string RateProfileIDs []string AccountProfileIDs []string ActionProfileIDs []string } type ArgsComputeFilterIndexes struct { - Tenant string - Context string - AttributeS bool - ResourceS bool - StatS bool - RouteS bool - ThresholdS bool - ChargerS bool - DispatcherS bool - RateS bool - RateProfile bool - AccountProfile bool - ActionProfile bool + Tenant string + Context string + AttributeS bool + ResourceS bool + StatS bool + RouteS bool + ThresholdS bool + ChargerS bool + DispatcherS bool + RateS bool + AccountS bool + ActionS bool } // AsActivationTime converts TPActivationInterval into ActivationInterval