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)
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
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
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
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
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