'Fetch events from some remote destinations, checking if we already
have them.
Args:
destinations (list)
room_id (str)
event_ids (list)
return_local (bool): Whether to include events we already have in
the DB in the returned list of events
Returns:
Deferred: A deferred resolving to a 2-tuple where the first is a list of
events and the second is a list of event ids that we failed to fetch.'

@defer.inlineCallbacks
def get_events(self, destinations, room_id, event_ids, return_local=True):

    if return_local:
        seen_events = (yield self.store.get_events(event_ids, allow_rejected=True))
        signed_events = seen_events.values()
    else:
        seen_events = (yield self.store.have_events(event_ids))
        signed_events = []
    failed_to_fetch = set()
    missing_events = set(event_ids)
    for k in seen_events:
        missing_events.discard(k)
    if (not missing_events):
        defer.returnValue((signed_events, failed_to_fetch))
    def random_server_list():
        srvs = list(destinations)
        random.shuffle(srvs)
        return srvs
    batch_size = 20
    missing_events = list(missing_events)
    for i in xrange(0, len(missing_events), batch_size):
        batch = set(missing_events[i:(i + batch_size)])
        deferreds = [preserve_fn(self.get_pdu)(destinations=random_server_list(), event_id=e_id) for e_id in batch]
        res = (yield preserve_context_over_deferred(defer.DeferredList(deferreds, consumeErrors=True)))
        for (success, result) in res:
            if (success and result):
                signed_events.append(result)
                batch.discard(result.event_id)
        failed_to_fetch.update(batch)
    defer.returnValue((signed_events, failed_to_fetch))
