added some basic documentation to the config service manager and dependency finder

This commit is contained in:
Blake Harnden 2020-01-24 17:27:12 -08:00
parent bc2fb628cc
commit 22ff48182a
2 changed files with 55 additions and 2 deletions

View file

@ -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)

View file

@ -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)