'Takes a database connection and waits for requests for events from
the _event_fetch_list queue.'

def _do_fetch(self, conn):

    event_list = []
    i = 0
    while True:
        try:
            with self._event_fetch_lock:
                event_list = self._event_fetch_list
                self._event_fetch_list = []
                if (not event_list):
                    single_threaded = self.database_engine.single_threaded
                    if (single_threaded or (i > EVENT_QUEUE_ITERATIONS)):
                        self._event_fetch_ongoing -= 1
                        return
                    else:
                        self._event_fetch_lock.wait(EVENT_QUEUE_TIMEOUT_S)
                        i += 1
                        continue
                i = 0
            event_id_lists = zip(*event_list)[0]
            event_ids = [item for sublist in event_id_lists for item in sublist]
            rows = self._new_transaction(conn, 'do_fetch', [], [], None, self._fetch_event_rows, event_ids)
            row_dict = {r['event_id']: r for r in rows}
            def fire(lst, res):
                for (ids, d) in lst:
                    if (not d.called):
                        try:
                            with PreserveLoggingContext():
                                d.callback([res[i] for i in ids if (i in res)])
                        except:
                            logger.exception('Failed    to    callback')
            with PreserveLoggingContext():
                reactor.callFromThread(fire, event_list, row_dict)
        except Exception as e:
            logger.exception('do_fetch')
            def fire(evs):
                for (_, d) in evs:
                    if (not d.called):
                        with PreserveLoggingContext():
                            d.errback(e)
            if event_list:
                with PreserveLoggingContext():
                    reactor.callFromThread(fire, event_list)
