diff --git a/config/config_it_test.go b/config/config_it_test.go index b2e96845c..7992d31b8 100644 --- a/config/config_it_test.go +++ b/config/config_it_test.go @@ -360,6 +360,73 @@ func TestCGRConfigReloadRALs(t *testing.T) { } } +func TestCGRConfigReloadSessionS(t *testing.T) { + cfg, err := NewDefaultCGRConfig() + if err != nil { + t.Fatal(err) + } + cfg.RalsCfg().Enabled = true + cfg.ChargerSCfg().Enabled = true + cfg.CdrsCfg().Enabled = true + var reply string + if err = cfg.V1ReloadConfig(&ConfigReloadWithArgDispatcher{ + Path: path.Join("/usr", "share", "cgrates", "conf", "samples", "tutmongo2"), + Section: SessionSJson, + }, &reply); err != nil { + t.Error(err) + } else if reply != utils.OK { + t.Errorf("Expected OK received: %s", reply) + } + expAttr := &SessionSCfg{ + Enabled: true, + ListenBijson: "127.0.0.1:2014", + ChargerSConns: []*RemoteHost{ + &RemoteHost{ + Address: utils.MetaInternal, + }, + }, + RALsConns: []*RemoteHost{ + &RemoteHost{ + Address: utils.MetaInternal, + }, + }, + ResSConns: []*RemoteHost{ + &RemoteHost{ + Address: "127.0.0.1:2012", + Transport: utils.MetaJSONrpc, + }, + }, + ThreshSConns: []*RemoteHost{}, + StatSConns: []*RemoteHost{}, + SupplSConns: []*RemoteHost{ + &RemoteHost{ + Address: "127.0.0.1:2012", + Transport: utils.MetaJSONrpc, + }, + }, + AttrSConns: []*RemoteHost{ + &RemoteHost{ + Address: "127.0.0.1:2012", + Transport: utils.MetaJSONrpc, + }, + }, + CDRsConns: []*RemoteHost{ + &RemoteHost{ + Address: utils.MetaInternal, + }, + }, + + SessionReplicationConns: []*RemoteHost{}, + MaxCallDuration: 3 * time.Hour, + SessionIndexes: utils.NewStringMap(), + ClientProtocol: 1, + TerminateAttempts: 5, + } + if !reflect.DeepEqual(expAttr, cfg.SessionSCfg()) { + t.Errorf("Expected %s , received: %s ", utils.ToJSON(expAttr), utils.ToJSON(cfg.SessionSCfg())) + } +} + func TestCgrCfgV1ReloadConfigSection(t *testing.T) { for _, dir := range []string{"/tmp/ers/in", "/tmp/ers/out"} { if err := os.RemoveAll(dir); err != nil { diff --git a/services/sessions.go b/services/sessions.go index 69b0c73e8..23728db6e 100644 --- a/services/sessions.go +++ b/services/sessions.go @@ -116,11 +116,11 @@ func (smg *SessionService) Start(sp servmanager.ServiceProvider, waitCache bool) statSConns, suplSConns, attrConns, cdrsConn, chargerSConn, sReplConns, sp.GetDM(), sp.GetConfig().GeneralCfg().DefaultTimezone) //start sync session in a separate gorutine - go func() { - if err = smg.sm.ListenAndServe(sp.GetExitChan()); err != nil { + go func(sm *sessions.SessionS) { + if err = sm.ListenAndServe(sp.GetExitChan()); err != nil { utils.Logger.Err(fmt.Sprintf("<%s> error: %s!", utils.SessionS, err)) } - }() + }(smg.sm) // Pass internal connection via BiRPCClient smg.connChan <- smg.sm // Register RPC handler @@ -139,9 +139,8 @@ func (smg *SessionService) Start(sp servmanager.ServiceProvider, waitCache bool) for method, handler := range smg.rpcv1.Handlers() { sp.GetServer().BiRPCRegisterName(method, handler) } - sp.GetServer().ServeBiJSON(sp.GetConfig().SessionSCfg().ListenBijson, smg.sm.OnBiJSONConnect, smg.sm.OnBiJSONDisconnect) - return fmt.Errorf("<%s> the session ServeBiJSON should not exit", - utils.SessionS) // imposible this should never reach + // run this in it's own gorutine + go sp.GetServer().ServeBiJSON(sp.GetConfig().SessionSCfg().ListenBijson, smg.sm.OnBiJSONConnect, smg.sm.OnBiJSONDisconnect) } return } diff --git a/services/sessions_it_test.go b/services/sessions_it_test.go new file mode 100644 index 000000000..6d5dacf4e --- /dev/null +++ b/services/sessions_it_test.go @@ -0,0 +1,100 @@ +// +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 services + +import ( + "path" + "testing" + "time" + + "github.com/cgrates/cgrates/config" + "github.com/cgrates/cgrates/engine" + "github.com/cgrates/cgrates/servmanager" + "github.com/cgrates/cgrates/utils" + "github.com/cgrates/rpcclient" +) + +func TestSessionSReload(t *testing.T) { + cfg, err := config.NewDefaultCGRConfig() + if err != nil { + t.Fatal(err) + } + cfg.ChargerSCfg().Enabled = true + cfg.RalsCfg().Enabled = true + cfg.CdrsCfg().Enabled = true + utils.Newlogger(utils.MetaSysLog, cfg.GeneralCfg().NodeID) + utils.Logger.SetLogLevel(7) + filterSChan := make(chan *engine.FilterS, 1) + filterSChan <- nil + engineShutdown := make(chan bool, 1) + chS := engine.NewCacheS(cfg, nil) + + close(chS.GetPrecacheChannel(utils.CacheChargerProfiles)) + close(chS.GetPrecacheChannel(utils.CacheChargerFilterIndexes)) + + close(chS.GetPrecacheChannel(utils.CacheDestinations)) + close(chS.GetPrecacheChannel(utils.CacheReverseDestinations)) + close(chS.GetPrecacheChannel(utils.CacheRatingPlans)) + close(chS.GetPrecacheChannel(utils.CacheRatingProfiles)) + close(chS.GetPrecacheChannel(utils.CacheActions)) + close(chS.GetPrecacheChannel(utils.CacheActionPlans)) + close(chS.GetPrecacheChannel(utils.CacheAccountActionPlans)) + close(chS.GetPrecacheChannel(utils.CacheActionTriggers)) + close(chS.GetPrecacheChannel(utils.CacheSharedGroups)) + close(chS.GetPrecacheChannel(utils.CacheTimings)) + + cacheSChan := make(chan rpcclient.RpcClientConnection, 1) + cacheSChan <- chS + + server := utils.NewServer() + srvMngr := servmanager.NewServiceManager(cfg /*dm*/, nil, + /*cdrStorage*/ nil, + /*loadStorage*/ nil, filterSChan, + server, nil, engineShutdown) + srvMngr.SetCacheS(chS) + attrS := NewSessionService() + srvMngr.AddService(attrS, NewChargerService(), NewRalService(srvMngr), &CacheService{connChan: cacheSChan}, NewSchedulerService(), NewCDRServer()) + if err = srvMngr.StartServices(); err != nil { + t.Error(err) + } + if attrS.IsRunning() { + t.Errorf("Expected service to be down") + } + var reply string + if err := cfg.V1ReloadConfig(&config.ConfigReloadWithArgDispatcher{ + Path: path.Join("/usr", "share", "cgrates", "conf", "samples", "tutmongonew"), + Section: config.SessionSJson, + }, &reply); err != nil { + t.Error(err) + } else if reply != utils.OK { + t.Errorf("Expecting OK ,received %s", reply) + } + time.Sleep(10 * time.Millisecond) //need to switch to gorutine + if !attrS.IsRunning() { + t.Errorf("Expected service to be running") + } + cfg.SessionSCfg().Enabled = false + cfg.GetReloadChan(config.SessionSJson) <- struct{}{} + time.Sleep(10 * time.Millisecond) + if attrS.IsRunning() { + t.Errorf("Expected service to be down") + } + engineShutdown <- true +}