diff --git a/apier/v1/config_it_test.go b/apier/v1/config_it_test.go
index 39a51c51a..2c0362d14 100644
--- a/apier/v1/config_it_test.go
+++ b/apier/v1/config_it_test.go
@@ -165,6 +165,7 @@ func testConfigSSetConfigSessionS(t *testing.T) {
"scheduler_conns": []any{},
"thresholds_conns": []any{},
"stats_conns": []any{},
+ utils.BackupIntervalCfg: "0",
"min_dur_low_balance": "0",
"stir": map[string]any{
"allowed_attest": []any{utils.MetaAny},
@@ -232,7 +233,7 @@ func testConfigSSetConfigSessionS(t *testing.T) {
}, &rpl); err != nil {
t.Error(err)
} else if !reflect.DeepEqual(exp, rpl) {
- t.Errorf("Expected %+v , received: %+v ", utils.ToJSON(exp), utils.ToJSON(rpl))
+ t.Errorf("Expected %+v , \nreceived: %+v ", utils.ToJSON(exp), utils.ToJSON(rpl))
}
}
@@ -259,6 +260,7 @@ func testConfigSv1GetJSONSectionWithoutTenant(t *testing.T) {
"session_ttl": "0",
"stale_chan_max_extra_usage": "0",
"store_session_costs": false,
+ utils.BackupIntervalCfg: "0",
"min_dur_low_balance": "0",
"alterable_fields": []any{},
"stir": map[string]any{
diff --git a/config/config_it_test.go b/config/config_it_test.go
index 75eb3c7dc..1ffde468f 100644
--- a/config/config_it_test.go
+++ b/config/config_it_test.go
@@ -1053,11 +1053,12 @@ func testCGRConfigReloadConfigFromStringSessionS(t *testing.T) {
}
var rcv string
- expected := `{"sessions":{"alterable_fields":[],"attributes_conns":["*localhost"],"cdrs_conns":["*internal"],"channel_sync_interval":"0","chargers_conns":["*localhost"],"client_protocol":2,"debit_interval":"0","default_usage":{"*any":"3h0m0s","*data":"1048576","*sms":"1","*voice":"3h0m0s"},"enabled":true,"listen_bigob":"","listen_bijson":"127.0.0.1:2014","min_dur_low_balance":"0","rals_conns":["*internal"],"replication_conns":[],"resources_conns":["*localhost"],"routes_conns":["*localhost"],"scheduler_conns":[],"session_indexes":[],"session_ttl":"0","stale_chan_max_extra_usage":"0","stats_conns":[],"stir":{"allowed_attest":["*any"],"default_attest":"A","payload_maxduration":"-1","privatekey_path":"","publickey_path":""},"store_session_costs":false,"terminate_attempts":5,"thresholds_conns":[]}}`
+ expected := `{"sessions":{"alterable_fields":[],"attributes_conns":["*localhost"],"backup_interval":"0","cdrs_conns":["*internal"],"channel_sync_interval":"0","chargers_conns":["*localhost"],"client_protocol":2,"debit_interval":"0","default_usage":{"*any":"3h0m0s","*data":"1048576","*sms":"1","*voice":"3h0m0s"},"enabled":true,"listen_bigob":"","listen_bijson":"127.0.0.1:2014","min_dur_low_balance":"0","rals_conns":["*internal"],"replication_conns":[],"resources_conns":["*localhost"],"routes_conns":["*localhost"],"scheduler_conns":[],"session_indexes":[],"session_ttl":"0","stale_chan_max_extra_usage":"0","stats_conns":[],"stir":{"allowed_attest":["*any"],"default_attest":"A","payload_maxduration":"-1","privatekey_path":"","publickey_path":""},"store_session_costs":false,"terminate_attempts":5,"thresholds_conns":[]}}`
+
if err := cfg.V1GetConfigAsJSON(context.Background(), &SectionWithAPIOpts{Section: SessionSJson}, &rcv); err != nil {
t.Error(err)
} else if expected != rcv {
- t.Errorf("Expected: %+q, \n received: %s", expected, rcv)
+ t.Errorf("Expected: %s, \n received: %s", expected, rcv)
}
}
diff --git a/config/config_json_test.go b/config/config_json_test.go
index f69fde674..564bc894e 100644
--- a/config/config_json_test.go
+++ b/config/config_json_test.go
@@ -532,6 +532,13 @@ func TestDfDataDbJsonCfg(t *testing.T) {
Ttl: utils.StringPointer(utils.EmptyString),
Static_ttl: utils.BoolPointer(false),
},
+ utils.MetaSessionsBackup: {
+ Replicate: utils.BoolPointer(false),
+ Remote: utils.BoolPointer(false),
+ Limit: utils.IntPointer(-1),
+ Ttl: utils.StringPointer(utils.EmptyString),
+ Static_ttl: utils.BoolPointer(false),
+ },
},
}
dfCgrJSONCfg, err := NewCgrJsonCfgFromBytes([]byte(CGRATES_CFG_JSON))
@@ -843,6 +850,7 @@ func TestSmgJsonCfg(t *testing.T) {
Stale_chan_max_extra_usage: utils.StringPointer("0"),
Terminate_attempts: utils.IntPointer(5),
Alterable_fields: &[]string{},
+ Backup_interval: utils.StringPointer("0s"),
Default_usage: &map[string]string{
utils.MetaAny: "3h",
utils.MetaVoice: "3h",
@@ -865,7 +873,7 @@ func TestSmgJsonCfg(t *testing.T) {
if cfg, err := dfCgrJSONCfg.SessionSJsonCfg(); err != nil {
t.Error(err)
} else if !reflect.DeepEqual(eCfg, cfg) {
- t.Errorf("Expecting: %s, received: %s", utils.ToJSON(eCfg), utils.ToJSON(cfg))
+ t.Errorf("Expecting: %s, \nreceived: %s", utils.ToJSON(eCfg), utils.ToJSON(cfg))
}
}
diff --git a/config/config_test.go b/config/config_test.go
index 3b8534f10..ef4e78a04 100644
--- a/config/config_test.go
+++ b/config/config_test.go
@@ -501,6 +501,7 @@ func TestCgrCfgJSONDefaultsSMGenericCfg(t *testing.T) {
DebitInterval: 0,
StoreSCosts: false,
SessionTTL: 0,
+ BackupInterval: 0,
SessionIndexes: utils.StringSet{},
ClientProtocol: 2.0,
ChannelSyncInterval: 0,
@@ -2112,6 +2113,7 @@ func TestSessionSConfig(t *testing.T) {
DebitInterval: 0,
StoreSCosts: false,
SessionTTL: 0,
+ BackupInterval: 0,
SessionIndexes: utils.StringSet{},
ClientProtocol: 2.0,
ChannelSyncInterval: 0,
@@ -3590,7 +3592,7 @@ func TestV1GetConfigGeneral(t *testing.T) {
utils.DefaultTenantCfg: "cgrates.org",
utils.DefaultTimezoneCfg: "Local",
utils.DefaultCachingCfg: "*reload",
- utils.CachingDlayCfg: 0 * time.Second,
+ utils.CachingDlayCfg: "0",
utils.ConnectAttemptsCfg: 5,
utils.ReconnectsCfg: -1,
utils.MaxReconnectIntervalCfg: "0",
@@ -3891,6 +3893,7 @@ func TestV1GetConfigSessionS(t *testing.T) {
utils.SessionIndexesCfg: []string{},
utils.ClientProtocolCfg: 2.0,
utils.SessionTTLCfg: "0",
+ utils.BackupIntervalCfg: "0",
utils.ChannelSyncIntervalCfg: "0",
utils.StaleChanMaxExtraUsageCfg: "0",
utils.TerminateAttemptsCfg: 5,
@@ -4822,7 +4825,7 @@ func TestV1GetConfigAsJSONGeneral(t *testing.T) {
"node_id": "ENGINE1",
}
}`
- expected := `{"general":{"caching_delay":0,"connect_attempts":5,"connect_timeout":"1s","dbdata_encoding":"*msgpack","default_caching":"*reload","default_category":"call","default_request_type":"*rated","default_tenant":"cgrates.org","default_timezone":"Local","digest_equal":":","digest_separator":",","failed_posts_dir":"/var/spool/cgrates/failed_posts","failed_posts_ttl":"5s","locking_timeout":"0","log_level":6,"logger":"*syslog","max_parallel_conns":100,"max_reconnect_interval":"0","node_id":"ENGINE1","poster_attempts":3,"reconnects":-1,"reply_timeout":"2s","rounding_decimals":5,"rsr_separator":";","tpexport_dir":"/var/spool/cgrates/tpe"}}`
+ expected := `{"general":{"caching_delay":"0","connect_attempts":5,"connect_timeout":"1s","dbdata_encoding":"*msgpack","default_caching":"*reload","default_category":"call","default_request_type":"*rated","default_tenant":"cgrates.org","default_timezone":"Local","digest_equal":":","digest_separator":",","failed_posts_dir":"/var/spool/cgrates/failed_posts","failed_posts_ttl":"5s","locking_timeout":"0","log_level":6,"logger":"*syslog","max_parallel_conns":100,"max_reconnect_interval":"0","node_id":"ENGINE1","poster_attempts":3,"reconnects":-1,"reply_timeout":"2s","rounding_decimals":5,"rsr_separator":";","tpexport_dir":"/var/spool/cgrates/tpe"}}`
if cfgCgr, err := NewCGRConfigFromJSONStringWithDefaults(strJSON); err != nil {
t.Error(err)
} else if err := cfgCgr.V1GetConfigAsJSON(context.Background(), &SectionWithAPIOpts{Section: GENERAL_JSN}, &reply); err != nil {
@@ -4834,7 +4837,7 @@ func TestV1GetConfigAsJSONGeneral(t *testing.T) {
func TestV1GetConfigAsJSONDataDB(t *testing.T) {
var reply string
- expected := `{"data_db":{"db_host":"127.0.0.1","db_name":"10","db_password":"","db_port":6379,"db_type":"*redis","db_user":"cgrates","items":{"*account_action_plans":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*accounts":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*action_plans":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*action_triggers":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*actions":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*attribute_filter_indexes":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*attribute_profiles":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*charger_filter_indexes":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*charger_profiles":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*destinations":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*dispatcher_filter_indexes":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*dispatcher_hosts":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*dispatcher_profiles":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*filters":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*load_ids":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*rating_plans":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*rating_profiles":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*resource_filter_indexes":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*resource_profiles":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*resources":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*reverse_destinations":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*reverse_filter_indexes":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*route_filter_indexes":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*route_profiles":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*shared_groups":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*stat_filter_indexes":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*statqueue_profiles":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*statqueues":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*threshold_filter_indexes":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*threshold_profiles":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*thresholds":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*timings":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*versions":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false}},"opts":{"mongoConnScheme":"mongodb","mongoQueryTimeout":"10s","redisCACertificate":"","redisClientCertificate":"","redisClientKey":"","redisCluster":false,"redisClusterOndownDelay":"0s","redisClusterSync":"5s","redisConnectAttempts":20,"redisConnectTimeout":"0s","redisMaxConns":10,"redisReadTimeout":"0s","redisSentinel":"","redisTLS":false,"redisWriteTimeout":"0s"},"remote_conn_id":"","remote_conns":[],"replication_cache":"","replication_conns":[],"replication_filtered":false}}`
+ expected := `{"data_db":{"db_host":"127.0.0.1","db_name":"10","db_password":"","db_port":6379,"db_type":"*redis","db_user":"cgrates","items":{"*account_action_plans":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*accounts":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*action_plans":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*action_triggers":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*actions":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*attribute_filter_indexes":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*attribute_profiles":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*charger_filter_indexes":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*charger_profiles":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*destinations":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*dispatcher_filter_indexes":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*dispatcher_hosts":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*dispatcher_profiles":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*filters":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*load_ids":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*rating_plans":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*rating_profiles":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*resource_filter_indexes":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*resource_profiles":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*resources":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*reverse_destinations":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*reverse_filter_indexes":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*route_filter_indexes":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*route_profiles":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*sessions_backup":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*shared_groups":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*stat_filter_indexes":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*statqueue_profiles":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*statqueues":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*threshold_filter_indexes":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*threshold_profiles":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*thresholds":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*timings":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*versions":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false}},"opts":{"mongoConnScheme":"mongodb","mongoQueryTimeout":"10s","redisCACertificate":"","redisClientCertificate":"","redisClientKey":"","redisCluster":false,"redisClusterOndownDelay":"0s","redisClusterSync":"5s","redisConnectAttempts":20,"redisConnectTimeout":"0s","redisMaxConns":10,"redisReadTimeout":"0s","redisSentinel":"","redisTLS":false,"redisWriteTimeout":"0s"},"remote_conn_id":"","remote_conns":[],"replication_cache":"","replication_conns":[],"replication_filtered":false}}`
cfgCgr := NewDefaultCGRConfig()
if err := cfgCgr.V1GetConfigAsJSON(context.Background(), &SectionWithAPIOpts{Section: DATADB_JSN}, &reply); err != nil {
t.Error(err)
@@ -4944,7 +4947,7 @@ func TestV1GetConfigAsJSONCdrs(t *testing.T) {
func TestV1GetConfigAsJSONSessionS(t *testing.T) {
var reply string
- expected := `{"sessions":{"alterable_fields":[],"attributes_conns":[],"cdrs_conns":[],"channel_sync_interval":"0","chargers_conns":[],"client_protocol":2,"debit_interval":"0","default_usage":{"*any":"3h0m0s","*data":"1048576","*sms":"1","*voice":"3h0m0s"},"enabled":false,"listen_bigob":"","listen_bijson":"127.0.0.1:2014","min_dur_low_balance":"0","rals_conns":[],"replication_conns":[],"resources_conns":[],"routes_conns":[],"scheduler_conns":[],"session_indexes":[],"session_ttl":"0","stale_chan_max_extra_usage":"0","stats_conns":[],"stir":{"allowed_attest":["*any"],"default_attest":"A","payload_maxduration":"-1","privatekey_path":"","publickey_path":""},"store_session_costs":false,"terminate_attempts":5,"thresholds_conns":[]}}`
+ expected := `{"sessions":{"alterable_fields":[],"attributes_conns":[],"backup_interval":"0","cdrs_conns":[],"channel_sync_interval":"0","chargers_conns":[],"client_protocol":2,"debit_interval":"0","default_usage":{"*any":"3h0m0s","*data":"1048576","*sms":"1","*voice":"3h0m0s"},"enabled":false,"listen_bigob":"","listen_bijson":"127.0.0.1:2014","min_dur_low_balance":"0","rals_conns":[],"replication_conns":[],"resources_conns":[],"routes_conns":[],"scheduler_conns":[],"session_indexes":[],"session_ttl":"0","stale_chan_max_extra_usage":"0","stats_conns":[],"stir":{"allowed_attest":["*any"],"default_attest":"A","payload_maxduration":"-1","privatekey_path":"","publickey_path":""},"store_session_costs":false,"terminate_attempts":5,"thresholds_conns":[]}}`
cfgCgr := NewDefaultCGRConfig()
if err := cfgCgr.V1GetConfigAsJSON(context.Background(), &SectionWithAPIOpts{Section: SessionSJson}, &reply); err != nil {
t.Error(err)
@@ -5357,7 +5360,7 @@ func TestV1GetConfigAsJSONAllConfig(t *testing.T) {
}`
var reply string
cgrCfg, err := NewCGRConfigFromJSONStringWithDefaults(cfgJSON)
- expected := `{"analyzers":{"cleanup_interval":"1h0m0s","db_path":"/var/spool/cgrates/analyzers","enabled":false,"index_type":"*scorch","ttl":"24h0m0s"},"apiban":{"keys":[]},"apiers":{"attributes_conns":[],"caches_conns":["*internal"],"ees_conns":[],"enabled":false,"scheduler_conns":[]},"asterisk_agent":{"asterisk_conns":[{"address":"127.0.0.1:8088","alias":"","connect_attempts":3,"max_reconnect_interval":"0s","password":"CGRateS.org","reconnects":5,"user":"cgrates"}],"create_cdr":false,"enabled":false,"sessions_conns":["*birpc_internal"]},"attributes":{"any_context":true,"apiers_conns":[],"enabled":false,"indexed_selects":true,"nested_fields":false,"opts":{"*processRuns":1,"*profileIDs":[],"*profileIgnoreFilters":false,"*profileRuns":0},"prefix_indexed_fields":[],"resources_conns":[],"stats_conns":[],"suffix_indexed_fields":[]},"caches":{"partitions":{"*account_action_plans":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*action_plans":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*action_triggers":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*actions":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*apiban":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false,"ttl":"2m0s"},"*attribute_filter_indexes":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*attribute_profiles":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*caps_events":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*cdr_ids":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false,"ttl":"10m0s"},"*charger_filter_indexes":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*charger_profiles":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*closed_sessions":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false,"ttl":"10s"},"*destinations":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*diameter_messages":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false,"ttl":"3h0m0s"},"*dispatcher_filter_indexes":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*dispatcher_hosts":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*dispatcher_loads":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*dispatcher_profiles":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*dispatcher_routes":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*dispatchers":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*event_charges":{"limit":0,"precache":false,"remote":false,"replicate":false,"static_ttl":false,"ttl":"10s"},"*event_resources":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*filters":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*load_ids":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*radius_packets":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false,"ttl":"3h0m0s"},"*rating_plans":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*rating_profiles":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*replication_hosts":{"limit":0,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*resource_filter_indexes":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*resource_profiles":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*resources":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*reverse_destinations":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*reverse_filter_indexes":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*route_filter_indexes":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*route_profiles":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*rpc_connections":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*rpc_responses":{"limit":0,"precache":false,"remote":false,"replicate":false,"static_ttl":false,"ttl":"2s"},"*sentrypeer":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":true,"ttl":"24h0m0s"},"*shared_groups":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*stat_filter_indexes":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*statqueue_profiles":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*statqueues":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*stir":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false,"ttl":"3h0m0s"},"*threshold_filter_indexes":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*threshold_profiles":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*thresholds":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*timings":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*uch":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false,"ttl":"3h0m0s"}},"remote_conns":[],"replication_conns":[]},"cdrs":{"attributes_conns":[],"chargers_conns":[],"ees_conns":[],"enabled":false,"extra_fields":[],"online_cdr_exports":[],"rals_conns":[],"scheduler_conns":[],"session_cost_retries":5,"stats_conns":[],"store_cdrs":true,"thresholds_conns":[]},"chargers":{"attributes_conns":[],"enabled":false,"indexed_selects":true,"nested_fields":false,"prefix_indexed_fields":[],"suffix_indexed_fields":[]},"configs":{"enabled":false,"root_dir":"/var/spool/cgrates/configs","url":"/configs/"},"cores":{"caps":0,"caps_stats_interval":"0","caps_strategy":"*busy","shutdown_timeout":"1s"},"data_db":{"db_host":"127.0.0.1","db_name":"10","db_password":"","db_port":6379,"db_type":"*redis","db_user":"cgrates","items":{"*account_action_plans":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*accounts":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*action_plans":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*action_triggers":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*actions":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*attribute_filter_indexes":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*attribute_profiles":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*charger_filter_indexes":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*charger_profiles":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*destinations":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*dispatcher_filter_indexes":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*dispatcher_hosts":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*dispatcher_profiles":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*filters":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*load_ids":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*rating_plans":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*rating_profiles":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*resource_filter_indexes":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*resource_profiles":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*resources":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*reverse_destinations":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*reverse_filter_indexes":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*route_filter_indexes":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*route_profiles":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*shared_groups":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*stat_filter_indexes":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*statqueue_profiles":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*statqueues":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*threshold_filter_indexes":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*threshold_profiles":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*thresholds":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*timings":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*versions":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false}},"opts":{"mongoConnScheme":"mongodb","mongoQueryTimeout":"10s","redisCACertificate":"","redisClientCertificate":"","redisClientKey":"","redisCluster":false,"redisClusterOndownDelay":"0s","redisClusterSync":"5s","redisConnectAttempts":20,"redisConnectTimeout":"0s","redisMaxConns":10,"redisReadTimeout":"0s","redisSentinel":"","redisTLS":false,"redisWriteTimeout":"0s"},"remote_conn_id":"","remote_conns":[],"replication_cache":"","replication_conns":[],"replication_filtered":false},"diameter_agent":{"asr_template":"","concurrent_requests":-1,"dictionaries_path":"/usr/share/cgrates/diameter/dict/","enabled":false,"forced_disconnect":"*none","listen":"127.0.0.1:3868","listen_net":"tcp","origin_host":"CGR-DA","origin_realm":"cgrates.org","product_name":"CGRateS","rar_template":"","request_processors":[],"sessions_conns":["*birpc_internal"],"synced_conn_requests":false,"vendor_id":0},"dispatchers":{"any_subsystem":true,"attributes_conns":[],"enabled":false,"indexed_selects":true,"nested_fields":false,"prefix_indexed_fields":[],"prevent_loop":false,"suffix_indexed_fields":[]},"dns_agent":{"enabled":false,"listeners":[{"address":"127.0.0.1:53","network":"udp"}],"request_processors":[],"sessions_conns":["*internal"],"timezone":""},"ees":{"attributes_conns":[],"cache":{"*file_csv":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false,"ttl":"5s"}},"enabled":false,"exporters":[{"attempts":1,"attribute_context":"","attribute_ids":[],"concurrent_requests":0,"export_path":"/var/spool/cgrates/ees","failed_posts_dir":"/var/spool/cgrates/failed_posts","fields":[],"filters":[],"flags":[],"id":"*default","opts":{},"synchronous":false,"timezone":"","type":"*none"}]},"ers":{"concurrent_events":1,"ees_conns":[],"enabled":false,"partial_cache_ttl":"1s","readers":[{"cache_dump_fields":[],"concurrent_requests":1024,"fields":[{"mandatory":true,"path":"*cgreq.ToR","tag":"ToR","type":"*variable","value":"~*req.2"},{"mandatory":true,"path":"*cgreq.OriginID","tag":"OriginID","type":"*variable","value":"~*req.3"},{"mandatory":true,"path":"*cgreq.RequestType","tag":"RequestType","type":"*variable","value":"~*req.4"},{"mandatory":true,"path":"*cgreq.Tenant","tag":"Tenant","type":"*variable","value":"~*req.6"},{"mandatory":true,"path":"*cgreq.Category","tag":"Category","type":"*variable","value":"~*req.7"},{"mandatory":true,"path":"*cgreq.Account","tag":"Account","type":"*variable","value":"~*req.8"},{"mandatory":true,"path":"*cgreq.Subject","tag":"Subject","type":"*variable","value":"~*req.9"},{"mandatory":true,"path":"*cgreq.Destination","tag":"Destination","type":"*variable","value":"~*req.10"},{"mandatory":true,"path":"*cgreq.SetupTime","tag":"SetupTime","type":"*variable","value":"~*req.11"},{"mandatory":true,"path":"*cgreq.AnswerTime","tag":"AnswerTime","type":"*variable","value":"~*req.12"},{"mandatory":true,"path":"*cgreq.Usage","tag":"Usage","type":"*variable","value":"~*req.13"}],"filters":[],"flags":[],"id":"*default","max_reconnect_interval":"5m0s","opts":{"csvFieldSeparator":",","csvHeaderDefineChar":":","csvRowLength":0,"natsSubject":"cgrates_cdrs","partialCacheAction":"*none","partialOrderField":"~*req.AnswerTime"},"partial_commit_fields":[],"processed_path":"/var/spool/cgrates/ers/out","reconnects":-1,"run_delay":"0","source_path":"/var/spool/cgrates/ers/in","tenant":"","timezone":"","type":"*none"}],"sessions_conns":["*internal"]},"filters":{"apiers_conns":[],"resources_conns":[],"stats_conns":[]},"freeswitch_agent":{"active_session_delimiter":",","create_cdr":false,"empty_balance_ann_file":"","empty_balance_context":"","enabled":false,"event_socket_conns":[{"address":"127.0.0.1:8021","alias":"127.0.0.1:8021","max_reconnect_interval":"0s","password":"ClueCon","reconnects":5,"reply_timeout":"1m0s"}],"extra_fields":"","low_balance_ann_file":"","max_wait_connection":"2s","sessions_conns":["*birpc_internal"],"subscribe_park":true},"general":{"caching_delay":0,"connect_attempts":5,"connect_timeout":"1s","dbdata_encoding":"*msgpack","default_caching":"*reload","default_category":"call","default_request_type":"*rated","default_tenant":"cgrates.org","default_timezone":"Local","digest_equal":":","digest_separator":",","failed_posts_dir":"/var/spool/cgrates/failed_posts","failed_posts_ttl":"5s","locking_timeout":"0","log_level":6,"logger":"*syslog","max_parallel_conns":100,"max_reconnect_interval":"0","node_id":"ENGINE1","poster_attempts":3,"reconnects":-1,"reply_timeout":"2s","rounding_decimals":5,"rsr_separator":";","tpexport_dir":"/var/spool/cgrates/tpe"},"http":{"auth_users":{},"client_opts":{"dialFallbackDelay":"300ms","dialKeepAlive":"30s","dialTimeout":"30s","disableCompression":false,"disableKeepAlives":false,"expectContinueTimeout":"0s","forceAttemptHttp2":true,"idleConnTimeout":"1m30s","maxConnsPerHost":0,"maxIdleConns":100,"maxIdleConnsPerHost":2,"responseHeaderTimeout":"0s","skipTlsVerify":false,"tlsHandshakeTimeout":"10s"},"freeswitch_cdrs_url":"/freeswitch_json","http_cdrs":"/cdr_http","json_rpc_url":"/jsonrpc","registrars_url":"/registrar","use_basic_auth":false,"ws_url":"/ws"},"http_agent":[],"kamailio_agent":{"create_cdr":false,"enabled":false,"evapi_conns":[{"address":"127.0.0.1:8448","alias":"","max_reconnect_interval":"0s","reconnects":5}],"sessions_conns":["*birpc_internal"],"timezone":""},"listen":{"http":"127.0.0.1:2080","http_tls":"127.0.0.1:2280","rpc_gob":"127.0.0.1:2013","rpc_gob_tls":"127.0.0.1:2023","rpc_json":"127.0.0.1:2012","rpc_json_tls":"127.0.0.1:2022"},"loader":{"caches_conns":["*localhost"],"data_path":"./","disable_reverse":false,"field_separator":",","gapi_credentials":".gapi/credentials.json","gapi_token":".gapi/token.json","scheduler_conns":["*localhost"],"tpid":""},"loaders":[{"caches_conns":["*internal"],"data":[{"fields":[{"mandatory":true,"path":"Tenant","tag":"TenantID","type":"*variable","value":"~*req.0"},{"mandatory":true,"path":"ID","tag":"ProfileID","type":"*variable","value":"~*req.1"},{"path":"Contexts","tag":"Contexts","type":"*variable","value":"~*req.2"},{"path":"FilterIDs","tag":"FilterIDs","type":"*variable","value":"~*req.3"},{"path":"ActivationInterval","tag":"ActivationInterval","type":"*variable","value":"~*req.4"},{"path":"AttributeFilterIDs","tag":"AttributeFilterIDs","type":"*variable","value":"~*req.5"},{"path":"Path","tag":"Path","type":"*variable","value":"~*req.6"},{"path":"Type","tag":"Type","type":"*variable","value":"~*req.7"},{"path":"Value","tag":"Value","type":"*variable","value":"~*req.8"},{"path":"Blocker","tag":"Blocker","type":"*variable","value":"~*req.9"},{"path":"Weight","tag":"Weight","type":"*variable","value":"~*req.10"}],"file_name":"Attributes.csv","flags":null,"type":"*attributes"},{"fields":[{"mandatory":true,"path":"Tenant","tag":"Tenant","type":"*variable","value":"~*req.0"},{"mandatory":true,"path":"ID","tag":"ID","type":"*variable","value":"~*req.1"},{"path":"Type","tag":"Type","type":"*variable","value":"~*req.2"},{"path":"Element","tag":"Element","type":"*variable","value":"~*req.3"},{"path":"Values","tag":"Values","type":"*variable","value":"~*req.4"},{"path":"ActivationInterval","tag":"ActivationInterval","type":"*variable","value":"~*req.5"}],"file_name":"Filters.csv","flags":null,"type":"*filters"},{"fields":[{"mandatory":true,"path":"Tenant","tag":"Tenant","type":"*variable","value":"~*req.0"},{"mandatory":true,"path":"ID","tag":"ID","type":"*variable","value":"~*req.1"},{"path":"FilterIDs","tag":"FilterIDs","type":"*variable","value":"~*req.2"},{"path":"ActivationInterval","tag":"ActivationInterval","type":"*variable","value":"~*req.3"},{"path":"UsageTTL","tag":"TTL","type":"*variable","value":"~*req.4"},{"path":"Limit","tag":"Limit","type":"*variable","value":"~*req.5"},{"path":"AllocationMessage","tag":"AllocationMessage","type":"*variable","value":"~*req.6"},{"path":"Blocker","tag":"Blocker","type":"*variable","value":"~*req.7"},{"path":"Stored","tag":"Stored","type":"*variable","value":"~*req.8"},{"path":"Weight","tag":"Weight","type":"*variable","value":"~*req.9"},{"path":"ThresholdIDs","tag":"ThresholdIDs","type":"*variable","value":"~*req.10"}],"file_name":"Resources.csv","flags":null,"type":"*resources"},{"fields":[{"mandatory":true,"path":"Tenant","tag":"Tenant","type":"*variable","value":"~*req.0"},{"mandatory":true,"path":"ID","tag":"ID","type":"*variable","value":"~*req.1"},{"path":"FilterIDs","tag":"FilterIDs","type":"*variable","value":"~*req.2"},{"path":"ActivationInterval","tag":"ActivationInterval","type":"*variable","value":"~*req.3"},{"path":"QueueLength","tag":"QueueLength","type":"*variable","value":"~*req.4"},{"path":"TTL","tag":"TTL","type":"*variable","value":"~*req.5"},{"path":"MinItems","tag":"MinItems","type":"*variable","value":"~*req.6"},{"path":"MetricIDs","tag":"MetricIDs","type":"*variable","value":"~*req.7"},{"path":"MetricFilterIDs","tag":"MetricFilterIDs","type":"*variable","value":"~*req.8"},{"path":"Blocker","tag":"Blocker","type":"*variable","value":"~*req.9"},{"path":"Stored","tag":"Stored","type":"*variable","value":"~*req.10"},{"path":"Weight","tag":"Weight","type":"*variable","value":"~*req.11"},{"path":"ThresholdIDs","tag":"ThresholdIDs","type":"*variable","value":"~*req.12"}],"file_name":"Stats.csv","flags":null,"type":"*stats"},{"fields":[{"mandatory":true,"path":"Tenant","tag":"Tenant","type":"*variable","value":"~*req.0"},{"mandatory":true,"path":"ID","tag":"ID","type":"*variable","value":"~*req.1"},{"path":"FilterIDs","tag":"FilterIDs","type":"*variable","value":"~*req.2"},{"path":"ActivationInterval","tag":"ActivationInterval","type":"*variable","value":"~*req.3"},{"path":"MaxHits","tag":"MaxHits","type":"*variable","value":"~*req.4"},{"path":"MinHits","tag":"MinHits","type":"*variable","value":"~*req.5"},{"path":"MinSleep","tag":"MinSleep","type":"*variable","value":"~*req.6"},{"path":"Blocker","tag":"Blocker","type":"*variable","value":"~*req.7"},{"path":"Weight","tag":"Weight","type":"*variable","value":"~*req.8"},{"path":"ActionIDs","tag":"ActionIDs","type":"*variable","value":"~*req.9"},{"path":"Async","tag":"Async","type":"*variable","value":"~*req.10"}],"file_name":"Thresholds.csv","flags":null,"type":"*thresholds"},{"fields":[{"mandatory":true,"path":"Tenant","tag":"Tenant","type":"*variable","value":"~*req.0"},{"mandatory":true,"path":"ID","tag":"ID","type":"*variable","value":"~*req.1"},{"path":"FilterIDs","tag":"FilterIDs","type":"*variable","value":"~*req.2"},{"path":"ActivationInterval","tag":"ActivationInterval","type":"*variable","value":"~*req.3"},{"path":"Sorting","tag":"Sorting","type":"*variable","value":"~*req.4"},{"path":"SortingParameters","tag":"SortingParameters","type":"*variable","value":"~*req.5"},{"path":"RouteID","tag":"RouteID","type":"*variable","value":"~*req.6"},{"path":"RouteFilterIDs","tag":"RouteFilterIDs","type":"*variable","value":"~*req.7"},{"path":"RouteAccountIDs","tag":"RouteAccountIDs","type":"*variable","value":"~*req.8"},{"path":"RouteRatingPlanIDs","tag":"RouteRatingPlanIDs","type":"*variable","value":"~*req.9"},{"path":"RouteResourceIDs","tag":"RouteResourceIDs","type":"*variable","value":"~*req.10"},{"path":"RouteStatIDs","tag":"RouteStatIDs","type":"*variable","value":"~*req.11"},{"path":"RouteWeight","tag":"RouteWeight","type":"*variable","value":"~*req.12"},{"path":"RouteBlocker","tag":"RouteBlocker","type":"*variable","value":"~*req.13"},{"path":"RouteParameters","tag":"RouteParameters","type":"*variable","value":"~*req.14"},{"path":"Weight","tag":"Weight","type":"*variable","value":"~*req.15"}],"file_name":"Routes.csv","flags":null,"type":"*routes"},{"fields":[{"mandatory":true,"path":"Tenant","tag":"Tenant","type":"*variable","value":"~*req.0"},{"mandatory":true,"path":"ID","tag":"ID","type":"*variable","value":"~*req.1"},{"path":"FilterIDs","tag":"FilterIDs","type":"*variable","value":"~*req.2"},{"path":"ActivationInterval","tag":"ActivationInterval","type":"*variable","value":"~*req.3"},{"path":"RunID","tag":"RunID","type":"*variable","value":"~*req.4"},{"path":"AttributeIDs","tag":"AttributeIDs","type":"*variable","value":"~*req.5"},{"path":"Weight","tag":"Weight","type":"*variable","value":"~*req.6"}],"file_name":"Chargers.csv","flags":null,"type":"*chargers"},{"fields":[{"mandatory":true,"path":"Tenant","tag":"Tenant","type":"*variable","value":"~*req.0"},{"mandatory":true,"path":"ID","tag":"ID","type":"*variable","value":"~*req.1"},{"path":"Contexts","tag":"Contexts","type":"*variable","value":"~*req.2"},{"path":"FilterIDs","tag":"FilterIDs","type":"*variable","value":"~*req.3"},{"path":"ActivationInterval","tag":"ActivationInterval","type":"*variable","value":"~*req.4"},{"path":"Strategy","tag":"Strategy","type":"*variable","value":"~*req.5"},{"path":"StrategyParameters","tag":"StrategyParameters","type":"*variable","value":"~*req.6"},{"path":"ConnID","tag":"ConnID","type":"*variable","value":"~*req.7"},{"path":"ConnFilterIDs","tag":"ConnFilterIDs","type":"*variable","value":"~*req.8"},{"path":"ConnWeight","tag":"ConnWeight","type":"*variable","value":"~*req.9"},{"path":"ConnBlocker","tag":"ConnBlocker","type":"*variable","value":"~*req.10"},{"path":"ConnParameters","tag":"ConnParameters","type":"*variable","value":"~*req.11"},{"path":"Weight","tag":"Weight","type":"*variable","value":"~*req.12"}],"file_name":"DispatcherProfiles.csv","flags":null,"type":"*dispatchers"},{"fields":[{"mandatory":true,"path":"Tenant","tag":"Tenant","type":"*variable","value":"~*req.0"},{"mandatory":true,"path":"ID","tag":"ID","type":"*variable","value":"~*req.1"},{"path":"Address","tag":"Address","type":"*variable","value":"~*req.2"},{"path":"Transport","tag":"Transport","type":"*variable","value":"~*req.3"},{"path":"ConnectAttempts","tag":"ConnectAttempts","type":"*variable","value":"~*req.4"},{"path":"Reconnects","tag":"Reconnects","type":"*variable","value":"~*req.5"},{"path":"MaxReconnectInterval","tag":"MaxReconnectInterval","type":"*variable","value":"~*req.6"},{"path":"ConnectTimeout","tag":"ConnectTimeout","type":"*variable","value":"~*req.7"},{"path":"ReplyTimeout","tag":"ReplyTimeout","type":"*variable","value":"~*req.8"},{"path":"TLS","tag":"TLS","type":"*variable","value":"~*req.9"},{"path":"ClientKey","tag":"ClientKey","type":"*variable","value":"~*req.10"},{"path":"ClientCertificate","tag":"ClientCertificate","type":"*variable","value":"~*req.11"},{"path":"CaCertificate","tag":"CaCertificate","type":"*variable","value":"~*req.12"}],"file_name":"DispatcherHosts.csv","flags":null,"type":"*dispatcher_hosts"}],"dry_run":false,"enabled":false,"field_separator":",","id":"*default","lockfile_path":".cgr.lck","run_delay":"0","tenant":"","tp_in_dir":"/var/spool/cgrates/loader/in","tp_out_dir":"/var/spool/cgrates/loader/out"}],"mailer":{"auth_password":"CGRateS.org","auth_user":"cgrates","from_address":"cgr-mailer@localhost.localdomain","server":"localhost"},"migrator":{"out_datadb_encoding":"msgpack","out_datadb_host":"127.0.0.1","out_datadb_name":"10","out_datadb_opts":{"mongoConnScheme":"mongodb","mongoQueryTimeout":"0s","redisCACertificate":"","redisClientCertificate":"","redisClientKey":"","redisCluster":false,"redisClusterOndownDelay":"0s","redisClusterSync":"5s","redisConnectAttempts":20,"redisConnectTimeout":"0s","redisMaxConns":10,"redisReadTimeout":"0s","redisSentinel":"","redisTLS":false,"redisWriteTimeout":"0s"},"out_datadb_password":"","out_datadb_port":"6379","out_datadb_type":"*redis","out_datadb_user":"cgrates","out_stordb_host":"127.0.0.1","out_stordb_name":"cgrates","out_stordb_opts":{"mongoConnScheme":"mongodb","mongoQueryTimeout":"0s","mysqlDSNParams":null,"mysqlLocation":"","pgSSLMode":"","sqlConnMaxLifetime":"0s","sqlMaxIdleConns":0,"sqlMaxOpenConns":0},"out_stordb_password":"","out_stordb_port":"3306","out_stordb_type":"*mysql","out_stordb_user":"cgrates","users_filters":null},"radius_agent":{"client_dictionaries":{"*default":["/usr/share/cgrates/radius/dict/"]},"client_secrets":{"*default":"CGRateS.org"},"coa_template":"*coa","dmr_template":"*dmr","enabled":false,"listeners":[{"acct_address":"127.0.0.1:1813","auth_address":"127.0.0.1:1812","network":"udp"}],"request_processors":[],"requests_cache_key":"","sessions_conns":["*internal"]},"rals":{"balance_rating_subject":{"*any":"*zero1ns","*voice":"*zero1s"},"enabled":false,"fallback_depth":3,"max_computed_usage":{"*any":"189h0m0s","*data":"107374182400","*mms":"10000","*sms":"10000","*voice":"72h0m0s"},"max_increments":1000000,"remove_expired":true,"rp_subject_prefix_matching":false,"sessions_conns":[],"stats_conns":[],"thresholds_conns":[]},"registrarc":{"dispatchers":{"hosts":[],"refresh_interval":"5m0s","registrars_conns":[]},"rpc":{"hosts":[],"refresh_interval":"5m0s","registrars_conns":[]}},"resources":{"enabled":false,"indexed_selects":true,"nested_fields":false,"opts":{"*units":1,"*usageID":""},"prefix_indexed_fields":[],"store_interval":"","suffix_indexed_fields":[],"thresholds_conns":[]},"routes":{"attributes_conns":[],"default_ratio":1,"enabled":false,"indexed_selects":true,"nested_fields":false,"opts":{"*context":"*routes","*ignoreErrors":false,"*maxCost":""},"prefix_indexed_fields":[],"rals_conns":[],"resources_conns":[],"stats_conns":[],"suffix_indexed_fields":[]},"rpc_conns":{"*bijson_localhost":{"conns":[{"address":"127.0.0.1:2014","transport":"*birpc_json"}],"poolSize":0,"strategy":"*first"},"*birpc_internal":{"conns":[{"address":"*birpc_internal","transport":""}],"poolSize":0,"strategy":"*first"},"*internal":{"conns":[{"address":"*internal","transport":""}],"poolSize":0,"strategy":"*first"},"*localhost":{"conns":[{"address":"127.0.0.1:2012","transport":"*json"}],"poolSize":0,"strategy":"*first"}},"sags":{"enabled":false},"sars":{"enabled":false,"stats_conns":[]},"schedulers":{"cdrs_conns":[],"dynaprepaid_actionplans":[],"enabled":false,"filters":[],"stats_conns":[],"thresholds_conns":[]},"sentrypeer":{"Audience":"https://sentrypeer.com/api","ClientID":"","ClientSecret":"","GrantType":"client_credentials","IpUrl":"https://sentrypeer.com/api/ip-addresses","NumberUrl":"https://sentrypeer.com/api/phone-numbers","TokenURL":"https://authz.sentrypeer.com/oauth/token"},"sessions":{"alterable_fields":[],"attributes_conns":[],"cdrs_conns":[],"channel_sync_interval":"0","chargers_conns":[],"client_protocol":2,"debit_interval":"0","default_usage":{"*any":"3h0m0s","*data":"1048576","*sms":"1","*voice":"3h0m0s"},"enabled":false,"listen_bigob":"","listen_bijson":"127.0.0.1:2014","min_dur_low_balance":"0","rals_conns":[],"replication_conns":[],"resources_conns":[],"routes_conns":[],"scheduler_conns":[],"session_indexes":[],"session_ttl":"0","stale_chan_max_extra_usage":"0","stats_conns":[],"stir":{"allowed_attest":["*any"],"default_attest":"A","payload_maxduration":"-1","privatekey_path":"","publickey_path":""},"store_session_costs":false,"terminate_attempts":5,"thresholds_conns":[]},"sip_agent":{"enabled":false,"listen":"127.0.0.1:5060","listen_net":"udp","request_processors":[],"retransmission_timer":1000000000,"sessions_conns":["*internal"],"timezone":""},"stats":{"enabled":false,"indexed_selects":true,"nested_fields":false,"opts":{"*profileIDs":[],"*profileIgnoreFilters":false},"prefix_indexed_fields":[],"store_interval":"","store_uncompressed_limit":0,"suffix_indexed_fields":[],"thresholds_conns":[]},"stor_db":{"db_host":"127.0.0.1","db_name":"cgrates","db_password":"CGRateS.org","db_port":3306,"db_type":"*mysql","db_user":"cgrates","items":{"*cdrs":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*session_costs":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*tp_account_actions":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*tp_action_plans":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*tp_action_triggers":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*tp_actions":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*tp_attributes":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*tp_chargers":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*tp_destination_rates":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*tp_destinations":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*tp_dispatcher_hosts":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*tp_dispatcher_profiles":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*tp_filters":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*tp_rates":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*tp_rating_plans":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*tp_rating_profiles":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*tp_resources":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*tp_routes":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*tp_shared_groups":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*tp_stats":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*tp_thresholds":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*tp_timings":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*versions":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false}},"opts":{"mongoConnScheme":"mongodb","mongoQueryTimeout":"10s","mysqlDSNParams":{},"mysqlLocation":"Local","pgSSLMode":"disable","pgSchema":"","sqlConnMaxLifetime":"0s","sqlMaxIdleConns":10,"sqlMaxOpenConns":100},"prefix_indexed_fields":[],"remote_conns":null,"replication_conns":null,"string_indexed_fields":[]},"suretax":{"bill_to_number":"","business_unit":"","client_number":"","client_tracking":"~*req.CGRID","customer_number":"~*req.Subject","include_local_cost":false,"orig_number":"~*req.Subject","p2pplus4":"","p2pzipcode":"","plus4":"","regulatory_code":"03","response_group":"03","response_type":"D4","return_file_code":"0","sales_type_code":"R","tax_exemption_code_list":"","tax_included":"0","tax_situs_rule":"04","term_number":"~*req.Destination","timezone":"UTC","trans_type_code":"010101","unit_type":"00","units":"1","url":"","validation_key":"","zipcode":""},"templates":{"*asr":[{"mandatory":true,"path":"*diamreq.Session-Id","tag":"SessionId","type":"*variable","value":"~*req.Session-Id"},{"mandatory":true,"path":"*diamreq.Origin-Host","tag":"OriginHost","type":"*variable","value":"~*req.Destination-Host"},{"mandatory":true,"path":"*diamreq.Origin-Realm","tag":"OriginRealm","type":"*variable","value":"~*req.Destination-Realm"},{"mandatory":true,"path":"*diamreq.Destination-Realm","tag":"DestinationRealm","type":"*variable","value":"~*req.Origin-Realm"},{"mandatory":true,"path":"*diamreq.Destination-Host","tag":"DestinationHost","type":"*variable","value":"~*req.Origin-Host"},{"mandatory":true,"path":"*diamreq.Auth-Application-Id","tag":"AuthApplicationId","type":"*variable","value":"~*vars.*appid"}],"*cca":[{"mandatory":true,"path":"*rep.Session-Id","tag":"SessionId","type":"*variable","value":"~*req.Session-Id"},{"path":"*rep.Result-Code","tag":"ResultCode","type":"*constant","value":"2001"},{"mandatory":true,"path":"*rep.Origin-Host","tag":"OriginHost","type":"*variable","value":"~*vars.OriginHost"},{"mandatory":true,"path":"*rep.Origin-Realm","tag":"OriginRealm","type":"*variable","value":"~*vars.OriginRealm"},{"mandatory":true,"path":"*rep.Auth-Application-Id","tag":"AuthApplicationId","type":"*variable","value":"~*vars.*appid"},{"mandatory":true,"path":"*rep.CC-Request-Type","tag":"CCRequestType","type":"*variable","value":"~*req.CC-Request-Type"},{"mandatory":true,"path":"*rep.CC-Request-Number","tag":"CCRequestNumber","type":"*variable","value":"~*req.CC-Request-Number"}],"*cdrLog":[{"mandatory":true,"path":"*cdr.ToR","tag":"ToR","type":"*variable","value":"~*req.BalanceType"},{"mandatory":true,"path":"*cdr.OriginHost","tag":"OriginHost","type":"*constant","value":"127.0.0.1"},{"mandatory":true,"path":"*cdr.RequestType","tag":"RequestType","type":"*constant","value":"*none"},{"mandatory":true,"path":"*cdr.Tenant","tag":"Tenant","type":"*variable","value":"~*req.Tenant"},{"mandatory":true,"path":"*cdr.Account","tag":"Account","type":"*variable","value":"~*req.Account"},{"mandatory":true,"path":"*cdr.Subject","tag":"Subject","type":"*variable","value":"~*req.Account"},{"mandatory":true,"path":"*cdr.Cost","tag":"Cost","type":"*variable","value":"~*req.Cost"},{"mandatory":true,"path":"*cdr.Source","tag":"Source","type":"*constant","value":"*cdrLog"},{"mandatory":true,"path":"*cdr.Usage","tag":"Usage","type":"*constant","value":"1"},{"mandatory":true,"path":"*cdr.RunID","tag":"RunID","type":"*variable","value":"~*req.ActionType"},{"mandatory":true,"path":"*cdr.SetupTime","tag":"SetupTime","type":"*constant","value":"*now"},{"mandatory":true,"path":"*cdr.AnswerTime","tag":"AnswerTime","type":"*constant","value":"*now"},{"mandatory":true,"path":"*cdr.PreRated","tag":"PreRated","type":"*constant","value":"true"}],"*coa":[{"path":"*radDAReq.User-Name","tag":"User-Name","type":"*variable","value":"~*oreq.User-Name"},{"path":"*radDAReq.NAS-IP-Address","tag":"NAS-IP-Address","type":"*variable","value":"~*oreq.NAS-IP-Address"},{"path":"*radDAReq.Acct-Session-Id","tag":"Acct-Session-Id","type":"*variable","value":"~*oreq.Acct-Session-Id"},{"path":"*radDAReq.Filter-Id","tag":"Filter-Id","type":"*variable","value":"~*req.CustomFilter"}],"*dmr":[{"path":"*radDAReq.User-Name","tag":"User-Name","type":"*variable","value":"~*oreq.User-Name"},{"path":"*radDAReq.NAS-IP-Address","tag":"NAS-IP-Address","type":"*variable","value":"~*oreq.NAS-IP-Address"},{"path":"*radDAReq.Acct-Session-Id","tag":"Acct-Session-Id","type":"*variable","value":"~*oreq.Acct-Session-Id"},{"path":"*radDAReq.Reply-Message","tag":"Reply-Message","type":"*variable","value":"~*req.DisconnectCause"}],"*err":[{"mandatory":true,"path":"*rep.Session-Id","tag":"SessionId","type":"*variable","value":"~*req.Session-Id"},{"mandatory":true,"path":"*rep.Origin-Host","tag":"OriginHost","type":"*variable","value":"~*vars.OriginHost"},{"mandatory":true,"path":"*rep.Origin-Realm","tag":"OriginRealm","type":"*variable","value":"~*vars.OriginRealm"}],"*errSip":[{"mandatory":true,"path":"*rep.Request","tag":"Request","type":"*constant","value":"SIP/2.0 500 Internal Server Error"}],"*rar":[{"mandatory":true,"path":"*diamreq.Session-Id","tag":"SessionId","type":"*variable","value":"~*req.Session-Id"},{"mandatory":true,"path":"*diamreq.Origin-Host","tag":"OriginHost","type":"*variable","value":"~*req.Destination-Host"},{"mandatory":true,"path":"*diamreq.Origin-Realm","tag":"OriginRealm","type":"*variable","value":"~*req.Destination-Realm"},{"mandatory":true,"path":"*diamreq.Destination-Realm","tag":"DestinationRealm","type":"*variable","value":"~*req.Origin-Realm"},{"mandatory":true,"path":"*diamreq.Destination-Host","tag":"DestinationHost","type":"*variable","value":"~*req.Origin-Host"},{"mandatory":true,"path":"*diamreq.Auth-Application-Id","tag":"AuthApplicationId","type":"*variable","value":"~*vars.*appid"},{"path":"*diamreq.Re-Auth-Request-Type","tag":"ReAuthRequestType","type":"*constant","value":"0"}]},"thresholds":{"enabled":false,"indexed_selects":true,"nested_fields":false,"opts":{"*profileIDs":[],"*profileIgnoreFilters":false},"prefix_indexed_fields":[],"store_interval":"","suffix_indexed_fields":[]},"tls":{"ca_certificate":"","client_certificate":"","client_key":"","server_certificate":"","server_key":"","server_name":"","server_policy":4}}`
+ expected := `{"analyzers":{"cleanup_interval":"1h0m0s","db_path":"/var/spool/cgrates/analyzers","enabled":false,"index_type":"*scorch","ttl":"24h0m0s"},"apiban":{"keys":[]},"apiers":{"attributes_conns":[],"caches_conns":["*internal"],"ees_conns":[],"enabled":false,"scheduler_conns":[]},"asterisk_agent":{"asterisk_conns":[{"address":"127.0.0.1:8088","alias":"","connect_attempts":3,"max_reconnect_interval":"0s","password":"CGRateS.org","reconnects":5,"user":"cgrates"}],"create_cdr":false,"enabled":false,"sessions_conns":["*birpc_internal"]},"attributes":{"any_context":true,"apiers_conns":[],"enabled":false,"indexed_selects":true,"nested_fields":false,"opts":{"*processRuns":1,"*profileIDs":[],"*profileIgnoreFilters":false,"*profileRuns":0},"prefix_indexed_fields":[],"resources_conns":[],"stats_conns":[],"suffix_indexed_fields":[]},"caches":{"partitions":{"*account_action_plans":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*action_plans":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*action_triggers":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*actions":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*apiban":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false,"ttl":"2m0s"},"*attribute_filter_indexes":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*attribute_profiles":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*caps_events":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*cdr_ids":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false,"ttl":"10m0s"},"*charger_filter_indexes":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*charger_profiles":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*closed_sessions":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false,"ttl":"10s"},"*destinations":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*diameter_messages":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false,"ttl":"3h0m0s"},"*dispatcher_filter_indexes":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*dispatcher_hosts":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*dispatcher_loads":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*dispatcher_profiles":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*dispatcher_routes":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*dispatchers":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*event_charges":{"limit":0,"precache":false,"remote":false,"replicate":false,"static_ttl":false,"ttl":"10s"},"*event_resources":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*filters":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*load_ids":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*radius_packets":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false,"ttl":"3h0m0s"},"*rating_plans":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*rating_profiles":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*replication_hosts":{"limit":0,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*resource_filter_indexes":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*resource_profiles":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*resources":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*reverse_destinations":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*reverse_filter_indexes":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*route_filter_indexes":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*route_profiles":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*rpc_connections":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*rpc_responses":{"limit":0,"precache":false,"remote":false,"replicate":false,"static_ttl":false,"ttl":"2s"},"*sentrypeer":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":true,"ttl":"24h0m0s"},"*shared_groups":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*stat_filter_indexes":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*statqueue_profiles":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*statqueues":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*stir":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false,"ttl":"3h0m0s"},"*threshold_filter_indexes":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*threshold_profiles":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*thresholds":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*timings":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false},"*uch":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false,"ttl":"3h0m0s"}},"remote_conns":[],"replication_conns":[]},"cdrs":{"attributes_conns":[],"chargers_conns":[],"ees_conns":[],"enabled":false,"extra_fields":[],"online_cdr_exports":[],"rals_conns":[],"scheduler_conns":[],"session_cost_retries":5,"stats_conns":[],"store_cdrs":true,"thresholds_conns":[]},"chargers":{"attributes_conns":[],"enabled":false,"indexed_selects":true,"nested_fields":false,"prefix_indexed_fields":[],"suffix_indexed_fields":[]},"configs":{"enabled":false,"root_dir":"/var/spool/cgrates/configs","url":"/configs/"},"cores":{"caps":0,"caps_stats_interval":"0","caps_strategy":"*busy","shutdown_timeout":"1s"},"data_db":{"db_host":"127.0.0.1","db_name":"10","db_password":"","db_port":6379,"db_type":"*redis","db_user":"cgrates","items":{"*account_action_plans":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*accounts":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*action_plans":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*action_triggers":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*actions":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*attribute_filter_indexes":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*attribute_profiles":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*charger_filter_indexes":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*charger_profiles":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*destinations":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*dispatcher_filter_indexes":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*dispatcher_hosts":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*dispatcher_profiles":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*filters":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*load_ids":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*rating_plans":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*rating_profiles":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*resource_filter_indexes":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*resource_profiles":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*resources":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*reverse_destinations":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*reverse_filter_indexes":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*route_filter_indexes":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*route_profiles":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*sessions_backup":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*shared_groups":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*stat_filter_indexes":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*statqueue_profiles":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*statqueues":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*threshold_filter_indexes":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*threshold_profiles":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*thresholds":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*timings":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*versions":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false}},"opts":{"mongoConnScheme":"mongodb","mongoQueryTimeout":"10s","redisCACertificate":"","redisClientCertificate":"","redisClientKey":"","redisCluster":false,"redisClusterOndownDelay":"0s","redisClusterSync":"5s","redisConnectAttempts":20,"redisConnectTimeout":"0s","redisMaxConns":10,"redisReadTimeout":"0s","redisSentinel":"","redisTLS":false,"redisWriteTimeout":"0s"},"remote_conn_id":"","remote_conns":[],"replication_cache":"","replication_conns":[],"replication_filtered":false},"diameter_agent":{"asr_template":"","concurrent_requests":-1,"dictionaries_path":"/usr/share/cgrates/diameter/dict/","enabled":false,"forced_disconnect":"*none","listen":"127.0.0.1:3868","listen_net":"tcp","origin_host":"CGR-DA","origin_realm":"cgrates.org","product_name":"CGRateS","rar_template":"","request_processors":[],"sessions_conns":["*birpc_internal"],"synced_conn_requests":false,"vendor_id":0},"dispatchers":{"any_subsystem":true,"attributes_conns":[],"enabled":false,"indexed_selects":true,"nested_fields":false,"prefix_indexed_fields":[],"prevent_loop":false,"suffix_indexed_fields":[]},"dns_agent":{"enabled":false,"listeners":[{"address":"127.0.0.1:53","network":"udp"}],"request_processors":[],"sessions_conns":["*internal"],"timezone":""},"ees":{"attributes_conns":[],"cache":{"*file_csv":{"limit":-1,"precache":false,"remote":false,"replicate":false,"static_ttl":false,"ttl":"5s"}},"enabled":false,"exporters":[{"attempts":1,"attribute_context":"","attribute_ids":[],"concurrent_requests":0,"export_path":"/var/spool/cgrates/ees","failed_posts_dir":"/var/spool/cgrates/failed_posts","fields":[],"filters":[],"flags":[],"id":"*default","opts":{},"synchronous":false,"timezone":"","type":"*none"}]},"ers":{"concurrent_events":1,"ees_conns":[],"enabled":false,"partial_cache_ttl":"1s","readers":[{"cache_dump_fields":[],"concurrent_requests":1024,"fields":[{"mandatory":true,"path":"*cgreq.ToR","tag":"ToR","type":"*variable","value":"~*req.2"},{"mandatory":true,"path":"*cgreq.OriginID","tag":"OriginID","type":"*variable","value":"~*req.3"},{"mandatory":true,"path":"*cgreq.RequestType","tag":"RequestType","type":"*variable","value":"~*req.4"},{"mandatory":true,"path":"*cgreq.Tenant","tag":"Tenant","type":"*variable","value":"~*req.6"},{"mandatory":true,"path":"*cgreq.Category","tag":"Category","type":"*variable","value":"~*req.7"},{"mandatory":true,"path":"*cgreq.Account","tag":"Account","type":"*variable","value":"~*req.8"},{"mandatory":true,"path":"*cgreq.Subject","tag":"Subject","type":"*variable","value":"~*req.9"},{"mandatory":true,"path":"*cgreq.Destination","tag":"Destination","type":"*variable","value":"~*req.10"},{"mandatory":true,"path":"*cgreq.SetupTime","tag":"SetupTime","type":"*variable","value":"~*req.11"},{"mandatory":true,"path":"*cgreq.AnswerTime","tag":"AnswerTime","type":"*variable","value":"~*req.12"},{"mandatory":true,"path":"*cgreq.Usage","tag":"Usage","type":"*variable","value":"~*req.13"}],"filters":[],"flags":[],"id":"*default","max_reconnect_interval":"5m0s","opts":{"csvFieldSeparator":",","csvHeaderDefineChar":":","csvRowLength":0,"natsSubject":"cgrates_cdrs","partialCacheAction":"*none","partialOrderField":"~*req.AnswerTime"},"partial_commit_fields":[],"processed_path":"/var/spool/cgrates/ers/out","reconnects":-1,"run_delay":"0","source_path":"/var/spool/cgrates/ers/in","tenant":"","timezone":"","type":"*none"}],"sessions_conns":["*internal"]},"filters":{"apiers_conns":[],"resources_conns":[],"stats_conns":[]},"freeswitch_agent":{"active_session_delimiter":",","create_cdr":false,"empty_balance_ann_file":"","empty_balance_context":"","enabled":false,"event_socket_conns":[{"address":"127.0.0.1:8021","alias":"127.0.0.1:8021","max_reconnect_interval":"0s","password":"ClueCon","reconnects":5,"reply_timeout":"1m0s"}],"extra_fields":"","low_balance_ann_file":"","max_wait_connection":"2s","sessions_conns":["*birpc_internal"],"subscribe_park":true},"general":{"caching_delay":"0","connect_attempts":5,"connect_timeout":"1s","dbdata_encoding":"*msgpack","default_caching":"*reload","default_category":"call","default_request_type":"*rated","default_tenant":"cgrates.org","default_timezone":"Local","digest_equal":":","digest_separator":",","failed_posts_dir":"/var/spool/cgrates/failed_posts","failed_posts_ttl":"5s","locking_timeout":"0","log_level":6,"logger":"*syslog","max_parallel_conns":100,"max_reconnect_interval":"0","node_id":"ENGINE1","poster_attempts":3,"reconnects":-1,"reply_timeout":"2s","rounding_decimals":5,"rsr_separator":";","tpexport_dir":"/var/spool/cgrates/tpe"},"http":{"auth_users":{},"client_opts":{"dialFallbackDelay":"300ms","dialKeepAlive":"30s","dialTimeout":"30s","disableCompression":false,"disableKeepAlives":false,"expectContinueTimeout":"0s","forceAttemptHttp2":true,"idleConnTimeout":"1m30s","maxConnsPerHost":0,"maxIdleConns":100,"maxIdleConnsPerHost":2,"responseHeaderTimeout":"0s","skipTlsVerify":false,"tlsHandshakeTimeout":"10s"},"freeswitch_cdrs_url":"/freeswitch_json","http_cdrs":"/cdr_http","json_rpc_url":"/jsonrpc","registrars_url":"/registrar","use_basic_auth":false,"ws_url":"/ws"},"http_agent":[],"kamailio_agent":{"create_cdr":false,"enabled":false,"evapi_conns":[{"address":"127.0.0.1:8448","alias":"","max_reconnect_interval":"0s","reconnects":5}],"sessions_conns":["*birpc_internal"],"timezone":""},"listen":{"http":"127.0.0.1:2080","http_tls":"127.0.0.1:2280","rpc_gob":"127.0.0.1:2013","rpc_gob_tls":"127.0.0.1:2023","rpc_json":"127.0.0.1:2012","rpc_json_tls":"127.0.0.1:2022"},"loader":{"caches_conns":["*localhost"],"data_path":"./","disable_reverse":false,"field_separator":",","gapi_credentials":".gapi/credentials.json","gapi_token":".gapi/token.json","scheduler_conns":["*localhost"],"tpid":""},"loaders":[{"caches_conns":["*internal"],"data":[{"fields":[{"mandatory":true,"path":"Tenant","tag":"TenantID","type":"*variable","value":"~*req.0"},{"mandatory":true,"path":"ID","tag":"ProfileID","type":"*variable","value":"~*req.1"},{"path":"Contexts","tag":"Contexts","type":"*variable","value":"~*req.2"},{"path":"FilterIDs","tag":"FilterIDs","type":"*variable","value":"~*req.3"},{"path":"ActivationInterval","tag":"ActivationInterval","type":"*variable","value":"~*req.4"},{"path":"AttributeFilterIDs","tag":"AttributeFilterIDs","type":"*variable","value":"~*req.5"},{"path":"Path","tag":"Path","type":"*variable","value":"~*req.6"},{"path":"Type","tag":"Type","type":"*variable","value":"~*req.7"},{"path":"Value","tag":"Value","type":"*variable","value":"~*req.8"},{"path":"Blocker","tag":"Blocker","type":"*variable","value":"~*req.9"},{"path":"Weight","tag":"Weight","type":"*variable","value":"~*req.10"}],"file_name":"Attributes.csv","flags":null,"type":"*attributes"},{"fields":[{"mandatory":true,"path":"Tenant","tag":"Tenant","type":"*variable","value":"~*req.0"},{"mandatory":true,"path":"ID","tag":"ID","type":"*variable","value":"~*req.1"},{"path":"Type","tag":"Type","type":"*variable","value":"~*req.2"},{"path":"Element","tag":"Element","type":"*variable","value":"~*req.3"},{"path":"Values","tag":"Values","type":"*variable","value":"~*req.4"},{"path":"ActivationInterval","tag":"ActivationInterval","type":"*variable","value":"~*req.5"}],"file_name":"Filters.csv","flags":null,"type":"*filters"},{"fields":[{"mandatory":true,"path":"Tenant","tag":"Tenant","type":"*variable","value":"~*req.0"},{"mandatory":true,"path":"ID","tag":"ID","type":"*variable","value":"~*req.1"},{"path":"FilterIDs","tag":"FilterIDs","type":"*variable","value":"~*req.2"},{"path":"ActivationInterval","tag":"ActivationInterval","type":"*variable","value":"~*req.3"},{"path":"UsageTTL","tag":"TTL","type":"*variable","value":"~*req.4"},{"path":"Limit","tag":"Limit","type":"*variable","value":"~*req.5"},{"path":"AllocationMessage","tag":"AllocationMessage","type":"*variable","value":"~*req.6"},{"path":"Blocker","tag":"Blocker","type":"*variable","value":"~*req.7"},{"path":"Stored","tag":"Stored","type":"*variable","value":"~*req.8"},{"path":"Weight","tag":"Weight","type":"*variable","value":"~*req.9"},{"path":"ThresholdIDs","tag":"ThresholdIDs","type":"*variable","value":"~*req.10"}],"file_name":"Resources.csv","flags":null,"type":"*resources"},{"fields":[{"mandatory":true,"path":"Tenant","tag":"Tenant","type":"*variable","value":"~*req.0"},{"mandatory":true,"path":"ID","tag":"ID","type":"*variable","value":"~*req.1"},{"path":"FilterIDs","tag":"FilterIDs","type":"*variable","value":"~*req.2"},{"path":"ActivationInterval","tag":"ActivationInterval","type":"*variable","value":"~*req.3"},{"path":"QueueLength","tag":"QueueLength","type":"*variable","value":"~*req.4"},{"path":"TTL","tag":"TTL","type":"*variable","value":"~*req.5"},{"path":"MinItems","tag":"MinItems","type":"*variable","value":"~*req.6"},{"path":"MetricIDs","tag":"MetricIDs","type":"*variable","value":"~*req.7"},{"path":"MetricFilterIDs","tag":"MetricFilterIDs","type":"*variable","value":"~*req.8"},{"path":"Blocker","tag":"Blocker","type":"*variable","value":"~*req.9"},{"path":"Stored","tag":"Stored","type":"*variable","value":"~*req.10"},{"path":"Weight","tag":"Weight","type":"*variable","value":"~*req.11"},{"path":"ThresholdIDs","tag":"ThresholdIDs","type":"*variable","value":"~*req.12"}],"file_name":"Stats.csv","flags":null,"type":"*stats"},{"fields":[{"mandatory":true,"path":"Tenant","tag":"Tenant","type":"*variable","value":"~*req.0"},{"mandatory":true,"path":"ID","tag":"ID","type":"*variable","value":"~*req.1"},{"path":"FilterIDs","tag":"FilterIDs","type":"*variable","value":"~*req.2"},{"path":"ActivationInterval","tag":"ActivationInterval","type":"*variable","value":"~*req.3"},{"path":"MaxHits","tag":"MaxHits","type":"*variable","value":"~*req.4"},{"path":"MinHits","tag":"MinHits","type":"*variable","value":"~*req.5"},{"path":"MinSleep","tag":"MinSleep","type":"*variable","value":"~*req.6"},{"path":"Blocker","tag":"Blocker","type":"*variable","value":"~*req.7"},{"path":"Weight","tag":"Weight","type":"*variable","value":"~*req.8"},{"path":"ActionIDs","tag":"ActionIDs","type":"*variable","value":"~*req.9"},{"path":"Async","tag":"Async","type":"*variable","value":"~*req.10"}],"file_name":"Thresholds.csv","flags":null,"type":"*thresholds"},{"fields":[{"mandatory":true,"path":"Tenant","tag":"Tenant","type":"*variable","value":"~*req.0"},{"mandatory":true,"path":"ID","tag":"ID","type":"*variable","value":"~*req.1"},{"path":"FilterIDs","tag":"FilterIDs","type":"*variable","value":"~*req.2"},{"path":"ActivationInterval","tag":"ActivationInterval","type":"*variable","value":"~*req.3"},{"path":"Sorting","tag":"Sorting","type":"*variable","value":"~*req.4"},{"path":"SortingParameters","tag":"SortingParameters","type":"*variable","value":"~*req.5"},{"path":"RouteID","tag":"RouteID","type":"*variable","value":"~*req.6"},{"path":"RouteFilterIDs","tag":"RouteFilterIDs","type":"*variable","value":"~*req.7"},{"path":"RouteAccountIDs","tag":"RouteAccountIDs","type":"*variable","value":"~*req.8"},{"path":"RouteRatingPlanIDs","tag":"RouteRatingPlanIDs","type":"*variable","value":"~*req.9"},{"path":"RouteResourceIDs","tag":"RouteResourceIDs","type":"*variable","value":"~*req.10"},{"path":"RouteStatIDs","tag":"RouteStatIDs","type":"*variable","value":"~*req.11"},{"path":"RouteWeight","tag":"RouteWeight","type":"*variable","value":"~*req.12"},{"path":"RouteBlocker","tag":"RouteBlocker","type":"*variable","value":"~*req.13"},{"path":"RouteParameters","tag":"RouteParameters","type":"*variable","value":"~*req.14"},{"path":"Weight","tag":"Weight","type":"*variable","value":"~*req.15"}],"file_name":"Routes.csv","flags":null,"type":"*routes"},{"fields":[{"mandatory":true,"path":"Tenant","tag":"Tenant","type":"*variable","value":"~*req.0"},{"mandatory":true,"path":"ID","tag":"ID","type":"*variable","value":"~*req.1"},{"path":"FilterIDs","tag":"FilterIDs","type":"*variable","value":"~*req.2"},{"path":"ActivationInterval","tag":"ActivationInterval","type":"*variable","value":"~*req.3"},{"path":"RunID","tag":"RunID","type":"*variable","value":"~*req.4"},{"path":"AttributeIDs","tag":"AttributeIDs","type":"*variable","value":"~*req.5"},{"path":"Weight","tag":"Weight","type":"*variable","value":"~*req.6"}],"file_name":"Chargers.csv","flags":null,"type":"*chargers"},{"fields":[{"mandatory":true,"path":"Tenant","tag":"Tenant","type":"*variable","value":"~*req.0"},{"mandatory":true,"path":"ID","tag":"ID","type":"*variable","value":"~*req.1"},{"path":"Contexts","tag":"Contexts","type":"*variable","value":"~*req.2"},{"path":"FilterIDs","tag":"FilterIDs","type":"*variable","value":"~*req.3"},{"path":"ActivationInterval","tag":"ActivationInterval","type":"*variable","value":"~*req.4"},{"path":"Strategy","tag":"Strategy","type":"*variable","value":"~*req.5"},{"path":"StrategyParameters","tag":"StrategyParameters","type":"*variable","value":"~*req.6"},{"path":"ConnID","tag":"ConnID","type":"*variable","value":"~*req.7"},{"path":"ConnFilterIDs","tag":"ConnFilterIDs","type":"*variable","value":"~*req.8"},{"path":"ConnWeight","tag":"ConnWeight","type":"*variable","value":"~*req.9"},{"path":"ConnBlocker","tag":"ConnBlocker","type":"*variable","value":"~*req.10"},{"path":"ConnParameters","tag":"ConnParameters","type":"*variable","value":"~*req.11"},{"path":"Weight","tag":"Weight","type":"*variable","value":"~*req.12"}],"file_name":"DispatcherProfiles.csv","flags":null,"type":"*dispatchers"},{"fields":[{"mandatory":true,"path":"Tenant","tag":"Tenant","type":"*variable","value":"~*req.0"},{"mandatory":true,"path":"ID","tag":"ID","type":"*variable","value":"~*req.1"},{"path":"Address","tag":"Address","type":"*variable","value":"~*req.2"},{"path":"Transport","tag":"Transport","type":"*variable","value":"~*req.3"},{"path":"ConnectAttempts","tag":"ConnectAttempts","type":"*variable","value":"~*req.4"},{"path":"Reconnects","tag":"Reconnects","type":"*variable","value":"~*req.5"},{"path":"MaxReconnectInterval","tag":"MaxReconnectInterval","type":"*variable","value":"~*req.6"},{"path":"ConnectTimeout","tag":"ConnectTimeout","type":"*variable","value":"~*req.7"},{"path":"ReplyTimeout","tag":"ReplyTimeout","type":"*variable","value":"~*req.8"},{"path":"TLS","tag":"TLS","type":"*variable","value":"~*req.9"},{"path":"ClientKey","tag":"ClientKey","type":"*variable","value":"~*req.10"},{"path":"ClientCertificate","tag":"ClientCertificate","type":"*variable","value":"~*req.11"},{"path":"CaCertificate","tag":"CaCertificate","type":"*variable","value":"~*req.12"}],"file_name":"DispatcherHosts.csv","flags":null,"type":"*dispatcher_hosts"}],"dry_run":false,"enabled":false,"field_separator":",","id":"*default","lockfile_path":".cgr.lck","run_delay":"0","tenant":"","tp_in_dir":"/var/spool/cgrates/loader/in","tp_out_dir":"/var/spool/cgrates/loader/out"}],"mailer":{"auth_password":"CGRateS.org","auth_user":"cgrates","from_address":"cgr-mailer@localhost.localdomain","server":"localhost"},"migrator":{"out_datadb_encoding":"msgpack","out_datadb_host":"127.0.0.1","out_datadb_name":"10","out_datadb_opts":{"mongoConnScheme":"mongodb","mongoQueryTimeout":"0s","redisCACertificate":"","redisClientCertificate":"","redisClientKey":"","redisCluster":false,"redisClusterOndownDelay":"0s","redisClusterSync":"5s","redisConnectAttempts":20,"redisConnectTimeout":"0s","redisMaxConns":10,"redisReadTimeout":"0s","redisSentinel":"","redisTLS":false,"redisWriteTimeout":"0s"},"out_datadb_password":"","out_datadb_port":"6379","out_datadb_type":"*redis","out_datadb_user":"cgrates","out_stordb_host":"127.0.0.1","out_stordb_name":"cgrates","out_stordb_opts":{"mongoConnScheme":"mongodb","mongoQueryTimeout":"0s","mysqlDSNParams":null,"mysqlLocation":"","pgSSLMode":"","sqlConnMaxLifetime":"0s","sqlMaxIdleConns":0,"sqlMaxOpenConns":0},"out_stordb_password":"","out_stordb_port":"3306","out_stordb_type":"*mysql","out_stordb_user":"cgrates","users_filters":null},"radius_agent":{"client_dictionaries":{"*default":["/usr/share/cgrates/radius/dict/"]},"client_secrets":{"*default":"CGRateS.org"},"coa_template":"*coa","dmr_template":"*dmr","enabled":false,"listeners":[{"acct_address":"127.0.0.1:1813","auth_address":"127.0.0.1:1812","network":"udp"}],"request_processors":[],"requests_cache_key":"","sessions_conns":["*internal"]},"rals":{"balance_rating_subject":{"*any":"*zero1ns","*voice":"*zero1s"},"enabled":false,"fallback_depth":3,"max_computed_usage":{"*any":"189h0m0s","*data":"107374182400","*mms":"10000","*sms":"10000","*voice":"72h0m0s"},"max_increments":1000000,"remove_expired":true,"rp_subject_prefix_matching":false,"sessions_conns":[],"stats_conns":[],"thresholds_conns":[]},"registrarc":{"dispatchers":{"hosts":[],"refresh_interval":"5m0s","registrars_conns":[]},"rpc":{"hosts":[],"refresh_interval":"5m0s","registrars_conns":[]}},"resources":{"enabled":false,"indexed_selects":true,"nested_fields":false,"opts":{"*units":1,"*usageID":""},"prefix_indexed_fields":[],"store_interval":"","suffix_indexed_fields":[],"thresholds_conns":[]},"routes":{"attributes_conns":[],"default_ratio":1,"enabled":false,"indexed_selects":true,"nested_fields":false,"opts":{"*context":"*routes","*ignoreErrors":false,"*maxCost":""},"prefix_indexed_fields":[],"rals_conns":[],"resources_conns":[],"stats_conns":[],"suffix_indexed_fields":[]},"rpc_conns":{"*bijson_localhost":{"conns":[{"address":"127.0.0.1:2014","transport":"*birpc_json"}],"poolSize":0,"strategy":"*first"},"*birpc_internal":{"conns":[{"address":"*birpc_internal","transport":""}],"poolSize":0,"strategy":"*first"},"*internal":{"conns":[{"address":"*internal","transport":""}],"poolSize":0,"strategy":"*first"},"*localhost":{"conns":[{"address":"127.0.0.1:2012","transport":"*json"}],"poolSize":0,"strategy":"*first"}},"sags":{"enabled":false},"sars":{"enabled":false,"stats_conns":[]},"schedulers":{"cdrs_conns":[],"dynaprepaid_actionplans":[],"enabled":false,"filters":[],"stats_conns":[],"thresholds_conns":[]},"sentrypeer":{"Audience":"https://sentrypeer.com/api","ClientID":"","ClientSecret":"","GrantType":"client_credentials","IpUrl":"https://sentrypeer.com/api/ip-addresses","NumberUrl":"https://sentrypeer.com/api/phone-numbers","TokenURL":"https://authz.sentrypeer.com/oauth/token"},"sessions":{"alterable_fields":[],"attributes_conns":[],"backup_interval":"0","cdrs_conns":[],"channel_sync_interval":"0","chargers_conns":[],"client_protocol":2,"debit_interval":"0","default_usage":{"*any":"3h0m0s","*data":"1048576","*sms":"1","*voice":"3h0m0s"},"enabled":false,"listen_bigob":"","listen_bijson":"127.0.0.1:2014","min_dur_low_balance":"0","rals_conns":[],"replication_conns":[],"resources_conns":[],"routes_conns":[],"scheduler_conns":[],"session_indexes":[],"session_ttl":"0","stale_chan_max_extra_usage":"0","stats_conns":[],"stir":{"allowed_attest":["*any"],"default_attest":"A","payload_maxduration":"-1","privatekey_path":"","publickey_path":""},"store_session_costs":false,"terminate_attempts":5,"thresholds_conns":[]},"sip_agent":{"enabled":false,"listen":"127.0.0.1:5060","listen_net":"udp","request_processors":[],"retransmission_timer":1000000000,"sessions_conns":["*internal"],"timezone":""},"stats":{"enabled":false,"indexed_selects":true,"nested_fields":false,"opts":{"*profileIDs":[],"*profileIgnoreFilters":false},"prefix_indexed_fields":[],"store_interval":"","store_uncompressed_limit":0,"suffix_indexed_fields":[],"thresholds_conns":[]},"stor_db":{"db_host":"127.0.0.1","db_name":"cgrates","db_password":"CGRateS.org","db_port":3306,"db_type":"*mysql","db_user":"cgrates","items":{"*cdrs":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*session_costs":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*tp_account_actions":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*tp_action_plans":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*tp_action_triggers":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*tp_actions":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*tp_attributes":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*tp_chargers":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*tp_destination_rates":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*tp_destinations":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*tp_dispatcher_hosts":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*tp_dispatcher_profiles":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*tp_filters":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*tp_rates":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*tp_rating_plans":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*tp_rating_profiles":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*tp_resources":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*tp_routes":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*tp_shared_groups":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*tp_stats":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*tp_thresholds":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*tp_timings":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false},"*versions":{"limit":-1,"remote":false,"replicate":false,"static_ttl":false}},"opts":{"mongoConnScheme":"mongodb","mongoQueryTimeout":"10s","mysqlDSNParams":{},"mysqlLocation":"Local","pgSSLMode":"disable","pgSchema":"","sqlConnMaxLifetime":"0s","sqlMaxIdleConns":10,"sqlMaxOpenConns":100},"prefix_indexed_fields":[],"remote_conns":null,"replication_conns":null,"string_indexed_fields":[]},"suretax":{"bill_to_number":"","business_unit":"","client_number":"","client_tracking":"~*req.CGRID","customer_number":"~*req.Subject","include_local_cost":false,"orig_number":"~*req.Subject","p2pplus4":"","p2pzipcode":"","plus4":"","regulatory_code":"03","response_group":"03","response_type":"D4","return_file_code":"0","sales_type_code":"R","tax_exemption_code_list":"","tax_included":"0","tax_situs_rule":"04","term_number":"~*req.Destination","timezone":"UTC","trans_type_code":"010101","unit_type":"00","units":"1","url":"","validation_key":"","zipcode":""},"templates":{"*asr":[{"mandatory":true,"path":"*diamreq.Session-Id","tag":"SessionId","type":"*variable","value":"~*req.Session-Id"},{"mandatory":true,"path":"*diamreq.Origin-Host","tag":"OriginHost","type":"*variable","value":"~*req.Destination-Host"},{"mandatory":true,"path":"*diamreq.Origin-Realm","tag":"OriginRealm","type":"*variable","value":"~*req.Destination-Realm"},{"mandatory":true,"path":"*diamreq.Destination-Realm","tag":"DestinationRealm","type":"*variable","value":"~*req.Origin-Realm"},{"mandatory":true,"path":"*diamreq.Destination-Host","tag":"DestinationHost","type":"*variable","value":"~*req.Origin-Host"},{"mandatory":true,"path":"*diamreq.Auth-Application-Id","tag":"AuthApplicationId","type":"*variable","value":"~*vars.*appid"}],"*cca":[{"mandatory":true,"path":"*rep.Session-Id","tag":"SessionId","type":"*variable","value":"~*req.Session-Id"},{"path":"*rep.Result-Code","tag":"ResultCode","type":"*constant","value":"2001"},{"mandatory":true,"path":"*rep.Origin-Host","tag":"OriginHost","type":"*variable","value":"~*vars.OriginHost"},{"mandatory":true,"path":"*rep.Origin-Realm","tag":"OriginRealm","type":"*variable","value":"~*vars.OriginRealm"},{"mandatory":true,"path":"*rep.Auth-Application-Id","tag":"AuthApplicationId","type":"*variable","value":"~*vars.*appid"},{"mandatory":true,"path":"*rep.CC-Request-Type","tag":"CCRequestType","type":"*variable","value":"~*req.CC-Request-Type"},{"mandatory":true,"path":"*rep.CC-Request-Number","tag":"CCRequestNumber","type":"*variable","value":"~*req.CC-Request-Number"}],"*cdrLog":[{"mandatory":true,"path":"*cdr.ToR","tag":"ToR","type":"*variable","value":"~*req.BalanceType"},{"mandatory":true,"path":"*cdr.OriginHost","tag":"OriginHost","type":"*constant","value":"127.0.0.1"},{"mandatory":true,"path":"*cdr.RequestType","tag":"RequestType","type":"*constant","value":"*none"},{"mandatory":true,"path":"*cdr.Tenant","tag":"Tenant","type":"*variable","value":"~*req.Tenant"},{"mandatory":true,"path":"*cdr.Account","tag":"Account","type":"*variable","value":"~*req.Account"},{"mandatory":true,"path":"*cdr.Subject","tag":"Subject","type":"*variable","value":"~*req.Account"},{"mandatory":true,"path":"*cdr.Cost","tag":"Cost","type":"*variable","value":"~*req.Cost"},{"mandatory":true,"path":"*cdr.Source","tag":"Source","type":"*constant","value":"*cdrLog"},{"mandatory":true,"path":"*cdr.Usage","tag":"Usage","type":"*constant","value":"1"},{"mandatory":true,"path":"*cdr.RunID","tag":"RunID","type":"*variable","value":"~*req.ActionType"},{"mandatory":true,"path":"*cdr.SetupTime","tag":"SetupTime","type":"*constant","value":"*now"},{"mandatory":true,"path":"*cdr.AnswerTime","tag":"AnswerTime","type":"*constant","value":"*now"},{"mandatory":true,"path":"*cdr.PreRated","tag":"PreRated","type":"*constant","value":"true"}],"*coa":[{"path":"*radDAReq.User-Name","tag":"User-Name","type":"*variable","value":"~*oreq.User-Name"},{"path":"*radDAReq.NAS-IP-Address","tag":"NAS-IP-Address","type":"*variable","value":"~*oreq.NAS-IP-Address"},{"path":"*radDAReq.Acct-Session-Id","tag":"Acct-Session-Id","type":"*variable","value":"~*oreq.Acct-Session-Id"},{"path":"*radDAReq.Filter-Id","tag":"Filter-Id","type":"*variable","value":"~*req.CustomFilter"}],"*dmr":[{"path":"*radDAReq.User-Name","tag":"User-Name","type":"*variable","value":"~*oreq.User-Name"},{"path":"*radDAReq.NAS-IP-Address","tag":"NAS-IP-Address","type":"*variable","value":"~*oreq.NAS-IP-Address"},{"path":"*radDAReq.Acct-Session-Id","tag":"Acct-Session-Id","type":"*variable","value":"~*oreq.Acct-Session-Id"},{"path":"*radDAReq.Reply-Message","tag":"Reply-Message","type":"*variable","value":"~*req.DisconnectCause"}],"*err":[{"mandatory":true,"path":"*rep.Session-Id","tag":"SessionId","type":"*variable","value":"~*req.Session-Id"},{"mandatory":true,"path":"*rep.Origin-Host","tag":"OriginHost","type":"*variable","value":"~*vars.OriginHost"},{"mandatory":true,"path":"*rep.Origin-Realm","tag":"OriginRealm","type":"*variable","value":"~*vars.OriginRealm"}],"*errSip":[{"mandatory":true,"path":"*rep.Request","tag":"Request","type":"*constant","value":"SIP/2.0 500 Internal Server Error"}],"*rar":[{"mandatory":true,"path":"*diamreq.Session-Id","tag":"SessionId","type":"*variable","value":"~*req.Session-Id"},{"mandatory":true,"path":"*diamreq.Origin-Host","tag":"OriginHost","type":"*variable","value":"~*req.Destination-Host"},{"mandatory":true,"path":"*diamreq.Origin-Realm","tag":"OriginRealm","type":"*variable","value":"~*req.Destination-Realm"},{"mandatory":true,"path":"*diamreq.Destination-Realm","tag":"DestinationRealm","type":"*variable","value":"~*req.Origin-Realm"},{"mandatory":true,"path":"*diamreq.Destination-Host","tag":"DestinationHost","type":"*variable","value":"~*req.Origin-Host"},{"mandatory":true,"path":"*diamreq.Auth-Application-Id","tag":"AuthApplicationId","type":"*variable","value":"~*vars.*appid"},{"path":"*diamreq.Re-Auth-Request-Type","tag":"ReAuthRequestType","type":"*constant","value":"0"}]},"thresholds":{"enabled":false,"indexed_selects":true,"nested_fields":false,"opts":{"*profileIDs":[],"*profileIgnoreFilters":false},"prefix_indexed_fields":[],"store_interval":"","suffix_indexed_fields":[]},"tls":{"ca_certificate":"","client_certificate":"","client_key":"","server_certificate":"","server_key":"","server_name":"","server_policy":4}}`
if err != nil {
t.Fatal(err)
}
diff --git a/config/generalcfg.go b/config/generalcfg.go
index 9aa90919a..e6ae2eb54 100644
--- a/config/generalcfg.go
+++ b/config/generalcfg.go
@@ -167,7 +167,7 @@ func (gencfg *GeneralCfg) AsMapInterface() (initialMP map[string]any) {
utils.DefaultTenantCfg: gencfg.DefaultTenant,
utils.DefaultTimezoneCfg: gencfg.DefaultTimezone,
utils.DefaultCachingCfg: gencfg.DefaultCaching,
- utils.CachingDlayCfg: gencfg.CachingDelay,
+ utils.CachingDlayCfg: "0",
utils.ConnectAttemptsCfg: gencfg.ConnectAttempts,
utils.ReconnectsCfg: gencfg.Reconnects,
utils.MaxReconnectIntervalCfg: "0",
@@ -201,6 +201,9 @@ func (gencfg *GeneralCfg) AsMapInterface() (initialMP map[string]any) {
initialMP[utils.ReplyTimeoutCfg] = gencfg.ReplyTimeout.String()
}
+ if gencfg.CachingDelay != 0 {
+ initialMP[utils.CachingDlayCfg] = gencfg.CachingDelay.String()
+ }
return
}
diff --git a/config/generalcfg_test.go b/config/generalcfg_test.go
index e3d0e96fc..aa2438601 100644
--- a/config/generalcfg_test.go
+++ b/config/generalcfg_test.go
@@ -165,7 +165,7 @@ func TestGeneralCfgAsMapInterface(t *testing.T) {
utils.DefaultTenantCfg: "cgrates.org",
utils.DefaultTimezoneCfg: "Local",
utils.DefaultCachingCfg: "*reload",
- utils.CachingDlayCfg: 0 * time.Second,
+ utils.CachingDlayCfg: "0",
utils.ConnectAttemptsCfg: 5,
utils.ReconnectsCfg: -1,
utils.MaxReconnectIntervalCfg: "1s",
@@ -210,7 +210,7 @@ func TestGeneralCfgAsMapInterface1(t *testing.T) {
utils.DefaultTenantCfg: "cgrates.org",
utils.DefaultTimezoneCfg: "Local",
utils.DefaultCachingCfg: "*reload",
- utils.CachingDlayCfg: 0 * time.Second,
+ utils.CachingDlayCfg: "0",
utils.ConnectAttemptsCfg: 5,
utils.ReconnectsCfg: -1,
utils.MaxReconnectIntervalCfg: "0",
diff --git a/config/sessionscfg_test.go b/config/sessionscfg_test.go
index b1264ae0d..0229d4796 100644
--- a/config/sessionscfg_test.go
+++ b/config/sessionscfg_test.go
@@ -369,6 +369,7 @@ func TestSessionSCfgAsMapInterfaceCase1(t *testing.T) {
utils.TerminateAttemptsCfg: 5,
utils.MinDurLowBalanceCfg: "0",
utils.AlterableFieldsCfg: []string{},
+ utils.BackupIntervalCfg: "0",
utils.STIRCfg: map[string]any{
utils.AllowedAtestCfg: []string{"*any"},
utils.PayloadMaxdurationCfg: "-1",
@@ -444,6 +445,7 @@ func TestSessionSCfgAsMapInterfaceCase2(t *testing.T) {
utils.StaleChanMaxExtraUsageCfg: "0",
utils.TerminateAttemptsCfg: 10,
utils.AlterableFieldsCfg: []string{},
+ utils.BackupIntervalCfg: "0",
utils.STIRCfg: map[string]any{
utils.AllowedAtestCfg: []string{"any1", "any2"},
utils.PayloadMaxdurationCfg: "1s",
diff --git a/general_tests/accounts_it_test.go b/general_tests/accounts_it_test.go
index bb3ab168c..f5242354a 100644
--- a/general_tests/accounts_it_test.go
+++ b/general_tests/accounts_it_test.go
@@ -287,7 +287,7 @@ func testV1AccSendToThreshold(t *testing.T) {
}
// give time to threshold to made the change
- time.Sleep(10 * time.Millisecond)
+ time.Sleep(100 * time.Millisecond)
//verify the account
var acnt *engine.Account
attrAcc := &utils.AttrGetAccount{
diff --git a/general_tests/balance_it_test.go b/general_tests/balance_it_test.go
index 662f917f4..4e7c87217 100644
--- a/general_tests/balance_it_test.go
+++ b/general_tests/balance_it_test.go
@@ -317,7 +317,8 @@ func TestBalanceFactor(t *testing.T) {
"enabled": true,
"cdrs_conns": ["*internal"],
"chargers_conns": ["*internal"],
- "rals_conns": ["*internal"]
+ "rals_conns": ["*internal"],
+ "backup_interval": "-1"
},
"chargers": {
diff --git a/general_tests/session_bkup_interval_it_test.go b/general_tests/session_bkup_interval_it_test.go
new file mode 100644
index 000000000..83d6041ba
--- /dev/null
+++ b/general_tests/session_bkup_interval_it_test.go
@@ -0,0 +1,352 @@
+//go:build integration
+// +build integration
+
+/*
+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 general_tests
+
+import (
+ "fmt"
+ "path"
+ "testing"
+ "time"
+
+ "github.com/cgrates/birpc"
+ "github.com/cgrates/birpc/context"
+ "github.com/cgrates/cgrates/config"
+ "github.com/cgrates/cgrates/engine"
+ "github.com/cgrates/cgrates/sessions"
+ "github.com/cgrates/cgrates/utils"
+)
+
+var (
+ sBkupCfgPath string
+ sBkupCfgDIR string
+ sBkupCfg *config.CGRConfig
+ sBkupRPC *birpc.Client
+ dDB engine.DataDB
+
+ SessionsBkupIntrvlTests = []func(t *testing.T){
+ testSessionSBkupIntrvlInitCfg,
+ testSessionSBkupIntrvlResetDB,
+ testSessionSBkupIntrvlStartEngine,
+ testSessionSBkupIntrvlApierRpcConn,
+ testSessionSBkupIntrvlLoadTP,
+ testSessionSBkupIntrvlInitiate,
+ testSessionSBkupIntrvlConcurrentAPIWithInterval,
+ testSessionSBkupIntrvlGetBackedupSessions1,
+ testSessionSBkupIntrvlStopCgrEngine,
+
+ testSessionSBkupIntrvlStartEngine,
+ testSessionSBkupIntrvlApierRpcConn,
+ testSessionSBkupIntrvlGetActiveSessionsTerminate,
+ testSessionSBkupIntrvlGetBackedupSessions2,
+ testSessionSBkupIntrvlStopCgrEngine,
+
+ testSessionSBkupIntrvlStartEngine,
+ testSessionSBkupIntrvlApierRpcConn,
+ testSessionSBkupIntrvlGetActiveSessions0,
+ testSessionSBkupIntrvlStopCgrEngine,
+ }
+)
+
+func TestSessionsBkupIntrvl(t *testing.T) {
+ switch *utils.DBType {
+ case utils.MetaInternal:
+ t.SkipNow()
+ case utils.MetaMySQL:
+ sBkupCfgDIR = "sessions_backup_interval_mysql"
+ case utils.MetaMongo:
+ sBkupCfgDIR = "sessions_backup_interval_mongo"
+ case utils.MetaPostgres:
+ sBkupCfgDIR = "sessions_backup_interval_postgres"
+ default:
+ t.Fatal("Unknown Database type")
+ }
+ for _, stest := range SessionsBkupIntrvlTests {
+ t.Run(*utils.DBType, stest)
+ }
+}
+
+func testSessionSBkupIntrvlInitCfg(t *testing.T) {
+ sBkupCfgPath = path.Join(*utils.DataDir, "conf", "samples", sBkupCfgDIR)
+ if sBkupCfg, err = config.NewCGRConfigFromPath(sBkupCfgPath); err != nil {
+ t.Fatal(err)
+ }
+}
+
+// Remove data in both rating and accounting db
+func testSessionSBkupIntrvlResetDB(t *testing.T) {
+ if err := engine.InitDataDb(sBkupCfg); err != nil {
+ t.Fatal(err)
+ }
+ if err := engine.InitStorDb(sBkupCfg); err != nil {
+ t.Fatal(err)
+ }
+}
+
+// Start CGR Engine
+func testSessionSBkupIntrvlStartEngine(t *testing.T) {
+ if _, err := engine.StartEngine(sBkupCfgPath, *utils.WaitRater); err != nil {
+ t.Fatal(err)
+ }
+}
+
+// Connect rpc client to rater
+func testSessionSBkupIntrvlApierRpcConn(t *testing.T) {
+ if sBkupRPC, err = newRPCClient(sBkupCfg.ListenCfg()); err != nil {
+ t.Fatal(err)
+ }
+}
+
+// Load the tariff plan, creating accounts and their balances
+func testSessionSBkupIntrvlLoadTP(t *testing.T) {
+ tpFiles := map[string]string{
+ utils.AccountActionsCsv: `#Tenant,Account,ActionPlanId,ActionTriggersId,AllowNegative,Disabled
+cgrates.org,1001,AP_PACKAGE_10,,,
+cgrates.org,1002,AP_PACKAGE_10,,,`,
+ utils.ActionPlansCsv: `#Id,ActionsId,TimingId,Weight
+AP_PACKAGE_10,ACT_TOPUP_RST_10,*asap,10`,
+ utils.ActionsCsv: `#ActionsId[0],Action[1],ExtraParameters[2],Filter[3],BalanceId[4],BalanceType[5],Categories[6],DestinationIds[7],RatingSubject[8],SharedGroup[9],ExpiryTime[10],TimingIds[11],Units[12],BalanceWeight[13],BalanceBlocker[14],BalanceDisabled[15],Weight[16]
+ACT_TOPUP_RST_10,*topup_reset,,,test,*monetary,,*any,,,*unlimited,,100000000000000,10,false,false,10`,
+ utils.ChargersCsv: `#Tenant,ID,FilterIDs,ActivationInterval,RunID,AttributeIDs,Weight
+cgrates.org,DEFAULT,,,*default,*none,0`,
+ utils.DestinationRatesCsv: `#Id,DestinationId,RatesTag,RoundingMethod,RoundingDecimals,MaxCost,MaxCostStrategy
+DR_ANY_20CNT,*any,RT_20CNT,*up,4,0,`,
+ utils.RatesCsv: `#Id,ConnectFee,Rate,RateUnit,RateIncrement,GroupIntervalStart
+RT_20CNT,0,1,1s,1s,0s`,
+ utils.RatingPlansCsv: `#Id,DestinationRatesId,TimingTag,Weight
+RP_ANY,DR_ANY_20CNT,*any,10`,
+ utils.RatingProfilesCsv: `#Tenant,Category,Subject,ActivationTime,RatingPlanId,RatesFallbackSubject
+cgrates.org,call,*any,2014-01-14T00:00:00Z,RP_ANY,`,
+ }
+
+ loadCSVs(t, sBkupRPC, "", t.TempDir(), tpFiles)
+
+ time.Sleep(time.Duration(*utils.WaitRater) * time.Millisecond)
+}
+
+func testSessionSBkupIntrvlInitiate(t *testing.T) {
+ var aSessions []*sessions.ExternalSession
+ if err := sBkupRPC.Call(context.Background(), utils.SessionSv1GetActiveSessions,
+ new(utils.SessionFilter), &aSessions); err == nil || err.Error() != utils.ErrNotFound.Error() {
+ t.Error(err)
+ }
+ if err := sBkupRPC.Call(context.Background(), utils.SessionSv1GetPassiveSessions,
+ new(utils.SessionFilter), &aSessions); err == nil || err.Error() != utils.ErrNotFound.Error() {
+ t.Error(err)
+ }
+
+ for i := 1; i <= 500; i++ {
+ strI := fmt.Sprint(i)
+ usage := time.Duration(i) * time.Second
+ argsInit := &sessions.V1InitSessionArgs{
+ InitSession: true,
+ CGREvent: &utils.CGREvent{
+ Tenant: "cgrates.org",
+ ID: "Test_" + strI,
+ Event: map[string]any{
+ utils.EventName: "EVENT_" + strI,
+ utils.Tenant: "cgrates.org",
+ utils.OriginID: strI,
+ utils.ToR: utils.MetaVoice,
+ utils.RequestType: utils.MetaPrepaid,
+ utils.AccountField: "1001",
+ utils.Subject: "1001",
+ utils.Destination: "1002",
+ utils.Category: "call",
+ utils.SetupTime: time.Date(2024, time.March, 7, 16, 60, 0, 0, time.UTC),
+ utils.AnswerTime: time.Date(2024, time.March, 7, 16, 60, 10, 0, time.UTC),
+ utils.Usage: usage,
+ },
+ },
+ }
+
+ var initRpl sessions.V1InitSessionReply
+ if err := sBkupRPC.Call(context.Background(), utils.SessionSv1InitiateSession,
+ argsInit, &initRpl); err != nil {
+ t.Error(err)
+ }
+ if initRpl.MaxUsage == nil || *initRpl.MaxUsage != usage {
+ t.Errorf("i <%v> Expecting : %+v, received: %+v", i, usage, initRpl.MaxUsage)
+ }
+ }
+
+ if err := sBkupRPC.Call(context.Background(), utils.SessionSv1GetActiveSessions,
+ new(utils.SessionFilter), &aSessions); err != nil {
+ t.Error(err)
+ } else if len(aSessions) != 500 {
+ t.Errorf("Unexpected number of sessions received: <%+v>\n%+v", len(aSessions), utils.ToIJSON(aSessions))
+ }
+ for _, session := range aSessions {
+ found := false
+ for i := 1; i <= 500; i++ {
+ strI := fmt.Sprint(i)
+ if session.OriginID == strI && session.Usage == time.Duration(i)*time.Second && session.Source == "SessionS_EVENT_"+strI {
+ found = true
+ break
+ }
+ }
+ if !found {
+ t.Errorf("Session not found: %+v", session)
+ }
+ }
+}
+
+// try to reach concurrency by calling backup API multiple times while "backup_interval" runs in background
+func testSessionSBkupIntrvlConcurrentAPIWithInterval(t *testing.T) {
+ for i := 0; i <= 1000; i++ {
+ var sessionsBackedup int
+ if err := sBkupRPC.Call(context.Background(), utils.SessionSv1BackupActiveSessions,
+ utils.EmptyString, &sessionsBackedup); err != nil {
+ t.Fatal(err)
+ } else if sessionsBackedup != 500 {
+ t.Errorf("Expected 500 backedup sessions. Backed up: %+v", sessionsBackedup)
+ }
+ }
+}
+
+func testSessionSBkupIntrvlGetBackedupSessions1(t *testing.T) {
+
+ if *utils.DBType == utils.MetaMySQL || *utils.DBType == utils.MetaPostgres {
+ dDB, err = engine.NewRedisStorage(
+ fmt.Sprintf("%s:%s", sBkupCfg.DataDbCfg().Host, sBkupCfg.DataDbCfg().Port),
+ 10, sBkupCfg.DataDbCfg().User, sBkupCfg.DataDbCfg().Password, sBkupCfg.GeneralCfg().DBDataEncoding,
+ 10, 20, "", false, 5*time.Second, 0, 0, 0, 0, false, utils.EmptyString, utils.EmptyString, utils.EmptyString)
+ if err != nil {
+ t.Fatal("Could not connect to Redis", err.Error())
+ }
+ }
+ if *utils.DBType == utils.MetaMongo {
+ dDB, err = engine.NewMongoStorage("mongodb", sBkupCfg.DataDbCfg().Host,
+ sBkupCfg.DataDbCfg().Port, sBkupCfg.DataDbCfg().Name,
+ sBkupCfg.DataDbCfg().User, sBkupCfg.DataDbCfg().Password,
+ sBkupCfg.GeneralCfg().DBDataEncoding,
+ utils.StorDB, nil, 10*time.Second)
+ if err != nil {
+ t.Fatal(err)
+ }
+ }
+
+ // wait for all sessions to be backedup, 2 intervals to make sure all sessions had time to be stored
+ time.Sleep(1000 * time.Millisecond)
+ storedSessions, err := dDB.GetSessionsBackupDrv(sBkupCfg.GeneralCfg().NodeID,
+ sBkupCfg.GeneralCfg().DefaultTenant)
+ if err != nil {
+ t.Error(err)
+ }
+
+ if len(storedSessions) != 500 {
+ t.Fatalf("Expected 500 sessions stored, received %v", len(storedSessions))
+ }
+ for _, oneSess := range storedSessions {
+ var found bool
+ for i := 1; i <= 500; i++ {
+ strI := fmt.Sprint(i)
+ if oneSess.ResourceID == strI && oneSess.SRuns[0].TotalUsage == time.Duration(i)*time.Second {
+ found = true
+ break
+ }
+ }
+ if !found {
+ for i := range oneSess.SRuns {
+ t.Errorf("Session not found: <%+v>, SRun<%+v>", oneSess, oneSess.SRuns[i])
+ }
+ }
+ }
+}
+
+func testSessionSBkupIntrvlGetActiveSessionsTerminate(t *testing.T) {
+ var aSessions []*sessions.ExternalSession
+ if err := sBkupRPC.Call(context.Background(), utils.SessionSv1GetActiveSessions,
+ new(utils.SessionFilter), &aSessions); err != nil {
+ t.Error(err)
+ } else if len(aSessions) != 500 {
+ t.Errorf("Unexpected number of sessions received: <%+v>\n%+v", len(aSessions), utils.ToIJSON(aSessions))
+ }
+ for _, session := range aSessions {
+ found := false
+ for i := 1; i <= 500; i++ {
+ strI := fmt.Sprint(i)
+ if session.OriginID == strI && session.Usage == time.Duration(i)*time.Second && session.Source == "SessionS_EVENT_"+strI {
+ found = true
+ break
+ }
+ }
+ if !found {
+ t.Errorf("Session not found: %+v", session)
+ }
+ }
+
+ var replyTerminate string
+ for i := 1; i <= 500; i++ {
+ strI := fmt.Sprint(i)
+ if err := sBkupRPC.Call(context.Background(), utils.SessionSv1TerminateSession,
+ &sessions.V1TerminateSessionArgs{
+ TerminateSession: true,
+ CGREvent: &utils.CGREvent{
+ Tenant: "cgrates.org",
+ ID: "Test_" + strI,
+ Event: map[string]any{
+ utils.EventName: "EVENT_" + strI,
+ utils.Tenant: "cgrates.org",
+ utils.OriginID: strI,
+ utils.ToR: utils.MetaVoice,
+ utils.RequestType: utils.MetaPrepaid,
+ utils.AccountField: "1001",
+ utils.Subject: "1001",
+ utils.Destination: "1002",
+ utils.Category: "call",
+ utils.SetupTime: time.Date(2024, time.March, 7, 16, 60, 3, 0, time.UTC),
+ utils.AnswerTime: time.Date(2024, time.March, 7, 16, 60, 13, 0, time.UTC),
+ utils.Usage: time.Duration(2 * time.Second),
+ },
+ },
+ }, &replyTerminate); err != nil {
+ t.Fatal(err)
+ } else if replyTerminate != utils.OK {
+ t.Errorf("Expected reply , received <%+v>", replyTerminate)
+ }
+ }
+ time.Sleep(1 * time.Second) // Wait for 2 500ms intervals so we are sure it removed all terminated sessions from dataDB
+}
+func testSessionSBkupIntrvlGetBackedupSessions2(t *testing.T) {
+ storedSessions, err := dDB.GetSessionsBackupDrv(sBkupCfg.GeneralCfg().NodeID,
+ sBkupCfg.GeneralCfg().DefaultTenant)
+ if err != utils.ErrNoBackupFound {
+ t.Error(err)
+ }
+ if len(storedSessions) != 0 { // Sessions terminated should instantly be removed from the backup
+ t.Errorf("Expected 0 sessions in backup, received %v", len(storedSessions))
+ }
+}
+
+func testSessionSBkupIntrvlGetActiveSessions0(t *testing.T) {
+ var aSessions []*sessions.ExternalSession
+ if err := sBkupRPC.Call(context.Background(), utils.SessionSv1GetActiveSessions,
+ new(utils.SessionFilter), &aSessions); err == nil || err.Error() != utils.ErrNotFound.Error() {
+ t.Error(err)
+ }
+}
+
+func testSessionSBkupIntrvlStopCgrEngine(t *testing.T) {
+ if err := engine.KillEngine(1000); err != nil {
+ t.Error(err)
+ }
+}
diff --git a/services/datadb_it_test.go b/services/datadb_it_test.go
index d7c8174fa..a2416a2fb 100644
--- a/services/datadb_it_test.go
+++ b/services/datadb_it_test.go
@@ -130,6 +130,7 @@ func TestDataDBReload(t *testing.T) {
utils.MetaChargerProfiles: {Limit: -1},
utils.MetaDispatcherProfiles: {Limit: -1},
utils.MetaLoadIDs: {Limit: -1},
+ utils.MetaSessionsBackup: {Limit: -1},
utils.CacheVersions: {Limit: -1},
utils.CacheResourceFilterIndexes: {Limit: -1},
diff --git a/services/ers_it_test.go b/services/ers_it_test.go
index 23fa03529..76e852eb1 100644
--- a/services/ers_it_test.go
+++ b/services/ers_it_test.go
@@ -90,6 +90,7 @@ func TestEventReaderSReload(t *testing.T) {
}
time.Sleep(10 * time.Millisecond)
runtime.Gosched()
+ time.Sleep(100 * time.Millisecond)
if !erS.IsRunning() {
t.Fatalf("Expected service to be running")
}
diff --git a/services/sessions_it_test.go b/services/sessions_it_test.go
index 664ae6866..1739c3452 100644
--- a/services/sessions_it_test.go
+++ b/services/sessions_it_test.go
@@ -102,7 +102,11 @@ func TestSessionSReload1(t *testing.T) {
utils.ConcatenatedKey(utils.MetaInternal, utils.MetaChargers): clientConect,
})
anz := NewAnalyzerService(cfg, server, filterSChan, shdChan, make(chan birpc.ClientConnector, 1), srvDep)
- srv := NewSessionService(cfg, new(DataDBService), server, make(chan birpc.ClientConnector, 1), shdChan, conMng, anz, srvDep)
+ dmService := NewDataDBService(cfg, conMng, srvDep)
+ if err := dmService.Start(); err != nil {
+ t.Fatal(err)
+ }
+ srv := NewSessionService(cfg, dmService, server, make(chan birpc.ClientConnector, 1), shdChan, conMng, anz, srvDep)
err := srv.Start()
if err != nil {
t.Fatal(err)
@@ -133,9 +137,8 @@ func TestSessionSReload1(t *testing.T) {
rply := new(sessions.V1InitSessionReply)
srv.(*SessionService).sm.BiRPCv1InitiateSession(context.Background(), args, rply)
- err = srv.Shutdown()
- if err == nil || err != utils.ErrPartiallyExecuted {
- t.Fatalf("\nExpecting <%+v>,\n Received <%+v>", utils.ErrPartiallyExecuted, err)
+ if err = srv.Shutdown(); err != nil {
+ t.Error(err)
}
}
@@ -252,9 +255,12 @@ func TestSessionSReload3(t *testing.T) {
if !srv.IsRunning() {
t.Fatalf("\nExpecting service to be running")
}
+ go func() {
+ time.Sleep(10 * time.Millisecond)
+ server.StopBiRPC()
+ }()
err2 := srv.(*SessionService).start()
if err2 != nil {
t.Fatalf("\nExpected <%+v>, \nReceived <%+v>", nil, err2)
}
-
}
diff --git a/sessions/sessions_bkup_it_test.go b/sessions/sessions_bkup_it_test.go
new file mode 100644
index 000000000..24791e46a
--- /dev/null
+++ b/sessions/sessions_bkup_it_test.go
@@ -0,0 +1,627 @@
+//go:build integration
+// +build integration
+
+/*
+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 sessions
+
+import (
+ "fmt"
+ "path"
+ "testing"
+ "time"
+
+ "github.com/cgrates/birpc"
+ "github.com/cgrates/birpc/context"
+ "github.com/cgrates/cgrates/config"
+ "github.com/cgrates/cgrates/engine"
+ "github.com/cgrates/cgrates/utils"
+)
+
+var (
+ sBkupCfgPath string
+ sBkupCfgDIR string
+ sBkupCfg *config.CGRConfig
+ sBkupRPC *birpc.Client
+ dataDB engine.DataDB
+ updatedAt time.Time
+
+ SessionsBkupTests = []func(t *testing.T){
+ testSessionSBkupInitCfg,
+ testSessionSBkupResetDB,
+ testSessionSBkupStartEngine,
+ testSessionSBkupApierRpcConn,
+ testSessionSBkupTPFromFolder,
+ testSessionSBkupInitiate,
+ testSessionSBkupStopCgrEngine,
+
+ testSessionSBkupStartEngine,
+ testSessionSBkupApierRpcConn,
+ testSessionSBkupCheckRestored1,
+ testSessionSBkupTerminate1,
+ testSessionSBkupStopCgrEngine,
+
+ testSessionSBkupStartEngine,
+ testSessionSBkupApierRpcConn,
+ testSessionSBkupCheckRestored2,
+ testSessionSBkupTerminate2,
+ testSessionSBkupStopCgrEngine,
+
+ testSessionSBkupStartEngine,
+ testSessionSBkupApierRpcConn,
+ testSessionSBkupCheckRestored3,
+ testSessionSBkupStopCgrEngine,
+
+ testSessionSBkupStartEngine,
+ testSessionSBkupApierRpcConn,
+ testSessionSBkupCallBackup1,
+ testSessionSBkupInitiate,
+ testSessionSBkupCallBackup2,
+ testSessionSBkupGetBackedupSessions,
+ testSessionSBkupUpdateTerminate,
+ testSessionSBkupCallBackup3,
+ testSessionSBkupCheckUpdatedAt,
+ testSessionSBkupStopCgrEngine,
+
+ testSessionSBkupStartEngine,
+ testSessionSBkupApierRpcConn,
+ testSessionSBkupCheckUpdatedNotExpired,
+ testSessionSBkupStopCgrEngine,
+
+ testSessionSBkupStartEngine,
+ testSessionSBkupApierRpcConn,
+ testSessionSBkupCheckUpdatedExpired,
+ testSessionSBkupStopCgrEngine,
+ }
+)
+
+func TestSessionsBkup(t *testing.T) {
+ switch *utils.DBType {
+ case utils.MetaInternal:
+ t.SkipNow()
+ case utils.MetaMySQL:
+ sBkupCfgDIR = "sessions_backup_mysql"
+ case utils.MetaMongo:
+ sBkupCfgDIR = "sessions_backup_mongo"
+ case utils.MetaPostgres:
+ sBkupCfgDIR = "sessions_backup_postgres"
+ default:
+ t.Fatal("Unknown Database type")
+ }
+ for _, stest := range SessionsBkupTests {
+ t.Run(*utils.DBType, stest)
+ }
+}
+
+func testSessionSBkupInitCfg(t *testing.T) {
+ sBkupCfgPath = path.Join(*utils.DataDir, "conf", "samples", sBkupCfgDIR)
+ if sBkupCfg, err = config.NewCGRConfigFromPath(sBkupCfgPath); err != nil {
+ t.Fatal(err)
+ }
+}
+
+// Remove data in both rating and accounting db
+func testSessionSBkupResetDB(t *testing.T) {
+ if err := engine.InitDataDb(sBkupCfg); err != nil {
+ t.Fatal(err)
+ }
+ if err := engine.InitStorDb(sBkupCfg); err != nil {
+ t.Fatal(err)
+ }
+}
+
+// Start CGR Engine
+func testSessionSBkupStartEngine(t *testing.T) {
+ if _, err := engine.StartEngine(sBkupCfgPath, *utils.WaitRater); err != nil {
+ t.Fatal(err)
+ }
+}
+
+// Connect rpc client to rater
+func testSessionSBkupApierRpcConn(t *testing.T) {
+ if sBkupRPC, err = newRPCClient(sBkupCfg.ListenCfg()); err != nil {
+ t.Fatal(err)
+ }
+}
+
+// Load the tariff plan, creating accounts and their balances
+func testSessionSBkupTPFromFolder(t *testing.T) {
+ attrs := &utils.AttrLoadTpFromFolder{FolderPath: path.Join(*utils.DataDir, "tariffplans", "oldtutorial")}
+ var loadInst utils.LoadInstance
+ if err := sBkupRPC.Call(context.Background(), utils.APIerSv2LoadTariffPlanFromFolder, attrs, &loadInst); err != nil {
+ t.Error(err)
+ }
+ time.Sleep(time.Duration(*utils.WaitRater) * time.Millisecond) // Give time for scheduler to execute topups
+}
+
+func testSessionSBkupInitiate(t *testing.T) {
+ var aSessions []*ExternalSession
+ if err := sBkupRPC.Call(context.Background(), utils.SessionSv1GetActiveSessions,
+ new(utils.SessionFilter), &aSessions); err == nil || err.Error() != utils.ErrNotFound.Error() {
+ t.Error(err)
+ }
+ if err := sBkupRPC.Call(context.Background(), utils.SessionSv1GetPassiveSessions,
+ new(utils.SessionFilter), &aSessions); err == nil || err.Error() != utils.ErrNotFound.Error() {
+ t.Error(err)
+ }
+
+ usage := time.Duration(90 * time.Second)
+ argsInit := &V1InitSessionArgs{
+ InitSession: true,
+ CGREvent: &utils.CGREvent{
+ Tenant: "cgrates.org",
+ ID: "TestBkupSessionExpiresAfter3s",
+ Event: map[string]any{
+ utils.EventName: "TEST_EVENT1",
+ utils.Tenant: "cgrates.org",
+ utils.OriginID: "123450",
+ utils.ToR: utils.MetaVoice,
+ utils.RequestType: utils.MetaPrepaid,
+ utils.AccountField: "1001",
+ utils.Subject: "1001",
+ utils.Destination: "1004",
+ utils.Category: "call",
+ utils.SetupTime: time.Date(2024, time.March, 7, 16, 60, 0, 0, time.UTC),
+ utils.AnswerTime: time.Date(2024, time.March, 7, 16, 60, 10, 0, time.UTC),
+ utils.Usage: usage,
+ },
+ },
+ }
+
+ var initRpl V1InitSessionReply
+ if err := sBkupRPC.Call(context.Background(), utils.SessionSv1InitiateSession,
+ argsInit, &initRpl); err != nil {
+ t.Error(err)
+ }
+ //compare the value
+ if initRpl.MaxUsage == nil || *initRpl.MaxUsage != usage {
+ t.Errorf("Expecting : %+v, received: %+v", usage, initRpl.MaxUsage)
+ }
+ time.Sleep(time.Duration(*utils.WaitRater) * time.Millisecond) // Wait for the sessions to be populated
+ // Delay further 4 seconds to make the session unrestorable (session expiries in 4s in configs)
+ time.Sleep(4 * time.Second)
+
+ //check if the session was createad as active session
+ if err := sBkupRPC.Call(context.Background(), utils.SessionSv1GetActiveSessions,
+ new(utils.SessionFilter), &aSessions); err != nil {
+ t.Error(err)
+ } else if len(aSessions) != 1 {
+ t.Errorf("Unexpected number of sessions received: %+v", utils.ToIJSON(aSessions))
+ } else if aSessions[0].Usage != usage {
+ t.Errorf("Expecting : %+v, received: %+v", usage, aSessions[0].Usage)
+ }
+
+ usage = time.Duration(120 * time.Second)
+ argsInit = &V1InitSessionArgs{
+ InitSession: true,
+ CGREvent: &utils.CGREvent{
+ Tenant: "cgrates.org",
+ ID: "TestBkupSession2",
+ Event: map[string]any{
+ utils.EventName: "TEST_EVENT2",
+ utils.Tenant: "cgrates.org",
+ utils.OriginID: "123452",
+ utils.ToR: utils.MetaVoice,
+ utils.RequestType: utils.MetaPrepaid,
+ utils.AccountField: "1001",
+ utils.Subject: "1001",
+ utils.Destination: "1004",
+ utils.Category: "call",
+ utils.SetupTime: time.Date(2024, time.March, 7, 16, 60, 2, 0, time.UTC),
+ utils.AnswerTime: time.Date(2024, time.March, 7, 16, 60, 12, 0, time.UTC),
+ utils.Usage: usage,
+ },
+ },
+ }
+
+ if err := sBkupRPC.Call(context.Background(), utils.SessionSv1InitiateSession,
+ argsInit, &initRpl); err != nil {
+ t.Error(err)
+ }
+ //compare the value
+ if initRpl.MaxUsage == nil || *initRpl.MaxUsage != usage {
+ t.Errorf("Expecting : %+v, received: %+v", usage, initRpl.MaxUsage)
+ }
+ time.Sleep(time.Duration(*utils.WaitRater) * time.Millisecond) // Wait for the sessions to be populated
+
+ if err := sBkupRPC.Call(context.Background(), utils.SessionSv1GetActiveSessions,
+ new(utils.SessionFilter), &aSessions); err != nil {
+ t.Error(err)
+ } else if len(aSessions) != 2 {
+ t.Errorf("Unexpected number of sessions received: %+v", utils.ToIJSON(aSessions))
+ }
+ for _, extSess := range aSessions {
+ if extSess.OriginID == "123452" {
+ if extSess.Usage != usage {
+ t.Errorf("OriginID: <123452>, Expecting : %+v, received: %+v", usage, extSess.Usage)
+ }
+ }
+ }
+
+ usage = time.Duration(150 * time.Second)
+ argsInit = &V1InitSessionArgs{
+ InitSession: true,
+ CGREvent: &utils.CGREvent{
+ Tenant: "cgrates.org",
+ ID: "TestBkupSession1",
+ Event: map[string]any{
+ utils.EventName: "TEST_EVENT1",
+ utils.Tenant: "cgrates.org",
+ utils.OriginID: "123451",
+ utils.ToR: utils.MetaVoice,
+ utils.RequestType: utils.MetaPrepaid,
+ utils.AccountField: "1001",
+ utils.Subject: "1001",
+ utils.Destination: "1004",
+ utils.Category: "call",
+ utils.SetupTime: time.Date(2024, time.March, 7, 16, 60, 3, 0, time.UTC),
+ utils.AnswerTime: time.Date(2024, time.March, 7, 16, 60, 13, 0, time.UTC),
+ utils.Usage: usage,
+ },
+ },
+ }
+
+ if err := sBkupRPC.Call(context.Background(), utils.SessionSv1InitiateSession,
+ argsInit, &initRpl); err != nil {
+ t.Error(err)
+ }
+ //compare the value
+ if initRpl.MaxUsage == nil || *initRpl.MaxUsage != usage {
+ t.Errorf("Expecting : %+v, received: %+v", usage, initRpl.MaxUsage)
+ }
+ time.Sleep(time.Duration(*utils.WaitRater) * time.Millisecond) // Wait for the sessions to be populated
+
+ if err := sBkupRPC.Call(context.Background(), utils.SessionSv1GetActiveSessions,
+ new(utils.SessionFilter), &aSessions); err != nil {
+ t.Error(err)
+ } else if len(aSessions) != 3 {
+ t.Errorf("Unexpected number of sessions received: %+v", utils.ToIJSON(aSessions))
+ }
+ for _, extSess := range aSessions {
+ if extSess.OriginID == "123451" {
+ if extSess.Usage != usage {
+ t.Errorf("OriginID: <123451>, Expecting : %+v, received: %+v", usage, extSess.Usage)
+ }
+ }
+ }
+}
+
+func testSessionSBkupCheckRestored1(t *testing.T) {
+ var aSessions []*ExternalSession
+ usage1 := time.Duration(120 * time.Second)
+ usage2 := time.Duration(150 * time.Second)
+ //check if the sessions were restored
+ if err := sBkupRPC.Call(context.Background(), utils.SessionSv1GetActiveSessions,
+ new(utils.SessionFilter), &aSessions); err != nil {
+ t.Error(err)
+ } else if len(aSessions) != 2 {
+ t.Fatalf("Unexpected number of sessions received: %+v", utils.ToIJSON(aSessions))
+ }
+ for _, extSess := range aSessions {
+ switch {
+ case extSess.OriginID == "123451":
+ if extSess.Usage != usage2 {
+ t.Errorf("OriginID: <123451>, Expecting : %+v, received: %+v", usage2, extSess.Usage)
+ }
+ case extSess.OriginID == "123452":
+ if extSess.Usage != usage1 {
+ t.Errorf("OriginID: <123452>, Expecting : %+v, received: %+v", usage1, extSess.Usage)
+ }
+ default:
+ t.Fatalf("Unexpected OriginID <%v> present in the session", extSess.OriginID)
+ }
+ }
+}
+
+func testSessionSBkupTerminate1(t *testing.T) {
+ var replyTerminate string
+ if err := sBkupRPC.Call(context.Background(), utils.SessionSv1TerminateSession,
+ &V1TerminateSessionArgs{
+ TerminateSession: true,
+ CGREvent: &utils.CGREvent{
+ Tenant: "cgrates.org",
+ ID: "TestBkupSession1",
+ Event: map[string]any{
+ utils.EventName: "TEST_EVENT1",
+ utils.Tenant: "cgrates.org",
+ utils.OriginID: "123451",
+ utils.ToR: utils.MetaVoice,
+ utils.RequestType: utils.MetaPrepaid,
+ utils.AccountField: "1001",
+ utils.Subject: "1001",
+ utils.Destination: "1004",
+ utils.Category: "call",
+ utils.SetupTime: time.Date(2024, time.March, 7, 16, 60, 3, 0, time.UTC),
+ utils.AnswerTime: time.Date(2024, time.March, 7, 16, 60, 13, 0, time.UTC),
+ },
+ },
+ }, &replyTerminate); err != nil {
+ t.Error(err)
+ }
+ if replyTerminate != utils.OK {
+ t.Errorf("Expected reply , received <%+v>", replyTerminate)
+ }
+}
+
+func testSessionSBkupCheckRestored2(t *testing.T) {
+ var aSessions []*ExternalSession
+ usage1 := time.Duration(120 * time.Second)
+ //check if the sessions were restored
+ if err := sBkupRPC.Call(context.Background(), utils.SessionSv1GetActiveSessions,
+ new(utils.SessionFilter), &aSessions); err != nil {
+ t.Fatal(err)
+ } else if len(aSessions) != 1 {
+ t.Fatalf("Unexpected number of sessions received: %+v", utils.ToIJSON(aSessions))
+ }
+ if aSessions[0].OriginID == "123452" {
+ if aSessions[0].Usage != usage1 {
+ t.Errorf("OriginID: <123452>, Expecting : %+v, received: %+v", usage1, aSessions[0].Usage)
+ }
+ }
+}
+
+func testSessionSBkupTerminate2(t *testing.T) {
+ var replyTerminate string
+ if err := sBkupRPC.Call(context.Background(), utils.SessionSv1TerminateSession,
+ &V1TerminateSessionArgs{
+ TerminateSession: true,
+ CGREvent: &utils.CGREvent{
+ Tenant: "cgrates.org",
+ ID: "TestBkupSession2",
+ Event: map[string]any{
+ utils.EventName: "TEST_EVENT2",
+ utils.Tenant: "cgrates.org",
+ utils.OriginID: "123452",
+ utils.ToR: utils.MetaVoice,
+ utils.RequestType: utils.MetaPrepaid,
+ utils.AccountField: "1001",
+ utils.Subject: "1001",
+ utils.Destination: "1004",
+ utils.Category: "call",
+ utils.SetupTime: time.Date(2024, time.March, 7, 16, 60, 2, 0, time.UTC),
+ utils.AnswerTime: time.Date(2024, time.March, 7, 16, 60, 12, 0, time.UTC),
+ },
+ },
+ }, &replyTerminate); err != nil {
+ t.Error(err)
+ }
+ if replyTerminate != utils.OK {
+ t.Errorf("Expected reply , received <%+v>", replyTerminate)
+ }
+}
+
+func testSessionSBkupCheckRestored3(t *testing.T) {
+ var aSessions []*ExternalSession
+ if err := sBkupRPC.Call(context.Background(), utils.SessionSv1GetActiveSessions,
+ new(utils.SessionFilter), &aSessions); err == nil || err.Error() != utils.ErrNotFound.Error() {
+ t.Error(err)
+ }
+ if len(aSessions) != 0 {
+ t.Errorf("Unexpected number of sessions received: %+v", utils.ToIJSON(aSessions))
+ }
+}
+
+func testSessionSBkupCallBackup1(t *testing.T) {
+ var sessionsBackedup int
+ if err := sBkupRPC.Call(context.Background(), utils.SessionSv1BackupActiveSessions,
+ utils.EmptyString, &sessionsBackedup); err != nil {
+ t.Error(err)
+ } else if sessionsBackedup != 0 {
+ t.Errorf("Expected 0 backedup sessions. Backed up: %+v", sessionsBackedup)
+ }
+}
+
+func testSessionSBkupCallBackup2(t *testing.T) {
+ var sessionsBackedup int
+ if err := sBkupRPC.Call(context.Background(), utils.SessionSv1BackupActiveSessions,
+ utils.EmptyString, &sessionsBackedup); err != nil {
+ t.Fatal(err)
+ } else if sessionsBackedup != 3 {
+ t.Errorf("Expected 3 backedup sessions. Backed up: %+v", sessionsBackedup)
+ }
+}
+
+func testSessionSBkupGetBackedupSessions(t *testing.T) {
+
+ if *utils.DBType == utils.MetaMySQL || *utils.DBType == utils.MetaPostgres {
+ dataDB, err = engine.NewRedisStorage(
+ fmt.Sprintf("%s:%s", sBkupCfg.DataDbCfg().Host, sBkupCfg.DataDbCfg().Port),
+ 10, sBkupCfg.DataDbCfg().User, sBkupCfg.DataDbCfg().Password, sBkupCfg.GeneralCfg().DBDataEncoding,
+ 10, 20, "", false, 5*time.Second, 0, 0, 0, 0, false, utils.EmptyString, utils.EmptyString, utils.EmptyString)
+ if err != nil {
+ t.Fatal("Could not connect to Redis", err.Error())
+ }
+ }
+ if *utils.DBType == utils.MetaMongo {
+ dataDB, err = engine.NewMongoStorage("mongodb", sBkupCfg.DataDbCfg().Host,
+ sBkupCfg.DataDbCfg().Port, sBkupCfg.DataDbCfg().Name,
+ sBkupCfg.DataDbCfg().User, sBkupCfg.DataDbCfg().Password,
+ sBkupCfg.GeneralCfg().DBDataEncoding,
+ utils.StorDB, nil, 10*time.Second)
+ if err != nil {
+ t.Fatal(err)
+ }
+ }
+
+ var getBackSess []*Session
+ storedSessions, err := dataDB.GetSessionsBackupDrv(sBkupCfg.GeneralCfg().NodeID,
+ sBkupCfg.GeneralCfg().DefaultTenant)
+ if err != nil {
+ t.Error(err)
+ }
+ for _, storSess := range storedSessions {
+ sess := newSessionFromStoredSession(storSess)
+ getBackSess = append(getBackSess, sess)
+ }
+
+ if len(getBackSess) != 3 { // even though one of them expired, we are not restoring them currently so in db there should be 3 sessions stored
+ t.Fatalf("Expected 3 sessions stored, received %v", len(getBackSess))
+ }
+ for _, oneSess := range getBackSess {
+ switch {
+ case oneSess.ResourceID == "123450":
+ if oneSess.totalUsage() != time.Duration(90*time.Second) {
+ t.Errorf("Expected <%v>, received <%v>", time.Duration(90*time.Second), oneSess.totalUsage())
+ }
+ case oneSess.ResourceID == "123451":
+ if oneSess.totalUsage() != time.Duration(150*time.Second) {
+ t.Errorf("Expected <%v>, received <%v>", time.Duration(150*time.Second), oneSess.totalUsage())
+ }
+ case oneSess.ResourceID == "123452":
+ if oneSess.totalUsage() != time.Duration(120*time.Second) {
+ t.Errorf("Expected <%v>, received <%v>", time.Duration(120*time.Second), oneSess.totalUsage())
+ }
+ updatedAt = oneSess.UpdatedAt
+ }
+ }
+
+}
+
+func testSessionSBkupUpdateTerminate(t *testing.T) {
+ updatedUsage := time.Duration(200 * time.Second)
+ var upRply V1UpdateSessionReply
+ upArgs := &V1UpdateSessionArgs{
+ UpdateSession: true,
+ CGREvent: &utils.CGREvent{
+ Tenant: "cgrates.org",
+ ID: "TestBkupSession2",
+ Event: map[string]any{
+ utils.EventName: "TEST_EVENT2",
+ utils.Tenant: "cgrates.org",
+ utils.OriginID: "123452",
+ utils.ToR: utils.MetaVoice,
+ utils.RequestType: utils.MetaPrepaid,
+ utils.AccountField: "1001",
+ utils.Subject: "1001",
+ utils.Destination: "1004",
+ utils.Category: "call",
+ utils.SetupTime: time.Date(2024, time.March, 7, 16, 60, 2, 0, time.UTC),
+ utils.AnswerTime: time.Date(2024, time.March, 7, 16, 60, 12, 0, time.UTC),
+ utils.Usage: updatedUsage,
+ },
+ },
+ }
+ if err = sBkupRPC.Call(context.Background(), utils.SessionSv1UpdateSession, upArgs, &upRply); err != nil {
+ t.Error(err)
+ } else if *upRply.MaxUsage != updatedUsage {
+ t.Errorf("Expected <%+v>, Received <%+v>", updatedUsage, *upRply.MaxUsage)
+ }
+
+ args := &V1TerminateSessionArgs{
+ TerminateSession: true,
+ CGREvent: &utils.CGREvent{
+ Tenant: "cgrates.org",
+ ID: "TestBkupSession1",
+ Event: map[string]any{
+ utils.EventName: "TEST_EVENT1",
+ utils.Tenant: "cgrates.org",
+ utils.OriginID: "123451",
+ utils.ToR: utils.MetaVoice,
+ utils.RequestType: utils.MetaPrepaid,
+ utils.AccountField: "1001",
+ utils.Subject: "1001",
+ utils.Destination: "1004",
+ utils.Category: "call",
+ utils.SetupTime: time.Date(2024, time.March, 7, 16, 60, 3, 0, time.UTC),
+ utils.AnswerTime: time.Date(2024, time.March, 7, 16, 60, 13, 0, time.UTC),
+ utils.Usage: time.Duration(160 * time.Second),
+ },
+ },
+ }
+ var rply string
+ if err := sBkupRPC.Call(context.Background(), utils.SessionSv1TerminateSession,
+ args, &rply); err != nil {
+ t.Error(err)
+ }
+ if rply != utils.OK {
+ t.Errorf("Unexpected reply: %s", rply)
+ }
+}
+
+func testSessionSBkupCallBackup3(t *testing.T) {
+ var sessionsBackedup int
+ if err := sBkupRPC.Call(context.Background(), utils.SessionSv1BackupActiveSessions,
+ utils.EmptyString, &sessionsBackedup); err != nil {
+ t.Fatal(err)
+ } else if sessionsBackedup != 2 { // should've backed up 2 since we terminated one of them
+ t.Errorf("Expected 2 backedup sessions. Backed up: %+v", sessionsBackedup)
+ }
+}
+
+func testSessionSBkupCheckUpdatedAt(t *testing.T) {
+ var getBackSess []*Session
+ storedSessions, err := dataDB.GetSessionsBackupDrv(sBkupCfg.GeneralCfg().NodeID,
+ sBkupCfg.GeneralCfg().DefaultTenant)
+ if err != nil {
+ t.Error(err)
+ }
+ for _, storSess := range storedSessions {
+ sess := newSessionFromStoredSession(storSess)
+ getBackSess = append(getBackSess, sess)
+ }
+
+ if len(getBackSess) != 2 { // even though one of them expired, we are not restoring them currently so in db there should be 2 sessions stored
+ t.Fatalf("Expected 2 sessions stored, received %v", len(getBackSess))
+ }
+ for _, oneSess := range getBackSess {
+ switch {
+ case oneSess.ResourceID == "123450":
+ if oneSess.totalUsage() != time.Duration(90*time.Second) {
+ t.Errorf("Expected <%v>, received <%v>", time.Duration(90*time.Second), oneSess.totalUsage())
+ }
+ case oneSess.ResourceID == "123452":
+ if oneSess.totalUsage() != time.Duration(320*time.Second) { // usage should be updated to 320 seconds
+ t.Errorf("Expected <%v>, received <%v>", time.Duration(320*time.Second), oneSess.totalUsage())
+ }
+ if oneSess.UpdatedAt == updatedAt {
+ t.Errorf("Expected UpdatedAt field to be changed on update. Received the same time as before <%+v>", oneSess.UpdatedAt)
+ }
+ }
+ }
+}
+
+func testSessionSBkupCheckUpdatedNotExpired(t *testing.T) {
+ var aSessions []*ExternalSession
+ if err := sBkupRPC.Call(context.Background(), utils.SessionSv1GetActiveSessions,
+ new(utils.SessionFilter), &aSessions); err != nil {
+ t.Error(err)
+ } else if len(aSessions) != 1 {
+ t.Fatalf("Unexpected number of sessions received: %+v", utils.ToIJSON(aSessions))
+ }
+ if aSessions[0].OriginID != "123452" {
+ t.Errorf("Expected backed up session source 123452, received <%+v>", aSessions[0].OriginID)
+ }
+ time.Sleep(4 * time.Second) // Wait for updated session to expire
+}
+
+func testSessionSBkupCheckUpdatedExpired(t *testing.T) {
+ var aSessions []*ExternalSession
+ if err := sBkupRPC.Call(context.Background(), utils.SessionSv1GetActiveSessions,
+ new(utils.SessionFilter), &aSessions); err == nil || err.Error() != utils.ErrNotFound.Error() {
+ t.Error(err)
+ } else if len(aSessions) != 0 {
+ t.Fatalf("Unexpected number of sessions received: %+v", utils.ToIJSON(aSessions))
+ }
+}
+
+func testSessionSBkupStopCgrEngine(t *testing.T) {
+ if err := engine.KillEngine(1000); err != nil {
+ t.Error(err)
+ }
+}
diff --git a/sessions/sessions_bkup_rpl_it_test.go b/sessions/sessions_bkup_rpl_it_test.go
new file mode 100644
index 000000000..a02a34b85
--- /dev/null
+++ b/sessions/sessions_bkup_rpl_it_test.go
@@ -0,0 +1,401 @@
+//go:build integration
+// +build integration
+
+/*
+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 sessions
+
+import (
+ "fmt"
+ "os/exec"
+ "path"
+ "testing"
+ "time"
+
+ "github.com/cgrates/birpc"
+ "github.com/cgrates/birpc/context"
+ "github.com/cgrates/cgrates/config"
+ "github.com/cgrates/cgrates/engine"
+ "github.com/cgrates/cgrates/utils"
+)
+
+var (
+ sBRplcEng1CfgPath, sBRplcEng2CfgPath string
+ sBRplcEng1CfgDIR, sBRplcEng2CfgDIR string
+ sBRplcEng1Cfg, sBRplcEng2Cfg *config.CGRConfig
+ sBRplcEng1RPC, sBRplcEng2RPC *birpc.Client
+ sBRplcEng1Eng, sBRplcEng2Eng *exec.Cmd
+
+ SessionsBkupRplTests = []func(t *testing.T){
+ testSessionSBkupRplcInitCfg,
+ testSessionSBkupRplcResetDB,
+ testSessionSBkupRplcStartEngineBoth,
+ testSessionSBkupRplcApierRpcConnBoth,
+ testSessionSBkupRplcTPFromFolder,
+ testSessionSBkupRplcInitiate,
+ testSessionSBkupRplcGetSessions,
+ testSessionSBkupRplcUpdate,
+ testSessionSBkupRplcStartEngine2,
+ testSessionSBkupRplcApierRpcConn2,
+ testSessionSBkupRplcGetActvSessionsFromRestored,
+ testSessionSBkupRplcTerminate,
+ testSessionSBkupRplcStopCgrEngine,
+
+ testSessionSBkupRplcStartEngine2,
+ testSessionSBkupRplcApierRpcConn2,
+ testSessionSBkupRplcGetNoActvSessionsFromRestored,
+ testSessionSBkupRplcStopCgrEngine,
+ }
+)
+
+func TestSessionSBkupRplc(t *testing.T) {
+ switch *utils.DBType {
+ case utils.MetaInternal:
+ t.SkipNow()
+ case utils.MetaMySQL:
+ sBRplcEng1CfgDIR = "sbkupreplcengine1_mysql"
+ sBRplcEng2CfgDIR = "sbkupreplcengine2_mongo"
+ case utils.MetaMongo:
+ sBRplcEng1CfgDIR = "sbkupreplcengine1_mongo"
+ sBRplcEng2CfgDIR = "sbkupreplcengine2_mysql"
+ case utils.MetaPostgres:
+ sBRplcEng1CfgDIR = "sbkupreplcengine1_postgres"
+ sBRplcEng2CfgDIR = "sbkupreplcengine2_mongo"
+ default:
+ t.Fatal("Unknown Database type")
+ }
+ if *utils.Encoding == utils.MetaGOB {
+ sBRplcEng1CfgDIR += "_gob"
+ sBRplcEng2CfgDIR += "_gob"
+ }
+ for _, stest := range SessionsBkupRplTests {
+ t.Run(*utils.DBType, stest)
+ }
+}
+
+func testSessionSBkupRplcInitCfg(t *testing.T) {
+ sBRplcEng1CfgPath = path.Join(*utils.DataDir, "conf", "samples", sBRplcEng1CfgDIR)
+ if sBRplcEng1Cfg, err = config.NewCGRConfigFromPath(sBRplcEng1CfgPath); err != nil {
+ t.Fatal(err)
+ }
+ sBRplcEng2CfgPath = path.Join(*utils.DataDir, "conf", "samples", sBRplcEng2CfgDIR)
+ if sBRplcEng2Cfg, err = config.NewCGRConfigFromPath(sBRplcEng2CfgPath); err != nil {
+ t.Fatal(err)
+ }
+}
+
+// Remove data in both rating and accounting db
+func testSessionSBkupRplcResetDB(t *testing.T) {
+ if err := engine.InitDataDb(sBRplcEng1Cfg); err != nil {
+ t.Fatal(err)
+ }
+ if err := engine.InitStorDb(sBRplcEng1Cfg); err != nil {
+ t.Fatal(err)
+ }
+ if err := engine.InitDataDb(sBRplcEng2Cfg); err != nil {
+ t.Fatal(err)
+ }
+ if err := engine.InitStorDb(sBRplcEng2Cfg); err != nil {
+ t.Fatal(err)
+ }
+}
+
+// Start CGR Engine
+func testSessionSBkupRplcStartEngineBoth(t *testing.T) {
+ if sBRplcEng2Eng, err = engine.StopStartEngine(sBRplcEng2CfgPath, *utils.WaitRater); err != nil { // Start engine2 before engine1
+ t.Fatal(err)
+ }
+ if sBRplcEng1Eng, err = engine.StartEngine(sBRplcEng1CfgPath, *utils.WaitRater); err != nil {
+ t.Fatal(err)
+ }
+}
+
+// Connect rpc client to rater
+func testSessionSBkupRplcApierRpcConnBoth(t *testing.T) {
+ if sBRplcEng1RPC, err = newRPCClient(sBRplcEng1Cfg.ListenCfg()); err != nil {
+ t.Fatal(err)
+ }
+ if sBRplcEng2RPC, err = newRPCClient(sBRplcEng2Cfg.ListenCfg()); err != nil {
+ t.Fatal(err)
+ }
+}
+
+// Load the tariff plan, creating accounts and their balances
+func testSessionSBkupRplcTPFromFolder(t *testing.T) {
+ attrs := &utils.AttrLoadTpFromFolder{FolderPath: path.Join(*utils.DataDir, "tariffplans", "oldtutorial")}
+ var loadInst utils.LoadInstance
+ if err := sBRplcEng1RPC.Call(context.Background(), utils.APIerSv2LoadTariffPlanFromFolder, attrs, &loadInst); err != nil {
+ t.Error(err)
+ }
+ time.Sleep(time.Duration(*utils.WaitRater) * time.Millisecond) // Give time for scheduler to execute topups
+ attrs = &utils.AttrLoadTpFromFolder{FolderPath: path.Join(*utils.DataDir, "tariffplans", "oldtutorial")}
+ if err := sBRplcEng2RPC.Call(context.Background(), utils.APIerSv2LoadTariffPlanFromFolder, attrs, &loadInst); err != nil {
+ t.Error(err)
+ }
+ time.Sleep(time.Duration(*utils.WaitRater) * time.Millisecond) // Give time for scheduler to execute topups
+}
+
+func testSessionSBkupRplcInitiate(t *testing.T) {
+ var aSessions []*ExternalSession
+ //make sure we don't have active sessions on engine1 and passive on engine2
+ if err := sBRplcEng1RPC.Call(context.Background(), utils.SessionSv1GetActiveSessions,
+ new(utils.SessionFilter), &aSessions); err == nil || err.Error() != utils.ErrNotFound.Error() {
+ t.Error(err)
+ }
+ if err := sBRplcEng2RPC.Call(context.Background(), utils.SessionSv1GetPassiveSessions,
+ new(utils.SessionFilter), &aSessions); err == nil || err.Error() != utils.ErrNotFound.Error() {
+ t.Error(err)
+ }
+
+ usage := time.Minute + 30*time.Second
+ argsInit := &V1InitSessionArgs{
+ InitSession: true,
+ CGREvent: &utils.CGREvent{
+ Tenant: "cgrates.org",
+ ID: "TestSessionSBkupRplcInitiate",
+ Event: map[string]any{
+ utils.EventName: "TEST_EVENT",
+ utils.Tenant: "cgrates.org",
+ utils.OriginID: "123451",
+ utils.ToR: utils.MetaVoice,
+ utils.RequestType: utils.MetaPrepaid,
+ utils.AccountField: "1001",
+ utils.Subject: "1001",
+ utils.Destination: "1004",
+ utils.Category: "call",
+ utils.SetupTime: time.Date(2018, time.January, 7, 16, 60, 0, 0, time.UTC),
+ utils.AnswerTime: time.Date(2018, time.January, 7, 16, 60, 10, 0, time.UTC),
+ utils.Usage: usage,
+ },
+ },
+ }
+
+ var initRpl V1InitSessionReply
+ if err := sBRplcEng1RPC.Call(context.Background(), utils.SessionSv1InitiateSession,
+ argsInit, &initRpl); err != nil {
+ t.Error(err)
+ }
+ //compare the value
+ if initRpl.MaxUsage == nil || *initRpl.MaxUsage != usage {
+ t.Errorf("Expecting : %+v, received: %+v", usage, initRpl.MaxUsage)
+ }
+ time.Sleep(time.Duration(*utils.WaitRater) * time.Millisecond) // Wait for the sessions to be populated
+
+ //check if the session was createad as active session on engine1
+ if err := sBRplcEng1RPC.Call(context.Background(), utils.SessionSv1GetActiveSessions,
+ utils.SessionFilter{
+ Filters: []string{
+ fmt.Sprintf("*string:~*req.%s:%s", utils.OriginID, "123451"),
+ },
+ }, &aSessions); err != nil {
+ t.Error(err)
+ } else if len(aSessions) != 1 {
+ t.Errorf("Unexpected number of sessions received: %+v", utils.ToIJSON(aSessions))
+ } else if aSessions[0].Usage != 90*time.Second {
+ t.Errorf("Expecting : %+v, received: %+v", 90*time.Second, aSessions[0].Usage)
+ }
+
+ //check if the session was created as passive session on engine2
+ var pSessions []*ExternalSession
+ if err := sBRplcEng2RPC.Call(context.Background(), utils.SessionSv1GetPassiveSessions,
+ utils.SessionFilter{
+ Filters: []string{
+ fmt.Sprintf("*string:~*req.%s:%s", utils.OriginID, "123451"),
+ },
+ }, &pSessions); err != nil {
+ t.Error(err)
+ } else if len(pSessions) != 1 {
+ t.Errorf("PassiveSessions: %+v", pSessions)
+ } else if pSessions[0].Usage != 90*time.Second {
+ t.Errorf("Expecting : %+v, received: %+v", 90*time.Second, pSessions[0].Usage)
+ }
+}
+
+func testSessionSBkupRplcGetSessions(t *testing.T) {
+ time.Sleep(501 * time.Millisecond) // make sure active sessions are backed up from "backup_interval"
+ if err := sBRplcEng1Eng.Process.Kill(); err != nil {
+ t.Errorf("Failed to kill process, error: %v", err.Error())
+ }
+ // make sure we have no active sessions on engine2
+ var aSessions []*ExternalSession
+ if err := sBRplcEng2RPC.Call(context.Background(), utils.SessionSv1GetActiveSessions,
+ new(utils.SessionFilter), &aSessions); err == nil || err.Error() != utils.ErrNotFound.Error() {
+ t.Error(err)
+ }
+ // make sure we have passive sessions on engine2
+ var pSessions []*ExternalSession
+ if err := sBRplcEng2RPC.Call(context.Background(), utils.SessionSv1GetPassiveSessions,
+ utils.SessionFilter{}, &pSessions); err != nil {
+ t.Error(err)
+ } else if len(pSessions) != 1 {
+ t.Errorf("PassiveSessions: %+v", pSessions)
+ } else if pSessions[0].Usage != 90*time.Second {
+ t.Errorf("Expecting : %+v, received: %+v", 90*time.Second, pSessions[0].Usage)
+ }
+}
+
+func testSessionSBkupRplcUpdate(t *testing.T) {
+ //update the session on engine2 so the session should became active
+ usage := time.Minute
+ argsUpdate := &V1UpdateSessionArgs{
+ UpdateSession: true,
+ CGREvent: &utils.CGREvent{
+ Tenant: "cgrates.org",
+ ID: "TestSessionSBkupRplcUpdate",
+ Event: map[string]any{
+ utils.EventName: "TEST_EVENT",
+ utils.Tenant: "cgrates.org",
+ utils.OriginID: "123451",
+ utils.ToR: utils.MetaVoice,
+ utils.RequestType: utils.MetaPrepaid,
+ utils.AccountField: "1001",
+ utils.Subject: "1001",
+ utils.Destination: "1004",
+ utils.Category: "call",
+ utils.SetupTime: time.Date(2018, time.January, 7, 16, 60, 0, 0, time.UTC),
+ utils.AnswerTime: time.Date(2018, time.January, 7, 16, 60, 10, 0, time.UTC),
+ utils.Usage: usage,
+ },
+ },
+ }
+ var updtRpl V1UpdateSessionReply
+ if err := sBRplcEng2RPC.Call(context.Background(), utils.SessionSv1UpdateSession,
+ argsUpdate, &updtRpl); err != nil {
+ t.Error(err)
+ }
+ if updtRpl.MaxUsage == nil || *updtRpl.MaxUsage != usage {
+ t.Errorf("Expecting : %+v, received: %+v", usage, updtRpl.MaxUsage)
+ }
+ time.Sleep(time.Duration(*utils.WaitRater) * time.Millisecond) // Wait for the sessions to be populated
+
+ var aSessions []*ExternalSession
+ if err := sBRplcEng2RPC.Call(context.Background(), utils.SessionSv1GetActiveSessions,
+ utils.SessionFilter{
+ Filters: []string{
+ fmt.Sprintf("*string:~*req.%s:%s", utils.OriginID, "123451"),
+ },
+ }, &aSessions); err != nil {
+ t.Error(err)
+ } else if len(aSessions) != 1 {
+ t.Errorf("Unexpected number of sessions received: %+v", aSessions)
+ } else if aSessions[0].Usage != 150*time.Second {
+ t.Errorf("Expecting : %+v, received: %+v", 150*time.Second, aSessions[0].Usage)
+ }
+
+ var pSessions []*ExternalSession
+ // Make sure we don't have passive session on active host
+ if err := sBRplcEng2RPC.Call(context.Background(), utils.SessionSv1GetPassiveSessions, new(utils.SessionFilter),
+ &pSessions); err == nil || err.Error() != utils.ErrNotFound.Error() {
+ t.Error(err)
+ }
+ time.Sleep(501 * time.Millisecond) // make sure active sessions are backed up from "backup_interval"
+ if err := sBRplcEng2Eng.Process.Kill(); err != nil {
+ t.Errorf("Failed to kill process, error: %v", err.Error())
+ }
+}
+
+func testSessionSBkupRplcStartEngine2(t *testing.T) {
+ if sBRplcEng2Eng, err = engine.StopStartEngine(sBRplcEng2CfgPath, *utils.WaitRater); err != nil {
+ t.Fatal(err)
+ }
+}
+
+func testSessionSBkupRplcApierRpcConn2(t *testing.T) {
+ if sBRplcEng2RPC, err = newRPCClient(sBRplcEng2Cfg.ListenCfg()); err != nil {
+ t.Fatal(err)
+ }
+}
+
+func testSessionSBkupRplcGetActvSessionsFromRestored(t *testing.T) {
+ var aSessions []*ExternalSession
+ if err := sBRplcEng2RPC.Call(context.Background(), utils.SessionSv1GetActiveSessions,
+ utils.SessionFilter{}, &aSessions); err != nil {
+ t.Error(err)
+ } else if len(aSessions) != 1 {
+ t.Errorf("Unexpected number of sessions received: %+v", utils.ToIJSON(aSessions))
+ } else if aSessions[0].Usage != 150*time.Second {
+ t.Errorf("Expecting : %+v, received: %+v", 150*time.Second, aSessions[0].Usage)
+ }
+
+ var pSessions []*ExternalSession
+ if err := sBRplcEng2RPC.Call(context.Background(), utils.SessionSv1GetPassiveSessions,
+ new(utils.SessionFilter), &pSessions); err == nil || err.Error() != utils.ErrNotFound.Error() {
+ t.Error(err)
+ }
+}
+
+func testSessionSBkupRplcTerminate(t *testing.T) {
+ args := &V1TerminateSessionArgs{
+ TerminateSession: true,
+ CGREvent: &utils.CGREvent{
+ Tenant: "cgrates.org",
+ ID: "TestSessionSBkupRplcTerminate",
+ Event: map[string]any{
+ utils.EventName: "TEST_EVENT",
+ utils.Tenant: "cgrates.org",
+ utils.OriginID: "123451",
+ utils.ToR: utils.MetaVoice,
+ utils.RequestType: utils.MetaPrepaid,
+ utils.AccountField: "1001",
+ utils.Subject: "1001",
+ utils.Destination: "1004",
+ utils.Category: "call",
+ utils.SetupTime: time.Date(2018, time.January, 7, 16, 60, 0, 0, time.UTC),
+ utils.AnswerTime: time.Date(2018, time.January, 7, 16, 60, 10, 0, time.UTC),
+ utils.Usage: 2*time.Minute + 30*time.Second,
+ },
+ },
+ }
+ var reply string
+ if err := sBRplcEng2RPC.Call(context.Background(), utils.SessionSv1TerminateSession, args, &reply); err != nil {
+ t.Error(err)
+ }
+ time.Sleep(time.Duration(*utils.WaitRater) * time.Millisecond) // Wait for the sessions to be populated
+ var aSessions []*ExternalSession
+ //check if the session was terminated on engine2
+ if err := sBRplcEng2RPC.Call(context.Background(), utils.SessionSv1GetActiveSessions,
+ new(utils.SessionFilter), &aSessions); err == nil || err.Error() != utils.ErrNotFound.Error() {
+ t.Errorf("Error: %v with len(aSessions)=%v , session : %+v", err, len(aSessions), utils.ToIJSON(aSessions))
+ }
+ // make sure we don't have passive session on engine2
+ var pSessions []*ExternalSession
+ if err := sBRplcEng2RPC.Call(context.Background(), utils.SessionSv1GetPassiveSessions, new(utils.SessionFilter),
+ &pSessions); err == nil || err.Error() != utils.ErrNotFound.Error() {
+ t.Errorf("Error: %v with len(pSessions)=%v , session : %+v", err, len(pSessions), utils.ToIJSON(pSessions))
+ }
+}
+
+func testSessionSBkupRplcGetNoActvSessionsFromRestored(t *testing.T) {
+ var aSessions []*ExternalSession
+ if err := sBRplcEng2RPC.Call(context.Background(), utils.SessionSv1GetActiveSessions,
+ utils.SessionFilter{}, &aSessions); err == nil || err.Error() != utils.ErrNotFound.Error() {
+ t.Error(err)
+ }
+
+ var pSessions []*ExternalSession
+ if err := sBRplcEng2RPC.Call(context.Background(), utils.SessionSv1GetPassiveSessions,
+ new(utils.SessionFilter), &pSessions); err == nil || err.Error() != utils.ErrNotFound.Error() {
+ t.Error(err)
+ }
+}
+
+func testSessionSBkupRplcStopCgrEngine(t *testing.T) {
+ if err := engine.KillEngine(1000); err != nil {
+ t.Error(err)
+ }
+}
diff --git a/sessions/sessions_test.go b/sessions/sessions_test.go
index a70b2d431..e7a91cb51 100644
--- a/sessions/sessions_test.go
+++ b/sessions/sessions_test.go
@@ -1938,21 +1938,23 @@ func (*testRPCClientConnection) Call(string, any, any) error { return nil }
func TestNewSessionS(t *testing.T) {
cgrCGF := config.NewDefaultCGRConfig()
- eOut := &SessionS{
- cgrCfg: cgrCGF,
- dm: nil,
- biJClnts: make(map[birpc.ClientConnector]string),
- biJIDs: make(map[string]*biJClient),
- aSessions: make(map[string]*Session),
- aSessionsIdx: make(map[string]map[string]map[string]utils.StringSet),
- aSessionsRIdx: make(map[string][]*riFieldNameVal),
- pSessions: make(map[string]*Session),
- pSessionsIdx: make(map[string]map[string]map[string]utils.StringSet),
- pSessionsRIdx: make(map[string][]*riFieldNameVal),
- }
sS := NewSessionS(cgrCGF, nil, nil)
+ eOut := &SessionS{
+ cgrCfg: cgrCGF,
+ dm: nil,
+ biJClnts: make(map[birpc.ClientConnector]string),
+ biJIDs: make(map[string]*biJClient),
+ aSessions: make(map[string]*Session),
+ aSessionsIdx: make(map[string]map[string]map[string]utils.StringSet),
+ aSessionsRIdx: make(map[string][]*riFieldNameVal),
+ pSessions: make(map[string]*Session),
+ pSessionsIdx: make(map[string]map[string]map[string]utils.StringSet),
+ pSessionsRIdx: make(map[string][]*riFieldNameVal),
+ markedSsCGRIDs: make(utils.StringSet),
+ removeSsCGRIDs: make(utils.StringSet),
+ }
if !reflect.DeepEqual(sS, eOut) {
- t.Errorf("Expected %s , received: %s", utils.ToJSON(sS), utils.ToJSON(eOut))
+ t.Errorf("Expected <%+v> , \nreceived: <%+v>", sS, eOut)
}
}
@@ -2663,6 +2665,7 @@ func TestInitSession(t *testing.T) {
},
DebitInterval: 0,
Chargeable: true,
+ UpdatedAt: s.UpdatedAt,
}
s.SRuns = nil
if !reflect.DeepEqual(exp, s) {
diff --git a/sessions/sessionscover_test.go b/sessions/sessionscover_test.go
index ff576d580..d7ca17171 100644
--- a/sessions/sessionscover_test.go
+++ b/sessions/sessionscover_test.go
@@ -1545,11 +1545,12 @@ func TestTransitSState(t *testing.T) {
CGRID: "TEST_CGRID",
},
}
- expected := &Session{
- CGRID: "TEST_CGRID",
- }
rcv = sessions.getActivateSession("test")
+ expected := &Session{
+ CGRID: "TEST_CGRID",
+ UpdatedAt: rcv.UpdatedAt,
+ }
if !reflect.DeepEqual(rcv, expected) {
t.Errorf("Expected %+v \n, received %+v", utils.ToJSON(expected), utils.ToJSON(rcv))
}
@@ -1579,6 +1580,7 @@ func TestRelocateSession(t *testing.T) {
},
},
}
+ rcv := sessions.relocateSession("111", "222", "127.0.0.1")
expected := &Session{
CGRID: "dfa2adaa5ab49349777c1ab3bcf3455df0259880",
EventStart: map[string]any{
@@ -1593,10 +1595,9 @@ func TestRelocateSession(t *testing.T) {
},
},
},
+ UpdatedAt: rcv.UpdatedAt,
}
- if rcv := sessions.relocateSession("111", "222", "127.0.0.1"); rcv == nil {
- t.Errorf("Expected to not be nil")
- } else if !reflect.DeepEqual(rcv, expected) {
+ if !reflect.DeepEqual(rcv, expected) {
t.Errorf("Expected %+v \n, received %+v", utils.ToJSON(expected), utils.ToJSON(rcv))
}
@@ -1604,7 +1605,7 @@ func TestRelocateSession(t *testing.T) {
"0d0fe8779b54c88f121e26c5d83abee5935127e5": nil,
}
- rcv := sessions.relocateSession("111", "222", utils.EmptyString)
+ rcv = sessions.relocateSession("111", "222", utils.EmptyString)
if rcv != nil {
t.Errorf("Expected to be nil")
}
@@ -1629,12 +1630,12 @@ func TestGetRelocateSession(t *testing.T) {
},
}
+ rcv = sessions.getRelocateSession("test", utils.EmptyString, "222", "127.0.0.1")
expected := &Session{
- CGRID: "TEST_CGRID",
+ CGRID: "TEST_CGRID",
+ UpdatedAt: rcv.UpdatedAt,
}
- if rcv = sessions.getRelocateSession("test", utils.EmptyString, "222", "127.0.0.1"); rcv == nil {
- t.Errorf("Expected to be nil")
- } else if !reflect.DeepEqual(rcv, expected) {
+ if !reflect.DeepEqual(rcv, expected) {
t.Errorf("Expected %+v \n, received %+v", utils.ToJSON(expected), utils.ToJSON(rcv))
}
}
diff --git a/utils/reflect_test.go b/utils/reflect_test.go
index 2b0822cb9..eddf185f7 100644
--- a/utils/reflect_test.go
+++ b/utils/reflect_test.go
@@ -2009,3 +2009,22 @@ func TestReflectDifference(t *testing.T) {
t.Error(rcv)
}
}
+
+func TestMapIfaceTimeAsString(t *testing.T) {
+ someTime := time.Date(2009, 11, 17, 20, 34, 58, 651387237, time.UTC)
+ mapAny := make(map[string]any)
+ mapAny["someTime"] = someTime
+ mapAny["timeDuration"] = 5 * time.Second
+ mapAny["simpleKey"] = "simpleValue"
+
+ MapIfaceTimeAsString(mapAny)
+ if mapAny["someTime"] != "2009-11-17T20:34:58Z" {
+ t.Errorf("Expected <%q>, received <%v>", "2009-11-17T20:34:58Z", mapAny["someTime"])
+ }
+ if mapAny["timeDuration"] != 5*time.Second {
+ t.Errorf("Expected <%q>, received <%v>", 5*time.Second, mapAny["timeDuration"])
+ }
+ if mapAny["simpleKey"] != "simpleValue" {
+ t.Errorf("Expected <%q>, received <%v>", "simpleValue", mapAny["simpleKey"])
+ }
+}