Esempio n. 1
0
def handle_outgoing(msg):
    def onerror():
        logging.exception("Exception while processing SMS %s" % msg._id)
    if send_message_via_backend(msg, onerror=onerror):
        handle_successful_processing_attempt(msg)
    else:
        handle_unsuccessful_processing_attempt(msg)
Esempio n. 2
0
def handle_outgoing(msg):
    """
    Should return a requeue flag, so if it returns True, the message will be
    requeued and processed again immediately, and if it returns False, it will
    not be queued again.
    """
    backend = msg.outbound_backend
    sms_interval = backend.get_sms_interval()
    use_rate_limit = sms_interval is not None
    use_load_balancing = (isinstance(backend, SMSLoadBalancingMixin) and
        len(backend.phone_numbers) > 1)

    if use_rate_limit or use_load_balancing:
        client = get_redis_client()

    lbi = None
    orig_phone_number = None
    if use_load_balancing:
        lbi = backend.get_next_phone_number(client)
        orig_phone_number = lbi.phone_number
    elif (isinstance(backend, SMSLoadBalancingMixin) and 
        len(backend.phone_numbers) == 1):
        # If there's only one phone number, we don't need to go through the
        # load balancing algorithm. But we should always pass an
        # orig_phone_number if it's an instance of SMSLoadBalancingMixin.
        orig_phone_number = backend.phone_numbers[0]

    if use_rate_limit:
        if use_load_balancing:
            lock_key = "sms-backend-%s-rate-limit-phone-%s" % (backend._id,
                lbi.phone_number)
        else:
            lock_key = "sms-backend-%s-rate-limit" % backend._id
        lock = client.lock(lock_key, timeout=30)

    if not use_rate_limit or (use_rate_limit and lock.acquire(blocking=False)):
        if use_load_balancing:
            lbi.finish(save_stats=True)
        result = send_message_via_backend(msg, backend=backend, 
            orig_phone_number=orig_phone_number)
        if use_rate_limit:
            wait_and_release_lock(lock, sms_interval)

        # Only do the following if an unrecoverable error did not happen
        if not msg.error:
            if result:
                handle_successful_processing_attempt(msg)
            else:
                handle_unsuccessful_processing_attempt(msg)
        return False
    else:
        # We're using rate limiting, but couldn't acquire the lock, so
        # another thread is sending sms with this backend. Rather than wait,
        # we'll just put this message at the back of the queue.
        if use_load_balancing:
            lbi.finish(save_stats=False)
        return True
Esempio n. 3
0
def handle_outgoing(msg):
    """
    Should return a requeue flag, so if it returns True, the message will be
    requeued and processed again immediately, and if it returns False, it will
    not be queued again.
    """
    backend = msg.outbound_backend
    sms_interval = backend.get_sms_interval()
    use_rate_limit = sms_interval is not None
    use_load_balancing = (isinstance(backend, SMSLoadBalancingMixin) and
        len(backend.phone_numbers) > 1)

    if use_rate_limit or use_load_balancing:
        client = cache_core.get_redis_client()

    lbi = None
    orig_phone_number = None
    if use_load_balancing:
        lbi = backend.get_next_phone_number(client)
        orig_phone_number = lbi.phone_number
    elif (isinstance(backend, SMSLoadBalancingMixin) and 
        len(backend.phone_numbers) == 1):
        # If there's only one phone number, we don't need to go through the
        # load balancing algorithm. But we should always pass an
        # orig_phone_number if it's an instance of SMSLoadBalancingMixin.
        orig_phone_number = backend.phone_numbers[0]

    if use_rate_limit:
        if use_load_balancing:
            lock_key = "sms-backend-%s-rate-limit-phone-%s" % (backend._id,
                lbi.phone_number)
        else:
            lock_key = "sms-backend-%s-rate-limit" % backend._id
        lock = client.lock(lock_key, timeout=30)

    if not use_rate_limit or (use_rate_limit and lock.acquire(blocking=False)):
        if use_load_balancing:
            lbi.finish(save_stats=True)
        result = send_message_via_backend(msg, backend=backend, 
            orig_phone_number=orig_phone_number)
        if use_rate_limit:
            wait_and_release_lock(lock, sms_interval)

        # Only do the following if an unrecoverable error did not happen
        if not msg.error:
            if result:
                handle_successful_processing_attempt(msg)
            else:
                handle_unsuccessful_processing_attempt(msg)
        return False
    else:
        # We're using rate limiting, but couldn't acquire the lock, so
        # another thread is sending sms with this backend. Rather than wait,
        # we'll just put this message at the back of the queue.
        if use_load_balancing:
            lbi.finish(save_stats=False)
        return True
Esempio n. 4
0
def handle_outgoing(msg):
    """
    Should return a requeue flag, so if it returns True, the message will be
    requeued and processed again immediately, and if it returns False, it will
    not be queued again.
    """
    backend = msg.outbound_backend
    sms_rate_limit = backend.get_sms_rate_limit()
    use_rate_limit = sms_rate_limit is not None
    use_load_balancing = isinstance(backend, PhoneLoadBalancingMixin)
    max_simultaneous_connections = backend.get_max_simultaneous_connections()
    orig_phone_number = None

    if use_load_balancing:
        orig_phone_number = backend.get_next_phone_number(msg.phone_number)

    if use_rate_limit:
        if use_load_balancing:
            redis_key = 'sms-rate-limit-backend-%s-phone-%s' % (
                backend.pk, orig_phone_number)
        else:
            redis_key = 'sms-rate-limit-backend-%s' % backend.pk

        if not rate_limit(
                redis_key, actions_allowed=sms_rate_limit, how_often=60):
            # Requeue the message and try it again shortly
            return True

    if max_simultaneous_connections:
        connection_slot_lock = get_connection_slot_lock(
            msg.phone_number, backend, max_simultaneous_connections)
        if not connection_slot_lock.acquire(blocking=False):
            # Requeue the message and try it again shortly
            return True

    if passes_trial_check(msg):
        result = send_message_via_backend(msg,
                                          backend=backend,
                                          orig_phone_number=orig_phone_number)

    if max_simultaneous_connections:
        release_lock(connection_slot_lock, True)

    if msg.error:
        remove_from_queue(msg)
    else:
        # Only do the following if an unrecoverable error did not happen
        if result:
            handle_successful_processing_attempt(msg)
        else:
            handle_unsuccessful_processing_attempt(msg)

    return False
Esempio n. 5
0
def handle_outgoing(msg):
    """
    Should return a requeue flag, so if it returns True, the message will be
    requeued and processed again immediately, and if it returns False, it will
    not be queued again.
    """
    backend = msg.outbound_backend
    sms_rate_limit = backend.get_sms_rate_limit()
    use_rate_limit = sms_rate_limit is not None
    use_load_balancing = isinstance(backend, PhoneLoadBalancingMixin)
    max_simultaneous_connections = backend.get_max_simultaneous_connections()
    orig_phone_number = None

    if use_load_balancing:
        orig_phone_number = backend.get_next_phone_number(msg.phone_number)

    if use_rate_limit:
        if use_load_balancing:
            redis_key = 'sms-rate-limit-backend-%s-phone-%s' % (backend.pk, orig_phone_number)
        else:
            redis_key = 'sms-rate-limit-backend-%s' % backend.pk

        if not rate_limit(redis_key, actions_allowed=sms_rate_limit, how_often=60):
            # Requeue the message and try it again shortly
            return True

    if max_simultaneous_connections:
        connection_slot_lock = get_connection_slot_lock(msg.phone_number, backend, max_simultaneous_connections)
        if not connection_slot_lock.acquire(blocking=False):
            # Requeue the message and try it again shortly
            return True

    if passes_trial_check(msg):
        result = send_message_via_backend(
            msg,
            backend=backend,
            orig_phone_number=orig_phone_number
        )

    if max_simultaneous_connections:
        release_lock(connection_slot_lock, True)

    if msg.error:
        remove_from_queue(msg)
    else:
        # Only do the following if an unrecoverable error did not happen
        if result:
            handle_successful_processing_attempt(msg)
        else:
            handle_unsuccessful_processing_attempt(msg)

    return False
Esempio n. 6
0
def handle_outgoing(msg):
    """
    Should return a requeue flag, so if it returns True, the message will be
    requeued and processed again immediately, and if it returns False, it will
    not be queued again.
    """
    backend = msg.outbound_backend
    sms_rate_limit = backend.get_sms_rate_limit()
    use_rate_limit = sms_rate_limit is not None
    use_load_balancing = isinstance(backend, PhoneLoadBalancingMixin)
    orig_phone_number = None

    if use_load_balancing:
        orig_phone_number = backend.get_next_phone_number()

    if use_rate_limit:
        if use_load_balancing:
            redis_key = 'sms-rate-limit-backend-%s-phone-%s' % (backend.pk, orig_phone_number)
        else:
            redis_key = 'sms-rate-limit-backend-%s' % backend.pk

        if not rate_limit(redis_key, actions_allowed=sms_rate_limit, how_often=60):
            # Requeue the message and try it again shortly
            return True

    result = send_message_via_backend(
        msg,
        backend=backend,
        orig_phone_number=orig_phone_number
    )

    if not msg.error:
        # Only do the following if an unrecoverable error did not happen
        if result:
            handle_successful_processing_attempt(msg)
        else:
            handle_unsuccessful_processing_attempt(msg)

    return False