def __deliver_responses(): import time registered_deliveries = r.scard('deliveries') deliveries_ready = r.scard('deliveries:ready') log.info("""Delivery daemon started: - Deliveries: {} - Ready: {}""".format(registered_deliveries, deliveries_ready)) log.info('Delivery daemon started') futures = {} while True: ready = r.smembers('deliveries:ready') for rid in ready: if rid not in futures: log.info('Response delivery of request {} is ready. Preparing...'.format(rid)) futures[rid] = thp.submit(__deliver_response, rid) for obsolete_rid in set.difference(set(futures.keys()), ready): if obsolete_rid in futures and futures[obsolete_rid].done(): del futures[obsolete_rid] sent = r.smembers('deliveries:sent') for rid in sent: r.srem('deliveries:ready', rid) r.srem('deliveries', rid) try: response = build_response(rid) response.sink.remove() log.info('Request {} was sent and cleared'.format(rid)) except AttributeError: log.warning('Request number {} was deleted by other means'.format(rid)) pass r.delete('deliveries:sent') time.sleep(1)
def __deliver_response(rid): 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 be something prepared to deliver. message, headers = messages.next() # Actually, this is the trigger reply(message, headers=headers, **response.sink.recipient) n_messages = 1 deliver_weight = len(str(message)) deliver_delta = deliver_weight for (message, headers) in messages: reply(message, headers=headers, **response.sink.recipient) n_messages += 1 deliver_weight += len(str(message)) deliver_delta += deliver_weight 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('deliveries:ready', rid) except StopIteration: # There was nothing prepared to deliver (Its state may have changed to # 'streaming') r.srem('deliveries:ready', rid) except (EnvironmentError, AttributeError, Exception), e: r.srem('deliveries:ready', 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))