diff --git a/config/attributescfg.go b/config/attributescfg.go index d580312c3..ffddae436 100644 --- a/config/attributescfg.go +++ b/config/attributescfg.go @@ -23,6 +23,9 @@ import "github.com/cgrates/cgrates/utils" // AttributeSCfg is the configuration of attribute service type AttributeSCfg struct { Enabled bool + ResourceSConns []string + StatSConns []string + ApierSConns []string IndexedSelects bool StringIndexedFields *[]string PrefixIndexedFields *[]string @@ -38,6 +41,39 @@ func (alS *AttributeSCfg) loadFromJsonCfg(jsnCfg *AttributeSJsonCfg) (err error) if jsnCfg.Enabled != nil { alS.Enabled = *jsnCfg.Enabled } + if jsnCfg.Stats_conns != nil { + alS.StatSConns = make([]string, len(*jsnCfg.Stats_conns)) + for idx, connID := range *jsnCfg.Stats_conns { + // if we have the connection internal we change the name so we can have internal rpc for each subsystem + if connID == utils.MetaInternal { + alS.StatSConns[idx] = utils.ConcatenatedKey(utils.MetaInternal, utils.MetaStatS) + } else { + alS.StatSConns[idx] = connID + } + } + } + if jsnCfg.Resources_conns != nil { + alS.ResourceSConns = make([]string, len(*jsnCfg.Resources_conns)) + for idx, connID := range *jsnCfg.Resources_conns { + // if we have the connection internal we change the name so we can have internal rpc for each subsystem + if connID == utils.MetaInternal { + alS.ResourceSConns[idx] = utils.ConcatenatedKey(utils.MetaInternal, utils.MetaResources) + } else { + alS.ResourceSConns[idx] = connID + } + } + } + if jsnCfg.Apiers_conns != nil { + alS.ApierSConns = make([]string, len(*jsnCfg.Apiers_conns)) + for idx, connID := range *jsnCfg.Apiers_conns { + // if we have the connection internal we change the name so we can have internal rpc for each subsystem + if connID == utils.MetaInternal { + alS.ApierSConns[idx] = utils.ConcatenatedKey(utils.MetaInternal, utils.MetaApier) + } else { + alS.ApierSConns[idx] = connID + } + } + } if jsnCfg.Indexed_selects != nil { alS.IndexedSelects = *jsnCfg.Indexed_selects } @@ -74,6 +110,9 @@ func (alS *AttributeSCfg) loadFromJsonCfg(jsnCfg *AttributeSJsonCfg) (err error) func (alS *AttributeSCfg) AsMapInterface() (initialMP map[string]interface{}) { initialMP = map[string]interface{}{ utils.EnabledCfg: alS.Enabled, + utils.StatSConnsCfg: alS.StatSConns, + utils.ResourceSConnsCfg: alS.ResourceSConns, + utils.ApierSConnsCfg: alS.ApierSConns, utils.IndexedSelectsCfg: alS.IndexedSelects, utils.ProcessRunsCfg: alS.ProcessRuns, utils.NestedFieldsCfg: alS.NestedFields, diff --git a/config/attributescfg_test.go b/config/attributescfg_test.go index c0b011e5b..a41ab4c1a 100644 --- a/config/attributescfg_test.go +++ b/config/attributescfg_test.go @@ -36,6 +36,9 @@ func TestAttributeSCfgloadFromJsonCfg(t *testing.T) { } expected := &AttributeSCfg{ Enabled: true, + ApierSConns: []string{}, + StatSConns: []string{}, + ResourceSConns: []string{}, IndexedSelects: false, StringIndexedFields: &[]string{"*req.index1"}, PrefixIndexedFields: &[]string{"*req.index1", "*req.index2"}, @@ -63,6 +66,9 @@ func TestAttributeSCfgAsMapInterface(t *testing.T) { }` eMap := map[string]interface{}{ utils.EnabledCfg: true, + utils.StatSConnsCfg: []string{}, + utils.ResourceSConnsCfg: []string{}, + utils.ApierSConnsCfg: []string{}, utils.StringIndexedFieldsCfg: []string{"*req.index1"}, utils.PrefixIndexedFieldsCfg: []string{"*req.index1", "*req.index2"}, utils.ProcessRunsCfg: 3, @@ -88,6 +94,9 @@ func TestAttributeSCfgAsMapInterface2(t *testing.T) { }` expectedMap := map[string]interface{}{ utils.EnabledCfg: true, + utils.StatSConnsCfg: []string{}, + utils.ResourceSConnsCfg: []string{}, + utils.ApierSConnsCfg: []string{}, utils.IndexedSelectsCfg: true, utils.PrefixIndexedFieldsCfg: []string{}, utils.SuffixIndexedFieldsCfg: []string{"*req.index1", "*req.index2"}, @@ -109,6 +118,9 @@ func TestAttributeSCfgAsMapInterface3(t *testing.T) { ` expectedMap := map[string]interface{}{ utils.EnabledCfg: false, + utils.StatSConnsCfg: []string{}, + utils.ResourceSConnsCfg: []string{}, + utils.ApierSConnsCfg: []string{}, utils.IndexedSelectsCfg: true, utils.PrefixIndexedFieldsCfg: []string{}, utils.SuffixIndexedFieldsCfg: []string{}, diff --git a/config/config_defaults.go b/config/config_defaults.go index 9f2d3157f..a5a248f1b 100755 --- a/config/config_defaults.go +++ b/config/config_defaults.go @@ -536,7 +536,10 @@ const CGRATES_CFG_JSON = ` "attributes": { // AttributeS config - "enabled": false, // starts attribute service: . + "enabled": false, // starts attribute service: + "stats_conns": [], // connections to StatS, empty to disable: <""|*internal|$rpc_conns_id> + "resources_conns": [], // connections to ResourceS, empty to disable: <""|*internal|$rpc_conns_id> + "apiers_conns": [], // connections to ApierS, empty to disable: <""|*internal|$rpc_conns_id> "indexed_selects": true, // enable profile matching exclusively on indexes //"string_indexed_fields": [], // query indexes based on these fields for faster processing "prefix_indexed_fields": [], // query indexes based on these fields for faster processing diff --git a/config/config_it_test.go b/config/config_it_test.go index b1851f909..5f3988b53 100644 --- a/config/config_it_test.go +++ b/config/config_it_test.go @@ -134,6 +134,9 @@ func testCGRConfigReloadAttributeS(t *testing.T) { } expAttr := &AttributeSCfg{ Enabled: true, + ApierSConns: []string{}, + ResourceSConns: []string{}, + StatSConns: []string{}, StringIndexedFields: &[]string{utils.MetaReq + utils.NestingSep + utils.Account}, PrefixIndexedFields: &[]string{}, SuffixIndexedFields: &[]string{}, diff --git a/config/config_json_test.go b/config/config_json_test.go index 41c022c39..35544f70e 100755 --- a/config/config_json_test.go +++ b/config/config_json_test.go @@ -825,12 +825,15 @@ func TestDNSAgentJsonCfg(t *testing.T) { func TestDfAttributeServJsonCfg(t *testing.T) { eCfg := &AttributeSJsonCfg{ Enabled: utils.BoolPointer(false), + Stats_conns: &[]string{}, + Resources_conns: &[]string{}, + Apiers_conns: &[]string{}, Indexed_selects: utils.BoolPointer(true), String_indexed_fields: nil, Prefix_indexed_fields: &[]string{}, Suffix_indexed_fields: &[]string{}, - Process_runs: utils.IntPointer(1), Nested_fields: utils.BoolPointer(false), + Process_runs: utils.IntPointer(1), } if cfg, err := dfCgrJSONCfg.AttributeServJsonCfg(); err != nil { t.Error(err) diff --git a/config/libconfig_json.go b/config/libconfig_json.go index 332d8eb27..3202a4521 100755 --- a/config/libconfig_json.go +++ b/config/libconfig_json.go @@ -395,6 +395,9 @@ type ReqProcessorJsnCfg struct { // Attribute service config section type AttributeSJsonCfg struct { Enabled *bool + Stats_conns *[]string + Resources_conns *[]string + Apiers_conns *[]string Indexed_selects *bool String_indexed_fields *[]string Prefix_indexed_fields *[]string diff --git a/engine/attributes.go b/engine/attributes.go index 55dbc5432..946f277e0 100644 --- a/engine/attributes.go +++ b/engine/attributes.go @@ -235,18 +235,21 @@ func (alS *AttributeService) processEvent(args *AttrArgsProcessEvent, evNm utils case utils.META_CONSTANT: substitute, err = attribute.Value.ParseValue(utils.EmptyString) case utils.MetaVariable, utils.META_COMPOSED: - substitute, err = attribute.Value.ParseDataProvider(evNm) + substitute, err = attribute.Value.ParseDataProvider(newDynamicDP(alS.cgrcfg.AttributeSCfg().ResourceSConns, + alS.cgrcfg.AttributeSCfg().StatSConns, alS.cgrcfg.AttributeSCfg().ApierSConns, args.Tenant, evNm)) case utils.META_USAGE_DIFFERENCE: if len(attribute.Value) != 2 { return nil, fmt.Errorf("invalid arguments <%s>", utils.ToJSON(attribute.Value)) } var strVal1 string - if strVal1, err = attribute.Value[0].ParseDataProvider(evNm); err != nil { + if strVal1, err = attribute.Value[0].ParseDataProvider(newDynamicDP(alS.cgrcfg.AttributeSCfg().ResourceSConns, + alS.cgrcfg.AttributeSCfg().StatSConns, alS.cgrcfg.AttributeSCfg().ApierSConns, args.Tenant, evNm)); err != nil { rply = nil return } var strVal2 string - if strVal2, err = attribute.Value[1].ParseDataProvider(evNm); err != nil { + if strVal2, err = attribute.Value[1].ParseDataProvider(newDynamicDP(alS.cgrcfg.AttributeSCfg().ResourceSConns, + alS.cgrcfg.AttributeSCfg().StatSConns, alS.cgrcfg.AttributeSCfg().ApierSConns, args.Tenant, evNm)); err != nil { rply = nil return } @@ -263,7 +266,8 @@ func (alS *AttributeService) processEvent(args *AttrArgsProcessEvent, evNm utils substitute = tEnd.Sub(tStart).String() case utils.MetaSum: var ifaceVals []interface{} - if ifaceVals, err = attribute.Value.GetIfaceFromValues(evNm); err != nil { + if ifaceVals, err = attribute.Value.GetIfaceFromValues(newDynamicDP(alS.cgrcfg.AttributeSCfg().ResourceSConns, + alS.cgrcfg.AttributeSCfg().StatSConns, alS.cgrcfg.AttributeSCfg().ApierSConns, args.Tenant, evNm)); err != nil { rply = nil return } @@ -275,7 +279,8 @@ func (alS *AttributeService) processEvent(args *AttrArgsProcessEvent, evNm utils substitute = utils.IfaceAsString(ifaceSum) case utils.MetaDifference: var ifaceVals []interface{} - if ifaceVals, err = attribute.Value.GetIfaceFromValues(evNm); err != nil { + if ifaceVals, err = attribute.Value.GetIfaceFromValues(newDynamicDP(alS.cgrcfg.AttributeSCfg().ResourceSConns, + alS.cgrcfg.AttributeSCfg().StatSConns, alS.cgrcfg.AttributeSCfg().ApierSConns, args.Tenant, evNm)); err != nil { rply = nil return } @@ -287,7 +292,8 @@ func (alS *AttributeService) processEvent(args *AttrArgsProcessEvent, evNm utils substitute = utils.IfaceAsString(ifaceSum) case utils.MetaMultiply: var ifaceVals []interface{} - if ifaceVals, err = attribute.Value.GetIfaceFromValues(evNm); err != nil { + if ifaceVals, err = attribute.Value.GetIfaceFromValues(newDynamicDP(alS.cgrcfg.AttributeSCfg().ResourceSConns, + alS.cgrcfg.AttributeSCfg().StatSConns, alS.cgrcfg.AttributeSCfg().ApierSConns, args.Tenant, evNm)); err != nil { rply = nil return } @@ -299,7 +305,8 @@ func (alS *AttributeService) processEvent(args *AttrArgsProcessEvent, evNm utils substitute = utils.IfaceAsString(ifaceSum) case utils.MetaDivide: var ifaceVals []interface{} - if ifaceVals, err = attribute.Value.GetIfaceFromValues(evNm); err != nil { + if ifaceVals, err = attribute.Value.GetIfaceFromValues(newDynamicDP(alS.cgrcfg.AttributeSCfg().ResourceSConns, + alS.cgrcfg.AttributeSCfg().StatSConns, alS.cgrcfg.AttributeSCfg().ApierSConns, args.Tenant, evNm)); err != nil { rply = nil return } @@ -315,7 +322,8 @@ func (alS *AttributeService) processEvent(args *AttrArgsProcessEvent, evNm utils utils.ToJSON(attribute.Value), utils.MetaValueExponent) } var strVal1 string - if strVal1, err = attribute.Value[0].ParseDataProvider(evNm); err != nil { + if strVal1, err = attribute.Value[0].ParseDataProvider(newDynamicDP(alS.cgrcfg.AttributeSCfg().ResourceSConns, + alS.cgrcfg.AttributeSCfg().StatSConns, alS.cgrcfg.AttributeSCfg().ApierSConns, args.Tenant, evNm)); err != nil { rply = nil return } @@ -325,7 +333,8 @@ func (alS *AttributeService) processEvent(args *AttrArgsProcessEvent, evNm utils strVal1, utils.MetaValueExponent) } var strVal2 string - if strVal2, err = attribute.Value[1].ParseDataProvider(evNm); err != nil { + if strVal2, err = attribute.Value[1].ParseDataProvider(newDynamicDP(alS.cgrcfg.AttributeSCfg().ResourceSConns, + alS.cgrcfg.AttributeSCfg().StatSConns, alS.cgrcfg.AttributeSCfg().ApierSConns, args.Tenant, evNm)); err != nil { rply = nil return } @@ -338,7 +347,8 @@ func (alS *AttributeService) processEvent(args *AttrArgsProcessEvent, evNm utils alS.cgrcfg.GeneralCfg().RoundingDecimals, utils.ROUNDING_MIDDLE), 'f', -1, 64) case utils.MetaUnixTimestamp: var val string - if val, err = attribute.Value.ParseDataProvider(evNm); err != nil { + if val, err = attribute.Value.ParseDataProvider(newDynamicDP(alS.cgrcfg.AttributeSCfg().ResourceSConns, + alS.cgrcfg.AttributeSCfg().StatSConns, alS.cgrcfg.AttributeSCfg().ApierSConns, args.Tenant, evNm)); err != nil { rply = nil return } diff --git a/engine/dynamicdp.go b/engine/dynamicdp.go new file mode 100644 index 000000000..c72125058 --- /dev/null +++ b/engine/dynamicdp.go @@ -0,0 +1,125 @@ +/* +Real-time Online/Offline Charging System (OCS) for Telecom & ISP environments +Copyright (C) ITsysCOM GmbH +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. +You should have received a copy of the GNU General Public License +along with this program. If not, see +*/ + +package engine + +import ( + "fmt" + "net" + + "github.com/cgrates/cgrates/config" + "github.com/cgrates/cgrates/utils" +) + +func newDynamicDP(resConns, stsConns, apiConns []string, + tenant string, initialDP utils.DataProvider) *dynamicDP { + return &dynamicDP{ + resConns: resConns, + stsConns: stsConns, + apiConns: apiConns, + tenant: tenant, + initialDP: initialDP, + cache: utils.MapStorage{}, + } +} + +type dynamicDP struct { + resConns []string + stsConns []string + apiConns []string + tenant string + initialDP utils.DataProvider + + cache utils.MapStorage +} + +func (dDP *dynamicDP) String() string { return dDP.initialDP.String() } + +func (dDP *dynamicDP) FieldAsString(fldPath []string) (string, error) { + val, err := dDP.FieldAsInterface(fldPath) + if err != nil { + return "", err + } + return utils.IfaceAsString(val), nil +} + +func (dDP *dynamicDP) RemoteHost() net.Addr { + return utils.LocalAddr() +} + +var initialDPPrefixes = utils.NewStringSet([]string{utils.MetaReq, utils.MetaVars, + utils.MetaCgreq, utils.MetaCgrep, utils.MetaRep, utils.MetaCGRAReq, + utils.MetaAct, utils.MetaEC, utils.MetaUCH, utils.MetaOpts}) + +func (dDP *dynamicDP) FieldAsInterface(fldPath []string) (val interface{}, err error) { + if len(fldPath) == 0 { + return nil, utils.ErrNotFound + } + if initialDPPrefixes.Has(fldPath[0]) { + return dDP.initialDP.FieldAsInterface(fldPath) + } + val, err = dDP.cache.FieldAsInterface(fldPath) + if err == utils.ErrNotFound { // in case not found in cache try to populate it + return dDP.fieldAsInterface(fldPath) + } + return +} + +func (dDP *dynamicDP) fieldAsInterface(fldPath []string) (val interface{}, err error) { + if len(fldPath) < 2 { + return nil, fmt.Errorf("invalid fieldname <%s>", fldPath) + } + switch fldPath[0] { + case utils.MetaAccounts: + // sample of fieldName : ~*accounts.1001.BalanceMap.*monetary[0].Value + // split the field name in 3 parts + // fieldNameType (~*accounts), accountID(1001) and queried part (BalanceMap.*monetary[0].Value) + + var account Account + if err = connMgr.Call(dDP.apiConns, nil, utils.APIerSv2GetAccount, + &utils.AttrGetAccount{Tenant: dDP.tenant, Account: fldPath[1]}, &account); err != nil { + return + } + //construct dataProvider from account and set it further + dp := config.NewObjectDP(account) + dDP.cache.Set(fldPath[:2], dp) + return dp.FieldAsInterface(fldPath[2:]) + case utils.MetaResources: + // sample of fieldName : ~*resources.ResourceID.Field + var reply *Resource + if err := connMgr.Call(dDP.resConns, nil, utils.ResourceSv1GetResource, + &utils.TenantID{Tenant: dDP.tenant, ID: fldPath[1]}, &reply); err != nil { + return nil, err + } + dp := config.NewObjectDP(reply) + dDP.cache.Set(fldPath[:2], dp) + return dp.FieldAsInterface(fldPath[2:]) + case utils.MetaStats: + // sample of fieldName : ~*stats.StatID.*acd + var statValues map[string]float64 + + if err := connMgr.Call(dDP.stsConns, nil, utils.StatSv1GetQueueFloatMetrics, + &utils.TenantIDWithOpts{TenantID: &utils.TenantID{Tenant: dDP.tenant, ID: fldPath[1]}}, + &statValues); err != nil { + return nil, err + } + for k, v := range statValues { + dDP.cache.Set([]string{utils.MetaStats, fldPath[1], k}, v) + } + return dDP.cache.FieldAsInterface(fldPath) + default: // in case of constant we give an empty DataProvider ( empty navigable map ) + } + return nil, utils.ErrNotFound +} diff --git a/engine/filters.go b/engine/filters.go index df99eb2cf..01dcd7169 100644 --- a/engine/filters.go +++ b/engine/filters.go @@ -33,7 +33,6 @@ func NewFilterS(cfg *config.CGRConfig, connMgr *ConnManager, dm *DataManager) (f cfg: cfg, connMgr: connMgr, } - return } @@ -53,7 +52,8 @@ func (fS *FilterS) Pass(tenant string, filterIDs []string, if len(filterIDs) == 0 { return true, nil } - dDP := newDynamicDP(fS.cfg, fS.connMgr, tenant, ev) + dDP := newDynamicDP(fS.cfg.FilterSCfg().ResourceSConns, fS.cfg.FilterSCfg().StatSConns, + fS.cfg.FilterSCfg().ApierSConns, tenant, ev) for _, fltrID := range filterIDs { f, err := fS.dm.GetFilter(tenant, fltrID, true, true, utils.NonTransactional) @@ -117,7 +117,8 @@ func (fS *FilterS) LazyPass(tenant string, filterIDs []string, return true, nil, nil } pass = true - dDP := newDynamicDP(fS.cfg, fS.connMgr, tenant, ev) + dDP := newDynamicDP(fS.cfg.FilterSCfg().ResourceSConns, fS.cfg.FilterSCfg().StatSConns, + fS.cfg.FilterSCfg().ApierSConns, tenant, ev) for _, fltrID := range filterIDs { var f *Filter f, err = fS.dm.GetFilter(tenant, fltrID, @@ -617,104 +618,6 @@ func (fltr *FilterRule) passAPIBan(dDP utils.DataProvider) (bool, error) { return dm.GetAPIBan(strVal, config.CgrConfig().APIBanCfg().Keys, fltr.Values[0] != utils.MetaAll, true, true) } -func newDynamicDP(cfg *config.CGRConfig, connMgr *ConnManager, - tenant string, initialDP utils.DataProvider) *dynamicDP { - return &dynamicDP{ - cfg: cfg, - connMgr: connMgr, - tenant: tenant, - initialDP: initialDP, - cache: utils.MapStorage{}, - } -} - -type dynamicDP struct { - cfg *config.CGRConfig - connMgr *ConnManager - tenant string - initialDP utils.DataProvider - - cache utils.MapStorage -} - -func (dDP *dynamicDP) String() string { return dDP.initialDP.String() } - -func (dDP *dynamicDP) FieldAsString(fldPath []string) (string, error) { - val, err := dDP.FieldAsInterface(fldPath) - if err != nil { - return "", err - } - return utils.IfaceAsString(val), nil -} - -func (dDP *dynamicDP) RemoteHost() net.Addr { - return utils.LocalAddr() -} - -var initialDPPrefixes = utils.NewStringSet([]string{utils.MetaReq, utils.MetaVars, - utils.MetaCgreq, utils.MetaCgrep, utils.MetaRep, utils.MetaCGRAReq, - utils.MetaAct, utils.MetaEC, utils.MetaUCH, utils.MetaOpts}) - -func (dDP *dynamicDP) FieldAsInterface(fldPath []string) (val interface{}, err error) { - if len(fldPath) == 0 { - return nil, utils.ErrNotFound - } - if initialDPPrefixes.Has(fldPath[0]) { - return dDP.initialDP.FieldAsInterface(fldPath) - } - val, err = dDP.cache.FieldAsInterface(fldPath) - if err == utils.ErrNotFound { // in case not found in cache try to populate it - return dDP.fieldAsInterface(fldPath) - } - return -} - -func (dDP *dynamicDP) fieldAsInterface(fldPath []string) (val interface{}, err error) { - if len(fldPath) < 2 { - return nil, fmt.Errorf("invalid fieldname <%s>", fldPath) - } - switch fldPath[0] { - case utils.MetaAccounts: - // sample of fieldName : ~*accounts.1001.BalanceMap.*monetary[0].Value - // split the field name in 3 parts - // fieldNameType (~*accounts), accountID(1001) and quried part (BalanceMap.*monetary[0].Value) - - var account Account - if err = dDP.connMgr.Call(dDP.cfg.FilterSCfg().ApierSConns, nil, utils.APIerSv2GetAccount, - &utils.AttrGetAccount{Tenant: dDP.tenant, Account: fldPath[1]}, &account); err != nil { - return - } - //construct dataProvider from account and set it furthder - dp := config.NewObjectDP(account) - dDP.cache.Set(fldPath[:2], dp) - return dp.FieldAsInterface(fldPath[2:]) - case utils.MetaResources: - // sample of fieldName : ~*resources.ResourceID.Field - var reply *Resource - if err := dDP.connMgr.Call(dDP.cfg.FilterSCfg().ResourceSConns, nil, utils.ResourceSv1GetResource, - &utils.TenantID{Tenant: dDP.tenant, ID: fldPath[1]}, &reply); err != nil { - return nil, err - } - dp := config.NewObjectDP(reply) - dDP.cache.Set(fldPath[:2], dp) - return dp.FieldAsInterface(fldPath[2:]) - case utils.MetaStats: - // sample of fieldName : ~*stats.StatID.*acd - var statValues map[string]float64 - - if err := dDP.connMgr.Call(dDP.cfg.FilterSCfg().StatSConns, nil, utils.StatSv1GetQueueFloatMetrics, - &utils.TenantIDWithOpts{TenantID: &utils.TenantID{Tenant: dDP.tenant, ID: fldPath[1]}}, - &statValues); err != nil { - return nil, err - } - for k, v := range statValues { - dDP.cache.Set([]string{utils.MetaStats, fldPath[1], k}, v) - } - return dDP.cache.FieldAsInterface(fldPath) - default: // in case of constant we give an empty DataProvider ( empty navigable map ) - } - return nil, utils.ErrNotFound -} func verifyInlineFilterS(fltrs []string) (err error) { for _, fl := range fltrs { if strings.HasPrefix(fl, utils.Meta) { diff --git a/engine/routes.go b/engine/routes.go index 4564e19d4..ae81d13fd 100644 --- a/engine/routes.go +++ b/engine/routes.go @@ -496,10 +496,12 @@ func (rpS *RouteService) populateSortingData(ev *utils.CGREvent, route *Route, //filter the route if len(route.lazyCheckRules) != 0 { //construct the DP and pass it to filterS - dynDP := newDynamicDP(rpS.cgrcfg, rpS.connMgr, ev.Tenant, utils.MapStorage{ - utils.MetaReq: ev.Event, - utils.MetaVars: sortedSpl.SortingData, - }) + dynDP := newDynamicDP(rpS.cgrcfg.FilterSCfg().ResourceSConns, rpS.cgrcfg.FilterSCfg().StatSConns, + rpS.cgrcfg.FilterSCfg().ApierSConns, + ev.Tenant, utils.MapStorage{ + utils.MetaReq: ev.Event, + utils.MetaVars: sortedSpl.SortingData, + }) for _, rule := range route.lazyCheckRules { // verify the rules remaining from PartialPass if pass, err = rule.Pass(dynDP); err != nil {