forked from LBRYCommunity/lbry-sdk
93 lines
2.8 KiB
Python
93 lines
2.8 KiB
Python
import logging
|
|
from twisted.internet import defer
|
|
|
|
log = logging.getLogger(__name__)
|
|
|
|
|
|
class ComponentManager(object):
|
|
components = set()
|
|
|
|
@classmethod
|
|
def sort_components(cls, reverse=False):
|
|
"""
|
|
Sort components by requirements
|
|
"""
|
|
steps = []
|
|
staged = set()
|
|
components = set(cls.components)
|
|
|
|
# components with no requirements
|
|
step = []
|
|
for component in set(components):
|
|
if not component.depends_on:
|
|
step.append(component)
|
|
staged.add(component.component_name)
|
|
components.remove(component)
|
|
|
|
if step:
|
|
steps.append(step)
|
|
|
|
while components:
|
|
step = []
|
|
to_stage = set()
|
|
for component in set(components):
|
|
reqs_met = 0
|
|
for needed in component.depends_on:
|
|
if needed in staged:
|
|
reqs_met += 1
|
|
if reqs_met == len(component.depends_on):
|
|
step.append(component)
|
|
to_stage.add(component.component_name)
|
|
components.remove(component)
|
|
if step:
|
|
staged.update(to_stage)
|
|
steps.append(step)
|
|
elif components:
|
|
raise SyntaxError("components cannot be started: %s" % components)
|
|
if reverse:
|
|
steps.reverse()
|
|
return steps
|
|
|
|
@classmethod
|
|
@defer.inlineCallbacks
|
|
def setup(cls):
|
|
"""
|
|
Start Components in sequence sorted by requirements
|
|
|
|
:return: (defer.Deferred)
|
|
"""
|
|
stages = cls.sort_components()
|
|
for stage in stages:
|
|
yield defer.DeferredList([component._setup() for component in stage])
|
|
|
|
@classmethod
|
|
@defer.inlineCallbacks
|
|
def stop(cls):
|
|
"""
|
|
Stop Components in reversed startup order
|
|
|
|
:return: (defer.Deferred)
|
|
"""
|
|
stages = cls.sort_components(reverse=True)
|
|
for stage in stages:
|
|
yield defer.DeferredList([component._stop() for component in stage])
|
|
|
|
@classmethod
|
|
def all_components_running(cls, *component_names):
|
|
"""
|
|
:return: (bool) True if all specified components are running
|
|
"""
|
|
c = {component.component_name: component for component in cls.components}
|
|
for component in component_names:
|
|
if component not in c:
|
|
raise NameError("%s is not a known Component" % component)
|
|
if not c[component].running:
|
|
return False
|
|
return True
|
|
|
|
@classmethod
|
|
def get_component(cls, component_name):
|
|
for component in cls.components:
|
|
if component.component_name == component_name:
|
|
return component
|
|
raise NameError(component_name)
|