diff --git a/config/config_defaults.go b/config/config_defaults.go index 5a7d38bf6..bbf5817ae 100755 --- a/config/config_defaults.go +++ b/config/config_defaults.go @@ -61,6 +61,7 @@ const CGRATES_CFG_JSON = ` "db_user": "cgrates", // username to use when connecting to data_db "db_password": "", // password to use when connecting to data_db "redis_sentinel":"", // the name of sentinel when used + "query_timeout":"30s", }, @@ -75,6 +76,7 @@ const CGRATES_CFG_JSON = ` "max_idle_conns": 10, // maximum database connections idle, not applying for mongo "conn_max_lifetime": 0, // maximum amount of time in seconds a connection may be reused (0 for unlimited), not applying for mongo "cdrs_indexes": [], // indexes on cdrs table to speed up queries, used only in case of mongo + "query_timeout":"30s", }, diff --git a/config/config_json_test.go b/config/config_json_test.go index 59b3dab40..1c59a492b 100755 --- a/config/config_json_test.go +++ b/config/config_json_test.go @@ -189,6 +189,7 @@ func TestDfDataDbJsonCfg(t *testing.T) { Db_user: utils.StringPointer("cgrates"), Db_password: utils.StringPointer(""), Redis_sentinel: utils.StringPointer(""), + Query_timeout: utils.StringPointer("30s"), } if cfg, err := dfCgrJsonCfg.DbJsonCfg(DATADB_JSN); err != nil { t.Error(err) @@ -209,6 +210,7 @@ func TestDfStorDBJsonCfg(t *testing.T) { Max_idle_conns: utils.IntPointer(10), Conn_max_lifetime: utils.IntPointer(0), Cdrs_indexes: &[]string{}, + Query_timeout: utils.StringPointer("30s"), } if cfg, err := dfCgrJsonCfg.DbJsonCfg(STORDB_JSN); err != nil { t.Error(err) diff --git a/config/datadbcfg.go b/config/datadbcfg.go index 416cc119b..f30c916bb 100644 --- a/config/datadbcfg.go +++ b/config/datadbcfg.go @@ -21,6 +21,7 @@ package config import ( "strconv" "strings" + "time" "github.com/cgrates/cgrates/utils" ) @@ -34,6 +35,7 @@ type DataDbCfg struct { DataDbUser string // The user to sign in as. DataDbPass string // The user's password. DataDbSentinelName string + QueryTimeout time.Duration } //loadFromJsonCfg loads Database config from JsonCfg @@ -66,5 +68,10 @@ func (dbcfg *DataDbCfg) loadFromJsonCfg(jsnDbCfg *DbJsonCfg) (err error) { if jsnDbCfg.Redis_sentinel != nil { dbcfg.DataDbSentinelName = *jsnDbCfg.Redis_sentinel } + if jsnDbCfg.Query_timeout != nil { + if dbcfg.QueryTimeout, err = utils.ParseDurationWithNanosecs(*jsnDbCfg.Query_timeout); err != nil { + return err + } + } return nil } diff --git a/config/libconfig_json.go b/config/libconfig_json.go index ab435aa50..7cad32e32 100755 --- a/config/libconfig_json.go +++ b/config/libconfig_json.go @@ -87,6 +87,7 @@ type DbJsonCfg struct { Conn_max_lifetime *int // Used only in case of storDb Cdrs_indexes *[]string Redis_sentinel *string + Query_timeout *string } // Filters config diff --git a/config/storedbcfg.go b/config/storedbcfg.go index bd8aedc9b..a5c99ebcf 100644 --- a/config/storedbcfg.go +++ b/config/storedbcfg.go @@ -21,6 +21,7 @@ package config import ( "strconv" "strings" + "time" "github.com/cgrates/cgrates/utils" ) @@ -37,6 +38,7 @@ type StorDbCfg struct { StorDBMaxIdleConns int // Maximum idle connections to keep opened StorDBConnMaxLifetime int StorDBCDRSIndexes []string + QueryTimeout time.Duration } //loadFromJsonCfg loads StoreDb config from JsonCfg @@ -78,5 +80,10 @@ func (dbcfg *StorDbCfg) loadFromJsonCfg(jsnDbCfg *DbJsonCfg) (err error) { if jsnDbCfg.Cdrs_indexes != nil { dbcfg.StorDBCDRSIndexes = *jsnDbCfg.Cdrs_indexes } + if jsnDbCfg.Query_timeout != nil { + if dbcfg.QueryTimeout, err = utils.ParseDurationWithNanosecs(*jsnDbCfg.Query_timeout); err != nil { + return err + } + } return nil } diff --git a/data/conf/cgrates/cgrates.json b/data/conf/cgrates/cgrates.json index 802f5cd21..ecf6b9f03 100644 --- a/data/conf/cgrates/cgrates.json +++ b/data/conf/cgrates/cgrates.json @@ -40,6 +40,7 @@ // "db_user": "cgrates", // username to use when connecting to data_db // "db_password": "", // password to use when connecting to data_db // "redis_sentinel":"", // the name of sentinel when used +// "query_timeout":"30s", // }, @@ -54,6 +55,7 @@ // "max_idle_conns": 10, // maximum database connections idle, not applying for mongo // "conn_max_lifetime": 0, // maximum amount of time in seconds a connection may be reused (0 for unlimited), not applying for mongo // "cdrs_indexes": [], // indexes on cdrs table to speed up queries, used only in case of mongo +// "query_timeout":"30s", // }, @@ -78,7 +80,7 @@ // }, -// "http": { // HTTP server configuration +// "http": { // HTTP server configuration // "json_rpc_url": "/jsonrpc", // JSON RPC relative URL ("" to disable) // "ws_url": "/ws", // WebSockets relative URL ("" to disable) // "freeswitch_cdrs_url": "/freeswitch_json", // Freeswitch CDRS relative URL ("" to disable) @@ -151,7 +153,7 @@ // }, -// "cdrs": { // CDRs config +// "cdrs": { // CDRs config // "enabled": false, // start the CDR Server: // "extra_fields": [], // extra fields to store in CDRs for non-generic CDRs (ie: FreeSWITCH JSON) // "store_cdrs": true, // store cdrs in StorDB @@ -169,7 +171,7 @@ // }, -// "cdre": { // CDRe config +// "cdre": { // CDRe config // "*default": { // "export_format": "*file_csv", // exported CDRs format <*file_csv|*file_fwv|*http_post|*http_json_cdr|*http_json_map|*amqp_json_cdr|*amqp_json_map|*sqs_json_map> // "export_path": "/var/spool/cgrates/cdre", // path where the exported CDRs will be placed @@ -204,7 +206,7 @@ // }, -// "cdrc": [ // CDRc config +// "cdrc": [ // CDRc config // { // "id": "*default", // identifier of the CDRC runner // "enabled": false, // enable CDR client functionality @@ -420,11 +422,11 @@ // }, -// "http_agent": [ // HTTP Agents, ie towards cnc.to MVNE platform +// "http_agent": [ // HTTP Agents, ie towards cnc.to MVNE platform // ], -// "attributes": { // AttributeS config +// "attributes": { // AttributeS config // "enabled": false, // starts attribute service: . // "indexed_selects":true, // enable profile matching exclusively on indexes // //"string_indexed_fields": [], // query indexes based on these fields for faster processing @@ -433,7 +435,7 @@ // }, -// "chargers": { // ChargerS config +// "chargers": { // ChargerS config // "enabled": false, // starts charger service: . // "attributes_conns": [], // connections to AttributeS for event fields altering <""|127.0.0.1:2013> // "indexed_selects":true, // enable profile matching exclusively on indexes @@ -442,7 +444,7 @@ // }, -// "resources": { // ResourceS config +// "resources": { // ResourceS config // "enabled": false, // starts ResourceLimiter service: . // "store_interval": "", // dump cache regularly to dataDB, 0 - dump at start/shutdown: <""|$dur> // "thresholds_conns": [], // connections to ThresholdS for resource reporting, empty to disable thresholds functionality: <""|*internal|x.y.z.y:1234> @@ -452,7 +454,7 @@ // }, -// "stats": { // StatS config +// "stats": { // StatS config // "enabled": false, // starts Stat service: . // "store_interval": "", // dump cache regularly to dataDB, 0 - dump at start/shutdown: <""|$dur> // "thresholds_conns": [], // connections to ThresholdS for StatUpdates, empty to disable thresholds functionality: <""|*internal|x.y.z.y:1234> @@ -462,7 +464,7 @@ // }, -// "thresholds": { // ThresholdS +// "thresholds": { // ThresholdS // "enabled": false, // starts ThresholdS service: . // "store_interval": "", // dump cache regularly to dataDB, 0 - dump at start/shutdown: <""|$dur> // "indexed_selects":true, // enable profile matching exclusively on indexes @@ -471,7 +473,7 @@ // }, -// "suppliers": { // SupplierS config +// "suppliers": { // SupplierS config // "enabled": false, // starts SupplierS service: . // "indexed_selects":true, // enable profile matching exclusively on indexes // //"string_indexed_fields": [], // query indexes based on these fields for faster processing @@ -516,8 +518,8 @@ // ], // }, // { -// "type": "*filters", // data source type -// "file_name": "Filters.csv", // file name in the tp_in_dir +// "type": "*filters", // data source type +// "file_name": "Filters.csv", // file name in the tp_in_dir // "fields": [ // {"tag": "Tenant", "field_id": "Tenant", "type": "*composed", "value": "~0", "mandatory": true}, // {"tag": "ID", "field_id": "ID", "type": "*composed", "value": "~1", "mandatory": true}, @@ -545,8 +547,8 @@ // ], // }, // { -// "type": "*stats", // data source type -// "file_name": "Stats.csv", // file name in the tp_in_dir +// "type": "*stats", // data source type +// "file_name": "Stats.csv", // file name in the tp_in_dir // "fields": [ // {"tag": "Tenant", "field_id": "Tenant", "type": "*composed", "value": "~0", "mandatory": true}, // {"tag": "ID", "field_id": "ID", "type": "*composed", "value": "~1", "mandatory": true}, @@ -676,7 +678,7 @@ // }, -// "loader": { // loader for tariff plans out of .csv files +// "loader": { // loader for tariff plans out of .csv files // "tpid": "", // tariff plan identificator // "data_path": "./", // path towards tariff plan files // "disable_reverse": false, // disable reverse computing @@ -708,7 +710,7 @@ // }, -// "dispatchers":{ // DispatcherS config +// "dispatchers":{ // DispatcherS config // "enabled": false, // starts DispatcherS service: . // "indexed_selects":true, // enable profile matching exclusively on indexes // //"string_indexed_fields": [], // query indexes based on these fields for faster processing @@ -719,7 +721,7 @@ // }, -// "analyzers":{ // AnalyzerS config +// "analyzers":{ // AnalyzerS config // "enabled":false // starts AnalyzerS service: . // }, diff --git a/engine/storage_mongo_datadb.go b/engine/storage_mongo_datadb.go index 72e9a805c..327dc49a2 100644 --- a/engine/storage_mongo_datadb.go +++ b/engine/storage_mongo_datadb.go @@ -136,10 +136,15 @@ func NewMongoStorage(host, port, db, user, pass, storageType string, cdrsIndexes dbName = strings.Split(db, "?")[0] // remove extra info after ? } ctx := context.Background() + ttl := config.CgrConfig().DataDbCfg().QueryTimeout + if !isDataDB { + ttl = config.CgrConfig().StorDbCfg().QueryTimeout + } url = "mongodb://" + url reg := bson.NewRegistryBuilder().RegisterDecoder(tTime, bsoncodec.ValueDecoderFunc(TimeDecodeValue1)).Build() - opt := options.Client().SetRegistry(reg). - SetServerSelectionTimeout(config.CgrConfig().GeneralCfg().ConnectTimeout) + opt := options.Client(). + SetRegistry(reg). + SetServerSelectionTimeout(ttl) client, err := mongo.NewClientWithOptions(url, opt) // client, err := mongo.NewClient(url) @@ -147,7 +152,6 @@ func NewMongoStorage(host, port, db, user, pass, storageType string, cdrsIndexes if err != nil { return nil, err } - ctxTTL := config.CgrConfig().GeneralCfg().ReplyTimeout err = client.Connect(ctx) if err != nil { return nil, err @@ -155,7 +159,7 @@ func NewMongoStorage(host, port, db, user, pass, storageType string, cdrsIndexes ms = &MongoStorage{ client: client, ctx: ctx, - ctxTTL: ctxTTL, + ctxTTL: ttl, db: dbName, storageType: storageType, ms: NewCodecMsgpackMarshaler(),