'Requests the PDU with given origin and ID from the remote home
servers.
Will attempt to get the PDU from each destination in the list until
one succeeds.
This will persist the PDU locally upon receipt.
Args:
destinations (list): Which home servers to query
event_id (str): event to fetch
outlier (bool): Indicates whether the PDU is an `outlier`, i.e. if
it\'s from an arbitary point in the context as opposed to part
of the current block of PDUs. Defaults to `False`
timeout (int): How long to try (in ms) each destination for before
moving to the next destination. None indicates no timeout.
Returns:
Deferred: Results in the requested PDU.'

@defer.inlineCallbacks
@log_function
def get_pdu(self, destinations, event_id, outlier=False, timeout=None):

    if self._get_pdu_cache:
        ev = self._get_pdu_cache.get(event_id)
        if ev:
            defer.returnValue(ev)
    pdu_attempts = self.pdu_destination_tried.setdefault(event_id, {})
    signed_pdu = None
    for destination in destinations:
        now = self._clock.time_msec()
        last_attempt = pdu_attempts.get(destination, 0)
        if ((last_attempt + PDU_RETRY_TIME_MS) > now):
            continue
        try:
            transaction_data = (yield self.transport_layer.get_event(destination, event_id, timeout=timeout))
            logger.debug('transaction_data    %r', transaction_data)
            pdu_list = [self.event_from_pdu_json(p, outlier=outlier) for p in transaction_data['pdus']]
            if (pdu_list and pdu_list[0]):
                pdu = pdu_list[0]
                signed_pdu = (yield self._check_sigs_and_hashes([pdu])[0])
                break
            pdu_attempts[destination] = now
        except SynapseError as e:
            logger.info('Failed    to    get    PDU    %s    from    %s    because    %s', event_id, destination, e)
        except NotRetryingDestination as e:
            logger.info(e.message)
            continue
        except Exception as e:
            pdu_attempts[destination] = now
            logger.info('Failed    to    get    PDU    %s    from    %s    because    %s', event_id, destination, e)
            continue
    if ((self._get_pdu_cache is not None) and signed_pdu):
        self._get_pdu_cache[event_id] = signed_pdu
    defer.returnValue(signed_pdu)
