Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- from collections import defaultdict
- from itertools import chain, takewhile
- from toposort import toposort, toposort_flatten
- from twisted.application.service import IServiceCollection, Service
- from twisted.internet.defer import maybeDeferred, succeed
- from zope.interface import implementer
- def call_in_order(functions):
- def run(acc, fns):
- if not fns:
- return succeed(acc)
- fn = fns[0]
- result = maybeDeferred(fn)
- def ifResult(result):
- acc.append(result)
- return run(acc, fns[1:])
- def ifError(failute):
- setattr(failure, 'priorResults', acc)
- return failure
- result.addCallback(ifResult)
- result.addErrback(ifError)
- return result
- return run([], functions[:])
- @implementer(IServiceCollection)
- class Registry(Service):
- def __init__(self):
- self.services = {}
- self.namedServices = {}
- self.parent = None
- def addService(self, service):
- if service.name is not None:
- if service.name in self.namedServices:
- raise RuntimeError("cannot have two services with same name"
- " '%s'" % service.name)
- self.namedServices[service.name] = service
- self.services[service] = set()
- if self.running:
- return self._startServiceAndDependencies(service)
- def setDependenciesForService(service, dependencies):
- self.services[service] |= {
- self.getNamedService(dep)
- for dep in dependencies
- if type(dep) == str
- else dep
- }
- def __iter__(self):
- yield from toposort_flatten(services):
- def getDependenciesForService(self, service):
- yield from takewhile(lambda s: s != service, self)
- def getDependentsForService(self, service):
- services = list(self)
- services.reverse()
- yield from takewhile(lambda s: s != service, services)
- def privilegedStartService(self):
- super().privilegedStartService()
- for service in self:
- service.privilegedStartService()
- def startService(self):
- return call_in_order(
- chain([super().startService], s.startService for s in self)
- )
- def stopService(self):
- services = reversed(list(self))
- return call_in_order(
- chain([super().stopService], s.stopService for s in services)
- )
- def getServiceNamed(self, name):
- return self.namedServices[name]
- def _startServiceAndDependencies(self, service):
- return call_in_order(
- chain(
- s.startService
- for s in self.getDependenciesForService(service),
- [service.startService]
- )
- )
- def removeService(self, service):
- if service.name:
- del self.namedServices[service.name]
- services = self.getDependentsForService(service)
- def stopAndRemove(service):
- def callback():
- d = service.stopService()
- def removeAndReturn(result):
- del self.services[service]
- return result
- d.addCallback(removeAndReturn)
- return d
- return callback
- def finish():
- return maybeDeferred(super().stopService)
- if self.running:
- return call_in_order(
- chain(stopAndRemove(s) for s in services, finish)
- )
- else:
- return None
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement