Beispiel #1
0
    def list(self):
        count = 0
        while True:
            queues = self._redis.xreadgroup(groupname=STREAM_GROUP, consumername=CONSUMER_NAME,
                                            streams={self._name: '>'}, count=1, block=round(self._timeout_ms))

            if not queues:
                queues = self._claim_olds()
                stats.set_gauge(['redis', self._name_str, 'nb_messages'], 0)
                if queues is None and self._stop_if_empty:
                    break
            if queues:
                for redis_message in queues:
                    queue_name, queue_messages = redis_message
                    assert queue_name == self._name
                    for message in queue_messages:
                        id_, body = message
                        try:
                            tile = decode_message(body[b'message'], from_redis=True, sqs_message=id_)
                            yield tile
                        except Exception:
                            logger.warning('Failed decoding the Redis message', exc_info=True)
                            stats.increment_counter(['redis', self._name_str, 'decode_error'])
                        count += 1

                if count % 100 == 0:
                    stats.set_gauge(['redis', self._name_str, 'nb_messages'], self._redis.xlen(name=self._name))
Beispiel #2
0
    def list(self):
        count = 0
        while True:
            queues = self._redis.xreadgroup(groupname=STREAM_GROUP,
                                            consumername=CONSUMER_NAME,
                                            streams={self._name: '>'},
                                            count=1,
                                            block=round(self._timeout_ms))

            if not queues:
                queues = self._claim_olds()
                stats.set_gauge(['redis', self._name_str, 'nb_messages'], 0)
                if queues is None and self._stop_if_empty:
                    break
            if queues:
                for redis_message in queues:
                    queue_name, queue_messages = redis_message
                    assert queue_name == self._name
                    for message in queue_messages:
                        id_, body = message
                        try:
                            tile = decode_message(body[b'message'],
                                                  from_redis=True,
                                                  sqs_message=id_)
                            yield tile
                        except Exception:
                            logger.warning('Failed decoding the Redis message',
                                           exc_info=True)
                            stats.increment_counter(
                                ['redis', self._name_str, 'decode_error'])
                        count += 1

                if count % 100 == 0:
                    stats.set_gauge(['redis', self._name_str, 'nb_messages'],
                                    self._redis.xlen(name=self._name))
Beispiel #3
0
    def _claim_olds(self):
        pendings = self._master.xpending_range(
            name=self._name, groupname=STREAM_GROUP, min="-", max="+", count=10
        )
        if not pendings:
            # None means there is nothing pending at all
            return None
        to_steal = []
        to_drop = []
        for pending in pendings:
            if int(pending["time_since_delivered"]) >= self._pending_timeout_ms:
                id_ = pending["message_id"]
                nb_retries = int(pending["times_delivered"])
                if nb_retries < self._max_retries:
                    logger.info(
                        "A message has been pending for too long. Stealing it (retry #%d): %s",
                        nb_retries,
                        id_,
                    )
                    to_steal.append(id_)
                else:
                    logger.warning(
                        "A message has been pending for too long and retried too many times. Dropping it: %s",
                        id_,
                    )
                    to_drop.append(id_)

        if to_drop:
            drop_messages = self._master.xclaim(
                name=self._name,
                groupname=STREAM_GROUP,
                consumername=CONSUMER_NAME,
                min_idle_time=self._pending_timeout_ms,
                message_ids=to_drop,
            )
            drop_ids = [drop_message[0] for drop_message in drop_messages]
            self._master.xack(self._name, STREAM_GROUP, *drop_ids)
            self._master.xdel(self._name, *drop_ids)
            for _, drop_message in drop_messages:
                tile = decode_message(drop_message[b"message"])
                self._master.xadd(
                    name=self._errors_name,
                    fields=dict(tilecoord=str(tile.tilecoord)),
                    maxlen=self._max_errors_nb,
                )
            stats.increment_counter(["redis", self._name_str, "dropped"], len(to_drop))

        if to_steal:
            messages = self._master.xclaim(
                name=self._name,
                groupname=STREAM_GROUP,
                consumername=CONSUMER_NAME,
                min_idle_time=self._pending_timeout_ms,
                message_ids=to_steal,
            )
            stats.increment_counter(["redis", self._name_str, "stolen"], len(to_steal))
            return [[self._name, messages]]
        else:
            # Empty means there are pending jobs, but they are not old enough to be stolen
            return []
Beispiel #4
0
    def list(self):
        while True:
            redis_message = self._redis.blpop(self._name,
                                              timeout=self._timeout)

            if not redis_message:
                if self._stop_if_empty:
                    break
            else:
                try:
                    tile = decode_message(redis_message[1], from_redis=True)
                    yield tile
                except Exception:
                    logger.warning('Failed decoding the Redis message',
                                   exc_info=True)
Beispiel #5
0
    def list(self) -> Iterator[Tile]:
        count = 0
        while True:
            queues = self._master.xreadgroup(
                groupname=STREAM_GROUP,
                consumername=CONSUMER_NAME,
                streams={self._name: ">"},
                count=1,
                block=round(self._timeout_ms),
            )
            logger.debug("Get %d new elements", len(queues))

            if not queues:
                queues = self._claim_olds()
                if queues is None:
                    stats.set_gauge(["redis", self._name_str, "nb_messages"],
                                    0)
                    stats.set_gauge(["redis", self._name_str, "pending"], 0)
                if queues is None and self._stop_if_empty:
                    break
            if queues:
                for redis_message in queues:
                    queue_name, queue_messages = redis_message
                    assert queue_name == self._name
                    for message in queue_messages:
                        id_, body = message
                        try:
                            tile = decode_message(body[b"message"],
                                                  from_redis=True,
                                                  sqs_message=id_)
                            yield tile
                        except Exception:
                            logger.warning("Failed decoding the Redis message",
                                           exc_info=True)
                            stats.increment_counter(
                                ["redis", self._name_str, "decode_error"])
                        count += 1

                if count % 10 == 0:
                    stats.set_gauge(
                        ["redis", self._name_str, "nb_messages"],
                        self._slave.xlen(name=self._name),
                    )
                    pending = self._slave.xpending(
                        self._name, STREAM_GROUP)  # type: ignore
                    stats.set_gauge(["redis", self._name_str, "pending"],
                                    pending["pending"])
Beispiel #6
0
    def list(self):
        while True:
            try:
                sqs_messages = self.queue.receive_messages(MaxNumberOfMessages=BATCH_SIZE)
            except botocore.exceptions.EndpointConnectionError:
                logger.warning("Error fetching SQS messages", exc_info=True)
                sqs_messages = []

            if not sqs_messages:
                if self.on_empty(self.queue):
                    break
            else:
                for sqs_message in sqs_messages:
                    try:
                        tile = decode_message(sqs_message.body.encode('utf-8'), sqs_message=sqs_message)
                        yield tile
                    except Exception:
                        logger.warning('Failed decoding the SQS message', exc_info=True)
                        sqs_message.delete()
Beispiel #7
0
    def _claim_olds(self):
        pendings = self._redis.xpending_range(name=self._name, groupname=STREAM_GROUP, min='-', max='+', count=10)
        if not pendings:
            # None means there is nothing pending at all
            return None
        to_steal = []
        to_drop = []
        for pending in pendings:
            if int(pending['time_since_delivered']) >= self._pending_timeout_ms:
                id_ = pending['message_id']
                nb_retries = int(pending['times_delivered'])
                if nb_retries < self._max_retries:
                    logger.info('A message has been pending for too long. Stealing it (retry #%d): %s', nb_retries, id_)
                    to_steal.append(id_)
                else:
                    logger.warning(
                        'A message has been pending for too long and retried too many times. Dropping it: %s', id_)
                    to_drop.append(id_)

        if to_drop:
            drop_messages = self._redis.xclaim(name=self._name, groupname=STREAM_GROUP, consumername=CONSUMER_NAME,
                                               min_idle_time=self._pending_timeout_ms, message_ids=to_drop)
            drop_ids = [drop_message[0] for drop_message in drop_messages]
            self._redis.xack(self._name, STREAM_GROUP, *drop_ids)
            self._redis.xdel(self._name, *drop_ids)
            for drop_id, drop_message in drop_messages:
                tile = decode_message(drop_message[b'message'])
                self._redis.xadd(name=self._errors_name, fields=dict(tilecoord=str(tile.tilecoord)),
                                 maxlen=self._max_errors_nb)
            stats.increment_counter(['redis', self._name_str, 'dropped'], len(to_drop))

        if to_steal:
            messages = self._redis.xclaim(name=self._name, groupname=STREAM_GROUP, consumername=CONSUMER_NAME,
                                          min_idle_time=self._pending_timeout_ms, message_ids=to_steal)
            stats.increment_counter(['redis', self._name_str, 'stolen'], len(to_steal))
            return [[self._name, messages]]
        else:
            # Empty means there are pending jobs, but they are not old enough to be stolen
            return []