added some basic documentation to the config service manager and dependency finder
This commit is contained in:
parent
bc2fb628cc
commit
22ff48182a
2 changed files with 55 additions and 2 deletions
|
@ -7,11 +7,15 @@ if TYPE_CHECKING:
|
||||||
|
|
||||||
class ConfigServiceDependencies:
|
class ConfigServiceDependencies:
|
||||||
"""
|
"""
|
||||||
Can generate boot paths for services, based on their dependencies. Will validate
|
Generates sets of services to start in order of their dependencies.
|
||||||
that all services will be booted and that all dependencies exist within the services provided.
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, services: Dict[str, "ConfigService"]) -> None:
|
def __init__(self, services: Dict[str, "ConfigService"]) -> None:
|
||||||
|
"""
|
||||||
|
Create a ConfigServiceDependencies instance.
|
||||||
|
|
||||||
|
:param services: services for determining dependency sets
|
||||||
|
"""
|
||||||
# helpers to check validity
|
# helpers to check validity
|
||||||
self.dependents = {}
|
self.dependents = {}
|
||||||
self.booted = set()
|
self.booted = set()
|
||||||
|
@ -28,6 +32,11 @@ class ConfigServiceDependencies:
|
||||||
self.visiting = set()
|
self.visiting = set()
|
||||||
|
|
||||||
def boot_paths(self) -> List[List["ConfigService"]]:
|
def boot_paths(self) -> List[List["ConfigService"]]:
|
||||||
|
"""
|
||||||
|
Find services sets based on dependencies.
|
||||||
|
|
||||||
|
:return: lists of lists of services that can be started in parallel
|
||||||
|
"""
|
||||||
paths = []
|
paths = []
|
||||||
for name in self.node_services:
|
for name in self.node_services:
|
||||||
service = self.node_services[name]
|
service = self.node_services[name]
|
||||||
|
@ -50,16 +59,33 @@ class ConfigServiceDependencies:
|
||||||
return paths
|
return paths
|
||||||
|
|
||||||
def _reset(self) -> None:
|
def _reset(self) -> None:
|
||||||
|
"""
|
||||||
|
Clear out metadata used for finding service dependency sets.
|
||||||
|
|
||||||
|
:return: nothing
|
||||||
|
"""
|
||||||
self.path = []
|
self.path = []
|
||||||
self.visited.clear()
|
self.visited.clear()
|
||||||
self.visiting.clear()
|
self.visiting.clear()
|
||||||
|
|
||||||
def _start(self, service: "ConfigService") -> List["ConfigService"]:
|
def _start(self, service: "ConfigService") -> List["ConfigService"]:
|
||||||
|
"""
|
||||||
|
Starts a oath for checking dependencies for a given service.
|
||||||
|
|
||||||
|
:param service: service to check dependencies for
|
||||||
|
:return: list of config services to start in order
|
||||||
|
"""
|
||||||
logging.debug("starting service dependency check: %s", service.name)
|
logging.debug("starting service dependency check: %s", service.name)
|
||||||
self._reset()
|
self._reset()
|
||||||
return self._visit(service)
|
return self._visit(service)
|
||||||
|
|
||||||
def _visit(self, current_service: "ConfigService") -> List["ConfigService"]:
|
def _visit(self, current_service: "ConfigService") -> List["ConfigService"]:
|
||||||
|
"""
|
||||||
|
Visits a service when discovering dependency chains for service.
|
||||||
|
|
||||||
|
:param current_service: service being visited
|
||||||
|
:return: list of dependent services for a visited service
|
||||||
|
"""
|
||||||
logging.debug("visiting service(%s): %s", current_service.name, self.path)
|
logging.debug("visiting service(%s): %s", current_service.name, self.path)
|
||||||
self.visited.add(current_service.name)
|
self.visited.add(current_service.name)
|
||||||
self.visiting.add(current_service.name)
|
self.visiting.add(current_service.name)
|
||||||
|
|
|
@ -8,16 +8,37 @@ from core.errors import CoreError
|
||||||
|
|
||||||
|
|
||||||
class ConfigServiceManager:
|
class ConfigServiceManager:
|
||||||
|
"""
|
||||||
|
Manager for configurable services.
|
||||||
|
"""
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
"""
|
||||||
|
Create a ConfigServiceManager instance.
|
||||||
|
"""
|
||||||
self.services = {}
|
self.services = {}
|
||||||
|
|
||||||
def get_service(self, name: str) -> Type[ConfigService]:
|
def get_service(self, name: str) -> Type[ConfigService]:
|
||||||
|
"""
|
||||||
|
Retrieve a service by name.
|
||||||
|
|
||||||
|
:param name: name of service
|
||||||
|
:return: service class
|
||||||
|
:raises CoreError: when service is not found
|
||||||
|
"""
|
||||||
service_class = self.services.get(name)
|
service_class = self.services.get(name)
|
||||||
if service_class is None:
|
if service_class is None:
|
||||||
raise CoreError(f"service does not exit {name}")
|
raise CoreError(f"service does not exit {name}")
|
||||||
return service_class
|
return service_class
|
||||||
|
|
||||||
def add(self, service: ConfigService) -> None:
|
def add(self, service: ConfigService) -> None:
|
||||||
|
"""
|
||||||
|
Add service to manager, checking service requirements have been met.
|
||||||
|
|
||||||
|
:param service: service to add to manager
|
||||||
|
:return: nothing
|
||||||
|
:raises CoreError: when service is a duplicate or has unmet executables
|
||||||
|
"""
|
||||||
name = service.name
|
name = service.name
|
||||||
logging.debug("loading service: class(%s) name(%s)", service.__class__, name)
|
logging.debug("loading service: class(%s) name(%s)", service.__class__, name)
|
||||||
|
|
||||||
|
@ -38,6 +59,12 @@ class ConfigServiceManager:
|
||||||
self.services[name] = service
|
self.services[name] = service
|
||||||
|
|
||||||
def load(self, path: str) -> List[str]:
|
def load(self, path: str) -> List[str]:
|
||||||
|
"""
|
||||||
|
Search path provided for configurable services and add them for being managed.
|
||||||
|
|
||||||
|
:param path: path to search configurable services
|
||||||
|
:return: list errors when loading and adding services
|
||||||
|
"""
|
||||||
path = pathlib.Path(path)
|
path = pathlib.Path(path)
|
||||||
subdirs = [x for x in path.iterdir() if x.is_dir()]
|
subdirs = [x for x in path.iterdir() if x.is_dir()]
|
||||||
subdirs.append(path)
|
subdirs.append(path)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue