class ServiceThread(Thread): def __init__(self, service, logfile): super().__init__() self.__service = service self.__logfile = logfile self.__request_queue = Queue() self.__dependencies = [] self.__children = [] self.__handlers = { ServiceThreadMessage.START : self.__start, ServiceThreadMessage.STOP : self.__stop, ServiceThreadMessage.RESTART : self.__restart, ServiceThreadMessage.HALT : self.__halt, ServiceThreadMessage.ADD_CHILD : self.__add_child, ServiceThreadMessage.ADD_DEPENDENCY : self.__add_dependency, } self.__process_thread = Thread() self.__terminated = Event() # TODO: replace with state? self.__running = False def service(self): return self.__service def logfile(self): return self.__logfile def run(self): logging.info("{} >> Ready".format(self)) while not self.__terminated.is_set(): _message = self.__request_queue.get() self.__handlers.get(_message[0])(_message[1:]) self.__request_queue.task_done() def put_request(self, message, block=False): self.__request_queue.put(message) if block: self.__request_queue.join() def is_running(self): return self.__running == True; def __start(self, message): logging.info("{} << Received START message".format(self)) if not self.__dependencies_running(): logging.info("{} << Unable to perform START: missing dependencies".format(self)) return self.__process_thread = ProcessThreadFactory.create(self, self.__logfile) self.__process_thread.start() logging.info("{} >> Response from [{}]: {}".format( self, self.__process_thread, self.__process_thread.get_response() )) self.__running = True self.__notify((ServiceThreadMessage.RESTART,)) def __dependencies_running(self): for dependency in self.__dependencies: if not dependency.is_running(): logging.info("{} << [{}] is not yet started".format(self, dependency)) return False return True def __stop(self, message): logging.info("{} << Received STOP message".format(self)) if self.__process_thread.is_alive(): self.__process_thread.terminate() logging.info("{} >> Response from [{}]: {}".format( self, self.__process_thread, self.__process_thread.get_response() )) self.__running = False def __restart(self, message): # TODO: Max restart-retry-count # we have to calculate the number of restart per unit time # we have to store the last valid restart-time logging.info("{} << Received RESTART message".format(self)) self.__stop(message) self.__start(message) def __halt(self, message): logging.info("{} << Received HALT message".format(self)) self.__stop(message) self.__terminated.set() def __add_child(self, message): _child = message[0] self.__children.append(_child) logging.info("{} >> Registered to publish over [{}]".format(self, _child)) def __add_dependency(self, message): _dependency = message[0] self.__dependencies.append(_dependency) logging.info("{} >> Registered dependency [{}]".format(self, _dependency)) def __notify(self, message): for child in self.__children: child.put_request(message) def __str__(self): return "{}:{}".format(self.__class__.__name__, self.__service)