Esempio n. 1
0
class Specialist(HospitalWorker):
    """
    Receives and processes specialized requests.
    Every specialist must be able to process exactly two
    out of three injury types (hip / knee / elbow).
    """
    def __init__(self, specializations):
        """
        Initializes connection structures, binds to each queue
        corresponding to specializations.
        """
        super().__init__()

        self._requests_consumer = Consumer('hospital', 'topic', 'localhost')

        for spec in specializations:
            self._requests_consumer.add_queue(queue_name=spec,
                                              routing_key='hosp.' + spec,
                                              callback=self.process_request)

        self._requests_consumer.start(new_thread=True)

    def process_request(self, ch, method, properties, body):
        """
        Simulates processing injury examination by sleeping random
        number of seconds (between 1 and 5) and sending back 'results' message.
        """
        body = body.decode()
        request_id = properties.correlation_id
        target = properties.reply_to

        log = colored(
            'processing request: ' + body + ' (request id: ' + request_id[:8] +
            ')', 'green')
        print(log, end='', flush=True)

        time_to_sleep = randint(1, 5)
        for _ in range(time_to_sleep):
            print(colored('.', 'green'), end='', flush=True)
            sleep(1)

        print('')

        message_opts = {
            'properties': pika.BasicProperties(correlation_id=request_id)
        }
        message = body + ' done'

        self._producer.send_message(routing_key=target,
                                    message=message,
                                    **message_opts)

        ch.basic_ack(delivery_tag=method.delivery_tag)
Esempio n. 2
0
class Administrator:
    """
    Receives and logs every message sent within the whole system.
    Is allowed to broadcast messages to all other workers.
    """
    def __init__(self):
        self._log_consumer = Consumer('hospital', 'topic', 'localhost')
        self._log_queue = self._log_consumer.add_queue(
            routing_key='#', callback=self.process_log)
        self._log_consumer.start(new_thread=True)
        self._info_producer = Producer('info', 'fanout', 'localhost')

    def send_info(self, message):
        print('sending info: ', message)
        self._info_producer.send_message(message=message)

    def process_log(self, ch, method, properties, body):
        body = body.decode()
        log = colored('LOG: ' + body, 'yellow')
        print(log)
        ch.basic_ack(delivery_tag=method.delivery_tag)
Esempio n. 3
0
class Medic(HospitalWorker):
    """
    Creates and sends specialized examination requests and receives
    the results. Every request must be of one of following types:
        - hip examination
        - knee examination
        - elbow examination
    """
    def __init__(self):
        """
        Initializes all data structures that will be used
        for receiving processed examination requests.
        """
        super().__init__()

        self._results_consumer = Consumer('hospital', 'topic', 'localhost')
        self._results_queue = self._results_consumer.add_queue(
            callback=self.process_results)
        self._results_consumer.start(new_thread=True)

        # Set of unique ids for every sent request
        # that hasn't been processed yet
        self._pending_requests = set()
        self._requests_lock = threading.Lock()

    def send_request(self, patient_name, injury_type):
        """
        Creates new request message and sends it to proper injury queue.
        Adds unique request id to pending requests set.
        """
        request_id = str(uuid4())
        routing_key = 'hosp.' + injury_type
        message = patient_name + ' ' + injury_type

        message_opts = {
            'properties':
            pika.BasicProperties(reply_to=self._results_queue,
                                 correlation_id=request_id)
        }

        with self._requests_lock:
            self._pending_requests.add(request_id)
            self._producer.send_message(routing_key, message, **message_opts)

        log = colored(
            'sending request: ' + message + ' (request id: ' + request_id[:8] +
            ')', 'blue')
        print(log)

    def process_results(self, ch, method, properties, body):
        """
        Removes request_id corresponding to received results
        from pending requests set.
        """
        body = body.decode()
        ignore = False
        request_id = properties.correlation_id

        with self._requests_lock:

            if request_id in self._pending_requests:
                self._pending_requests.remove(request_id)

            else:
                ignore = True

        if not ignore:
            log = colored(
                'received results: ' + body + ' (request id: ' +
                request_id[:8] + ')', 'green')
            print(log)

        ch.basic_ack(delivery_tag=method.delivery_tag)