diff --git a/services/caches.go b/services/caches.go index aef1cead9..bd5161948 100644 --- a/services/caches.go +++ b/services/caches.go @@ -101,7 +101,7 @@ func (cS *CacheService) Shutdown() (_ error) { // IsRunning returns if the service is running func (cS *CacheService) IsRunning() bool { - return CheckServiceState(cS.ServiceName(), utils.StateServiceUP, cS.srvIndexer) + return IsServiceInState(cS.ServiceName(), utils.StateServiceUP, cS.srvIndexer) } // ServiceName returns the service name diff --git a/services/config.go b/services/config.go index b417df739..5eee72fa2 100644 --- a/services/config.go +++ b/services/config.go @@ -80,7 +80,7 @@ func (s *ConfigService) Shutdown() error { // IsRunning returns whether the service is running or not. func (s *ConfigService) IsRunning() bool { - return CheckServiceState(s.ServiceName(), utils.StateServiceUP, s.srvIndexer) + return IsServiceInState(s.ServiceName(), utils.StateServiceUP, s.srvIndexer) } // ServiceName returns the service name diff --git a/services/globalvars.go b/services/globalvars.go index dda1c06d6..b87f2ff36 100644 --- a/services/globalvars.go +++ b/services/globalvars.go @@ -74,7 +74,7 @@ func (gv *GlobalVarS) Shutdown() error { // IsRunning returns if the service is running func (gv *GlobalVarS) IsRunning() bool { - return CheckServiceState(gv.ServiceName(), utils.StateServiceUP, gv.srvIndexer) + return IsServiceInState(gv.ServiceName(), utils.StateServiceUP, gv.srvIndexer) } // ServiceName returns the service name diff --git a/services/guardian.go b/services/guardian.go index 12cdd8d63..668875cb8 100644 --- a/services/guardian.go +++ b/services/guardian.go @@ -80,7 +80,7 @@ func (s *GuardianService) Shutdown() error { // IsRunning returns whether the service is running or not. func (s *GuardianService) IsRunning() bool { - return CheckServiceState(s.ServiceName(), utils.StateServiceUP, s.srvIndexer) + return IsServiceInState(s.ServiceName(), utils.StateServiceUP, s.srvIndexer) } // ServiceName returns the service name diff --git a/services/statedeps.go b/services/statedeps.go index 0a33aa1aa..bbe1a8c89 100644 --- a/services/statedeps.go +++ b/services/statedeps.go @@ -19,7 +19,9 @@ along with this program. If not, see package services import ( + "fmt" "sync" + "time" "github.com/cgrates/cgrates/servmanager" ) @@ -47,9 +49,40 @@ func (sDs *StateDependencies) StateChan(stateID string) (retChan chan struct{}) return } -func CheckServiceState(id, state string, indexer *servmanager.ServiceIndexer) bool { +// waitForServicesToReachState ensures each service reaches the desired state, with the timeout applied individually per service. +// Returns a map of service names to their instances or an error if any service fails to reach its state within its timeout window. +func waitForServicesToReachState(state string, serviceIDs []string, indexer *servmanager.ServiceIndexer, timeout time.Duration, +) (map[string]servmanager.Service, error) { + services := make(map[string]servmanager.Service, len(serviceIDs)) + for _, serviceID := range serviceIDs { + srv, err := waitForServiceState(state, serviceID, indexer, timeout) + if err != nil { + return nil, err + } + services[srv.ServiceName()] = srv + + } + return services, nil +} + +// waitForServiceState waits up to timeout duration for a service to reach the specified state. +// Returns the service instance or an error if the timeout is exceeded. +func waitForServiceState(state, serviceID string, indexer *servmanager.ServiceIndexer, timeout time.Duration, +) (servmanager.Service, error) { + srv := indexer.GetService(serviceID) select { - case <-indexer.GetService(id).StateChan(state): + case <-srv.StateChan(state): + return srv, nil + case <-time.After(timeout): + return nil, fmt.Errorf("timed out waiting for service %q state %q", serviceID, state) + } +} + +// IsServiceInState performs a non-blocking check to determine if a service is in the specified state. +func IsServiceInState(serviceID, state string, indexer *servmanager.ServiceIndexer) bool { + svc := indexer.GetService(serviceID) + select { + case <-svc.StateChan(state): return true default: return false