diff --git a/apis/accounts_test.go b/apis/accounts_test.go index c035ae1d1..9456e608d 100644 --- a/apis/accounts_test.go +++ b/apis/accounts_test.go @@ -2392,8 +2392,9 @@ func TestAccountsGetAccount(t *testing.T) { dm := engine.NewDataManager(dataDB, nil, connMgr) acc := accounts.NewAccountS(cfg, &engine.FilterS{}, connMgr, dm) accS := NewAccountSv1(acc) + fltrs := engine.NewFilterS(cfg, connMgr, dm) cfg.GeneralCfg().DefaultCaching = utils.MetaNone - admS := NewAdminSv1(cfg, dm, nil) + admS := NewAdminSv1(cfg, dm, nil, fltrs) acc_args := &utils.AccountWithAPIOpts{ Account: &utils.Account{ Tenant: "cgrates.org", diff --git a/apis/libadmin_test.go b/apis/libadmin_test.go index f7fbd56f8..feb6d4fcf 100644 --- a/apis/libadmin_test.go +++ b/apis/libadmin_test.go @@ -109,7 +109,8 @@ func TestCallCache(t *testing.T) { connMgr := engine.NewConnManager(cfg) dataDB := engine.NewInternalDB(nil, nil, cfg.DataDbCfg().Items) dm := engine.NewDataManager(dataDB, nil, connMgr) - admS := NewAdminSv1(cfg, dm, connMgr) + fltrs := engine.NewFilterS(cfg, connMgr, dm) + admS := NewAdminSv1(cfg, dm, connMgr, fltrs) admS.cfg.AdminSCfg().CachesConns = []string{"*internal"} opts := map[string]interface{}{ utils.MetaCache: utils.MetaNone, @@ -148,7 +149,8 @@ func TestCallCacheForRemoveIndexes(t *testing.T) { connMgr := engine.NewConnManager(cfg) dataDB := engine.NewInternalDB(nil, nil, cfg.DataDbCfg().Items) dm := engine.NewDataManager(dataDB, nil, connMgr) - admS := NewAdminSv1(cfg, dm, connMgr) + fltrs := engine.NewFilterS(cfg, connMgr, dm) + admS := NewAdminSv1(cfg, dm, connMgr, fltrs) admS.cfg.AdminSCfg().CachesConns = []string{"*internal"} opts := map[string]interface{}{ utils.MetaCache: utils.MetaNone, @@ -181,7 +183,8 @@ func TestCallCacheForComputeIndexes(t *testing.T) { connMgr := engine.NewConnManager(cfg) dataDB := engine.NewInternalDB(nil, nil, cfg.DataDbCfg().Items) dm := engine.NewDataManager(dataDB, nil, connMgr) - admS := NewAdminSv1(cfg, dm, connMgr) + fltrs := engine.NewFilterS(cfg, connMgr, dm) + admS := NewAdminSv1(cfg, dm, connMgr, fltrs) admS.cfg.AdminSCfg().CachesConns = []string{"*internal"} opts := map[string]interface{}{ utils.MetaCache: utils.MetaNone, @@ -214,7 +217,8 @@ func TestCallCacheMultiple(t *testing.T) { connMgr := engine.NewConnManager(cfg) dataDB := engine.NewInternalDB(nil, nil, cfg.DataDbCfg().Items) dm := engine.NewDataManager(dataDB, nil, connMgr) - admS := NewAdminSv1(cfg, dm, connMgr) + fltrs := engine.NewFilterS(cfg, connMgr, dm) + admS := NewAdminSv1(cfg, dm, connMgr, fltrs) admS.cfg.AdminSCfg().CachesConns = []string{"*internal"} opts := map[string]interface{}{ utils.MetaCache: utils.MetaNone, diff --git a/data/conf/samples/routes_cases_mysql/cgrates.json b/data/conf/samples/routes_cases_mysql/cgrates.json index 654633b95..d5750a198 100644 --- a/data/conf/samples/routes_cases_mysql/cgrates.json +++ b/data/conf/samples/routes_cases_mysql/cgrates.json @@ -12,7 +12,7 @@ "attributes": { "enabled": true, - "stats_conns": ["*localhost"], + "stats_conns": ["*internal"], "resources_conns": ["*localhost"], "accounts_conns": ["*localhost"] }, diff --git a/engine/dynamicdp.go b/engine/dynamicdp.go index 2c9d4078c..41e024692 100644 --- a/engine/dynamicdp.go +++ b/engine/dynamicdp.go @@ -76,6 +76,7 @@ func (dDP *dynamicDP) FieldAsInterface(fldPath []string) (val interface{}, err e 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) @@ -122,9 +123,6 @@ func (dDP *dynamicDP) fieldAsInterface(fldPath []string) (val interface{}, err e return nil, err } for k, v := range statValues { - // if v == utils.DecimalNaN { - // v = utils.NewDecimal(-1, 0) - // } dDP.cache.Set([]string{utils.MetaStats, fldPath[1], k}, v) } return dDP.cache.FieldAsInterface(fldPath) diff --git a/engine/route_cost_sort.go b/engine/route_cost_sort.go index 3cc5fb763..e57fb1543 100644 --- a/engine/route_cost_sort.go +++ b/engine/route_cost_sort.go @@ -79,9 +79,7 @@ func populateCostForRoutes(ctx *context.Context, cfg *config.CGRConfig, acntIDs = append(acntIDs, acntID) } srtRoute.SortingData[utils.AccountIDs] = acntIDs - } else { // query RateS for cost - ev.APIOpts[utils.OptsRatesProfileIDs] = utils.CloneStringSlice(route.RateProfileIDs) var rpCost utils.RateProfileCost if err = connMgr.Call(ctx, cfg.RouteSCfg().RateSConns, @@ -101,9 +99,7 @@ func populateCostForRoutes(ctx *context.Context, cfg *config.CGRConfig, continue } srtRoute.SortingData[utils.RateProfileID] = rpCost.ID - } - if cost != nil { srtRoute.sortingDataDecimal[utils.Cost] = cost } diff --git a/general_tests/route_stats_it_test.go b/general_tests/route_stats_it_test.go index be994df4d..dfd792024 100644 --- a/general_tests/route_stats_it_test.go +++ b/general_tests/route_stats_it_test.go @@ -26,6 +26,7 @@ import ( "reflect" "sort" "testing" + "time" "github.com/cgrates/birpc" "github.com/cgrates/birpc/context" @@ -225,53 +226,53 @@ func testV1RtStatsProcessStatsNotAnswered(t *testing.T) { } func testV1RtStatsGetMetrics(t *testing.T) { - expMetrics := map[string]float64{ - utils.MetaACD: 46400000000, - utils.MetaASR: 60, + expDecimals := map[string]*utils.Decimal{ + utils.MetaACD: utils.NewDecimal(4.64e+10, 0), + utils.MetaASR: utils.NewDecimal(60, 0), } - rplyFloatMetrics := make(map[string]float64) - if err := RtStatsSv1BiRpc.Call(context.Background(), utils.StatSv1GetQueueFloatMetrics, + var rplyDec map[string]*utils.Decimal + if err := RtStatsSv1BiRpc.Call(context.Background(), utils.StatSv1GetQueueDecimalMetrics, &utils.TenantIDWithAPIOpts{ TenantID: &utils.TenantID{ Tenant: "cgrates.org", ID: "STATS_TOP1", }, - }, &rplyFloatMetrics); err != nil { + }, &rplyDec); err != nil { t.Error(err) - } else if !reflect.DeepEqual(rplyFloatMetrics, expMetrics) { - t.Errorf("Expected %v, received %v", utils.ToJSON(expMetrics), utils.ToJSON(rplyFloatMetrics)) + } else if !reflect.DeepEqual(rplyDec, expDecimals) { + t.Errorf("Expected %v, received %v", utils.ToJSON(expDecimals), utils.ToJSON(rplyDec)) } - expMetrics = map[string]float64{ - utils.MetaACD: 44000000000, - utils.MetaASR: 33.33333333333333, + expDecimals = map[string]*utils.Decimal{ + utils.MetaACD: utils.NewDecimal(4.4e+10, 0), + utils.MetaASR: utils.NewDecimal(3333333333333333, 14), } - if err := RtStatsSv1BiRpc.Call(context.Background(), utils.StatSv1GetQueueFloatMetrics, + if err := RtStatsSv1BiRpc.Call(context.Background(), utils.StatSv1GetQueueDecimalMetrics, &utils.TenantIDWithAPIOpts{ TenantID: &utils.TenantID{ Tenant: "cgrates.org", ID: "STATS_TOP2", }, - }, &rplyFloatMetrics); err != nil { + }, &rplyDec); err != nil { t.Error(err) - } else if !reflect.DeepEqual(rplyFloatMetrics, expMetrics) { - t.Errorf("Expected %v, received %v", utils.ToJSON(expMetrics), utils.ToJSON(rplyFloatMetrics)) + } else if !reflect.DeepEqual(expDecimals, rplyDec) { + t.Errorf("Expected %v, received %v", utils.ToJSON(expDecimals), utils.ToJSON(rplyDec)) } - expMetrics = map[string]float64{ - utils.MetaACD: 60000000000, - utils.MetaASR: 100, + expDecimals = map[string]*utils.Decimal{ + utils.MetaACD: utils.NewDecimal(int64(time.Minute), 0), + utils.MetaASR: utils.NewDecimal(100, 0), } - if err := RtStatsSv1BiRpc.Call(context.Background(), utils.StatSv1GetQueueFloatMetrics, + if err := RtStatsSv1BiRpc.Call(context.Background(), utils.StatSv1GetQueueDecimalMetrics, &utils.TenantIDWithAPIOpts{ TenantID: &utils.TenantID{ Tenant: "cgrates.org", ID: "STATS_TOP3", }, - }, &rplyFloatMetrics); err != nil { + }, &rplyDec); err != nil { t.Error(err) - } else if !reflect.DeepEqual(rplyFloatMetrics, expMetrics) { - t.Errorf("Expected %v, received %v", utils.ToJSON(expMetrics), utils.ToJSON(rplyFloatMetrics)) + } else if !reflect.DeepEqual(rplyDec, expDecimals) { + t.Errorf("Expected %v, received %v", utils.ToJSON(expDecimals), utils.ToJSON(rplyDec)) } } diff --git a/go.sum b/go.sum index e3e2f1acb..6757470ab 100644 --- a/go.sum +++ b/go.sum @@ -293,7 +293,6 @@ github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANyt github.com/ishidawataru/sctp v0.0.0-20190922091402-408ec287e38c/go.mod h1:co9pwDoBCm1kGxawmb4sPq0cSIOOWNPT4KnHotMP1Zg= github.com/ishidawataru/sctp v0.0.0-20191218070446-00ab2ac2db07 h1:rw3IAne6CDuVFlZbPOkA7bhxlqawFh7RJJ+CejfMaxE= github.com/ishidawataru/sctp v0.0.0-20191218070446-00ab2ac2db07/go.mod h1:co9pwDoBCm1kGxawmb4sPq0cSIOOWNPT4KnHotMP1Zg= -github.com/jackc/chunkreader v1.0.0 h1:4s39bBR8ByfqH+DKm8rQA3E1LHZWB9XWcrz8fqaZbe0= github.com/jackc/chunkreader v1.0.0/go.mod h1:RT6O25fNZIuasFJRyZ4R/Y2BbhasbmZXF9QQ7T3kePo= github.com/jackc/chunkreader/v2 v2.0.0/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk= github.com/jackc/chunkreader/v2 v2.0.1 h1:i+RDz65UE+mmpjTfyz0MoVTnzeYxroil2G82ki7MGG8= @@ -312,7 +311,6 @@ github.com/jackc/pgmock v0.0.0-20190831213851-13a1b77aafa2 h1:JVX6jT/XfzNqIjye47 github.com/jackc/pgmock v0.0.0-20190831213851-13a1b77aafa2/go.mod h1:fGZlG77KXmcq05nJLRkk0+p82V8B8Dw8KN2/V9c/OAE= github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM= github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg= -github.com/jackc/pgproto3 v1.1.0 h1:FYYE4yRw+AgI8wXIinMlNjBbp/UitDJwfj5LqqewP1A= github.com/jackc/pgproto3 v1.1.0/go.mod h1:eR5FA3leWg7p9aeAqi37XOTgTIbkABlvcPB3E5rlc78= github.com/jackc/pgproto3/v2 v2.0.0-alpha1.0.20190420180111-c116219b62db/go.mod h1:bhq50y+xrl9n5mRYyCBFKkpRVTLYJVWeCc+mEAI3yXA= github.com/jackc/pgproto3/v2 v2.0.0-alpha1.0.20190609003834-432c2951c711/go.mod h1:uH0AWtUmuShn0bcesswc4aBTWGvw0cAxIJp+6OB//Wg= @@ -560,7 +558,6 @@ github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= -github.com/yuin/goldmark v1.4.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q= go.etcd.io/bbolt v1.3.5 h1:XAzx9gjCb0Rxj7EoqcClPD1d5ZBxZJk0jbuoPHenBt0= go.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ= @@ -673,7 +670,6 @@ golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210929193557-e81a3d93ecf6 h1:Z04ewVs7JhXaYkmDhBERPi41gnltfQpMWDnTnQbaCqk= golang.org/x/net v0.0.0-20210929193557-e81a3d93ecf6/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -751,7 +747,6 @@ golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6 h1:foEbQz/B0Oz6YIqu/69kfXPYeFQAuuMYFkjaqXzl5Wo= golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= @@ -942,8 +937,8 @@ gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/utils/consts.go b/utils/consts.go index a4b3df87d..318956861 100644 --- a/utils/consts.go +++ b/utils/consts.go @@ -159,6 +159,7 @@ const ( FilterValStart = "(" FilterValEnd = ")" PlusChar = "+" + DecNaN = `"NaN"` JSON = "json" JSONCaps = "JSON" GOBCaps = "GOB" diff --git a/utils/decimal.go b/utils/decimal.go index ae390edf1..bc62bd3ff 100644 --- a/utils/decimal.go +++ b/utils/decimal.go @@ -205,13 +205,20 @@ func (d *Decimal) UnmarshalJSON(data []byte) (err error) { if d.Big == nil { d.Big = decimal.WithContext(DecimalContext) } + // json Unmarshal does not support NaN + if bytes.Equal(data, []byte(DecNaN)) { + *d = *DecimalNaN + return + } return d.Big.UnmarshalText(data) } // MarshalJSON implements the method for jsonMarshal for JSON encoding func (d *Decimal) MarshalJSON() ([]byte, error) { - x, err := d.MarshalText() - return bytes.Trim(x, `"`), err + if d.IsNaN(0) { // json Unmarshal does not support NaN + return []byte(DecNaN), nil + } + return d.MarshalText() } // Clone returns a copy of the Decimal diff --git a/utils/decimal_test.go b/utils/decimal_test.go index ff4429f29..97817ee1b 100644 --- a/utils/decimal_test.go +++ b/utils/decimal_test.go @@ -19,7 +19,7 @@ along with this program. If not, see package utils import ( - "fmt" + "encoding/json" "reflect" "testing" "time" @@ -27,6 +27,27 @@ import ( "github.com/ericlagergren/decimal" ) +func TestUnmarshalInvalidSyntax(t *testing.T) { + x := map[string]*Decimal{ + "*asr": DecimalNaN, + "*abc": NewDecimal(2, 0), + "*acd": DecimalNaN, + } + var bts []byte + var err error + if bts, err = json.Marshal(x); err != nil { + + t.Error(err) + } + + var reply map[string]*Decimal + if err = json.Unmarshal(bts, &reply); err != nil { + t.Error(err) + } else if !reflect.DeepEqual(reply, x) { + t.Errorf("Expected %v, received %v", x, reply) + } +} + func TestConvertDecimalToFloat(t *testing.T) { decm := NewDecimal(9999000000000000, 13) if conv, ok := decm.Float64(); ok { @@ -224,8 +245,8 @@ func TestUnmarshalJSON(t *testing.T) { t.Errorf("Expected %+v, received %+v", expected, dec1) } - dec1 = nil - if err := dec1.UnmarshalJSON([]byte(`0`)); err != nil { + var dec2 Decimal + if err := dec2.UnmarshalJSON([]byte(`0`)); err != nil { t.Error(err) } } @@ -404,6 +425,7 @@ func TestMarshalUnmarshalNA(t *testing.T) { if err := dec2.UnmarshalJSON(mrsh); err != nil { t.Error(err) } - fmt.Printf("dec2 is NaN: %v\n", dec2.IsNaN(0)) - + if dec2.Compare(DecimalNaN) != 0 { + t.Errorf("%v and %v are different", dec2, DecimalNaN) + } }