Exemplo n.º 1
0
def __deliver_response(rid):
    """
    The delivery task for a given request id
    :param rid: Request id
    """

    def deliver_message():
        reply(message, headers=headers, **response.sink.recipient)
        return len(str(message))

    response = None
    try:
        response = build_response(rid)
        delivery_state = response.sink.delivery
        if delivery_state == 'ready':
            messages = response.build()
            # The creation of a response object may change the corresponding request delivery state
            # (mixing, streaming, etc). The thing is that it was 'ready' before,
            # so it should has something prepared to deliver.
            n_messages = 0
            deliver_weight = 0

            message, headers = messages.next()  # Actually, this is the trigger
            deliver_weight += deliver_message()
            n_messages += 1

            deliver_delta = 0
            for (message, headers) in messages:
                message_weight = deliver_message()
                deliver_weight += message_weight
                deliver_delta += message_weight
                n_messages += 1
                if deliver_delta > 1000:
                    deliver_delta = 0
                    __log.info('Delivering response of request {} [{} kB]'.format(rid, deliver_weight / 1000.0))

            deliver_weight /= 1000.0
            __log.info('{} messages delivered for request {} [{} kB]'.format(n_messages, rid, deliver_weight))

        elif delivery_state == 'accepted':
            __log.error('Request {} should not be marked as deliver-ready, its state is inconsistent'.format(rid))
        else:
            __log.info('Response of request {} is being delivered by other means...'.format(rid))
            r.srem(__ready_key, rid)
    except StopIteration:  # There was nothing prepared to deliver (Its state may have changed to
        # 'streaming')
        r.srem(__ready_key, rid)
    except (EnvironmentError, AttributeError, Exception), e:
        r.srem(__ready_key, rid)
        # traceback.print_exc()
        __log.warning(e.message)
        if response is not None:
            __log.error('Force remove of request {} due to a delivery error'.format(rid))
            response.sink.remove()
        else:
            __log.error("Couldn't remove request {}".format(rid))
Exemplo n.º 2
0
def __deliver_responses():
    import time
    __log.info('Delivery daemon started')

    # Declare in-progress deliveries dictionary
    futures = {}
    while True:
        try:
            # Get all ready deliveries
            ready = r.smembers(__ready_key)
            for rid in ready:
                # If the delivery is not in the thread pool, just submit it
                if rid not in futures:
                    __log.info('Response delivery of request {} is ready. Putting it in queue...'.format(rid))
                    futures[rid] = __thp.submit(__deliver_response, rid)

            # Clear futures that have already ceased to be ready
            for obsolete_rid in set.difference(set(futures.keys()), ready):
                if obsolete_rid in futures and futures[obsolete_rid].done():
                    del futures[obsolete_rid]

            # All those deliveries that are marked as 'sent' are being cleared here along its request data
            sent = r.smembers(__sent_key)
            for rid in sent:
                r.srem(__ready_key, rid)
                r.srem(__deliveries_key, rid)
                try:
                    response = build_response(rid)
                    response.sink.remove()  # Its lock is removed too
                    __log.info('Request {} was sent and cleared'.format(rid))
                except AttributeError:
                    traceback.print_exc()
                    __log.warning('Request number {} was deleted by other means'.format(rid))
                    pass
                r.srem(__sent_key, rid)
        except Exception as e:
            __log.error(e.message)
            traceback.print_exc()
        finally:
            time.sleep(0.1)