Example #1
0
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)