'Fetches events from the database using the _event_fetch_list. This
allows batch and bulk fetching of events - it allows us to fetch events
without having to create a new transaction for each request for events.'

@defer.inlineCallbacks
def _enqueue_events(self, events, check_redacted=True, allow_rejected=False):

    if (not events):
        defer.returnValue({})
    events_d = defer.Deferred()
    with self._event_fetch_lock:
        self._event_fetch_list.append((events, events_d))
        self._event_fetch_lock.notify()
        if (self._event_fetch_ongoing < EVENT_QUEUE_THREADS):
            self._event_fetch_ongoing += 1
            should_start = True
        else:
            should_start = False
    if should_start:
        with PreserveLoggingContext():
            self.runWithConnection(self._do_fetch)
    logger.debug('Loading    %d    events', len(events))
    with PreserveLoggingContext():
        rows = (yield events_d)
    logger.debug('Loaded    %d    events    (%d    rows)', len(events), len(rows))
    if (not allow_rejected):
        rows[:] = [r for r in rows if (not r['rejects'])]
    res = (yield preserve_context_over_deferred(defer.gatherResults([preserve_fn(self._get_event_from_row)(row['internal_metadata'], row['json'], row['redacts'], rejected_reason=row['rejects']) for row in rows], consumeErrors=True)))
    defer.returnValue({e.event.event_id: e for e in res if e})
