コード例 #1
0
class AsyncParser:
    """
    Create a message parser which decodes details about the provided messages and dispatches
    the resulting augmented messages to an output queue.
    """

    _logger = logging.getLogger('AsyncParser')

    def __init__(self, number_workers=5):
        self._worker_q = Queue.Queue()
        self.out_q = Queue.Queue()
        self._number_workers = number_workers
        self._threads = []

        # Make a "fast" parser, by simply install a url fetcher that return an empty string.
        # (sometimes you just have to love the power of dependency injection :)
        self._fastParser = HipChatParser(NullUrlFetcher())

    def start(self):
        """
        Start pulling messages from the queue and dispatching them to the out queue
        """
        self._logger.debug('Starting...')
        # In a real app, we would manage these threads more intelligently
        self._threads = [self._create_worker(i) for i in range(self._number_workers)]
        self._logger.info('Started')

    def stop(self):
        """
        Shutdown this processor in an orderly fashion
        """
        self._logger.debug('Stopping...')
        for t in self._threads:
            t.join()
        self._logger.info('Stopped')

    def parse(self, msg):
        """
        Parses the given message and send the result to the output queue
        """
        self._logger.debug('Parsing: %s', msg)

        # Quickly decode the details that we can do without delay
        msg.details = self._fastParser.parse_to_dict(msg.text)
        msg.details_as_json = self._fastParser.dict_to_json(msg.details)

        # Pumps out the message. "slow" details are not yet filled in
        self.out_q.put(msg)

        # If the message had links, send it to the workers, which will
        # produced an updated message once the details are filled in
        if HipChatParser.DETAIL_LINKS in msg.details:
            self._worker_q.put(msg)

    def _create_worker(self, worker_id):
        """
        Create and start a worker that will collect more costly message details
        """
        w = ParserWorkerThread(worker_id, self._worker_q, self.out_q)
        w.start()
        return w