Send push notifications more aggresively

Unbundle the push notifications from the missed message queue processors
and handlers. This makes notifications more immediate, and sets things up
for better badge count handling, and possibly per-stream filtering.

(imported from commit 11840301751b0bbcb3a99848ff9868d9023b665b)
This commit is contained in:
acrefoot
2013-11-18 18:55:24 -05:00
parent bbda1d93c4
commit 8ee7536012
3 changed files with 28 additions and 15 deletions

View File

@@ -1994,25 +1994,32 @@ def do_send_missedmessage_events(user_profile, missed_messages):
user_profile.last_reminder = datetime.datetime.now() user_profile.last_reminder = datetime.datetime.now()
user_profile.save(update_fields=['last_reminder']) user_profile.save(update_fields=['last_reminder'])
if user_profile.enable_offline_push_notifications:
if num_push_devices_for_user(user_profile) == 0:
return return
badge_count = len(missed_messages) @statsd_increment("push_notifications")
def handle_push_notification(user_profile_id, missed_message):
user_profile = get_user_profile_by_id(user_profile_id)
message = UserMessage.objects.get(user_profile=user_profile,
message__id=missed_message['message_id'],
flags=~UserMessage.flags.read).message
sender_str = message.sender.full_name
if user_profile.enable_offline_push_notifications and num_push_devices_for_user(user_profile):
#TODO: set badge count in a better way
# Determine what alert string to display based on the missed messages # Determine what alert string to display based on the missed messages
if all(msg.recipient.type == Recipient.HUDDLE for msg in missed_messages): if message.recipient.type == Recipient.HUDDLE:
alert = "New private group message%s from %s" % (plural_messages, sender_str) alert = "New private group message from %s" % (sender_str,)
elif all(msg.recipient.type == Recipient.PERSONAL for msg in missed_messages): elif message.recipient.type == Recipient.PERSONAL:
alert = "New private message%s from %s" % (plural_messages, sender_str) alert = "New private message from %s" % (sender_str,)
elif all(msg.recipient.type == Recipient.STREAM for msg in missed_messages): elif message.recipient.type == Recipient.STREAM:
alert = "New mention%s from %s" % (plural_messages, sender_str) alert = "New mention from %s" % (sender_str,)
else: else:
alert = "New Zulip mentions and private messages from %s" % (sender_str,) alert = "New Zulip mentions and private messages from %s" % (sender_str,)
extra_data = {'message_ids': [message.id]}
extra_data = {'message_ids': [amsg.id for amsg in missed_messages]} logging.info("sending push notification %r, %r" % (user_profile, alert))
send_apple_push_notification(user_profile, alert, badge=1, zulip=extra_data)
send_apple_push_notification(user_profile, alert, badge=badge_count, zulip=extra_data) return
def handle_missedmessage_emails(user_profile_id, missed_email_events): def handle_missedmessage_emails(user_profile_id, missed_email_events):
message_ids = [event.get('message_id') for event in missed_email_events] message_ids = [event.get('message_id') for event in missed_email_events]

View File

@@ -69,6 +69,7 @@ def missedmessage_hook(user_profile_id, queue, last_for_client):
for msg_id in message_ids: for msg_id in message_ids:
event = build_offline_notification_event(user_profile_id, msg_id) event = build_offline_notification_event(user_profile_id, msg_id)
queue_json_publish("missedmessage_emails", event, lambda event: None) queue_json_publish("missedmessage_emails", event, lambda event: None)
queue_json_publish("missedmessage_mobile_notifications", event, lambda event: None)
def cache_load_message_data(message_id, users): def cache_load_message_data(message_id, users):
# Get everything that we'll need out of memcached in one fetch, to save round-trip times: # Get everything that we'll need out of memcached in one fetch, to save round-trip times:
@@ -169,7 +170,6 @@ def process_new_message(data):
received_pm = message.recipient.type in (Recipient.PERSONAL, Recipient.HUDDLE) and \ received_pm = message.recipient.type in (Recipient.PERSONAL, Recipient.HUDDLE) and \
user_profile_id != message.sender.id user_profile_id != message.sender.id
mentioned = 'mentioned' in flags mentioned = 'mentioned' in flags
if (received_pm or mentioned) and receiver_is_idle(user_profile, realm_presences): if (received_pm or mentioned) and receiver_is_idle(user_profile, realm_presences):
if receives_offline_notifications(user_profile): if receives_offline_notifications(user_profile):
event = build_offline_notification_event(user_profile_id, message.id) event = build_offline_notification_event(user_profile_id, message.id)
@@ -177,6 +177,7 @@ def process_new_message(data):
# We require RabbitMQ to do this, as we can't call the email handler # We require RabbitMQ to do this, as we can't call the email handler
# from the Tornado process. So if there's no rabbitmq support do nothing # from the Tornado process. So if there's no rabbitmq support do nothing
queue_json_publish("missedmessage_emails", event, lambda event: None) queue_json_publish("missedmessage_emails", event, lambda event: None)
queue_json_publish("missedmessage_mobile_notifications", event, lambda event: None)
for client, flags in send_to_clients.itervalues(): for client, flags in send_to_clients.itervalues():
if not client.accepts_event_type('message'): if not client.accepts_event_type('message'):

View File

@@ -13,7 +13,7 @@ from zerver.lib.actions import handle_missedmessage_emails, do_send_confirmation
do_update_user_activity, do_update_user_activity_interval, do_update_user_presence, \ do_update_user_activity, do_update_user_activity_interval, do_update_user_presence, \
internal_send_message, send_local_email_template_with_delay, clear_followup_emails_queue, \ internal_send_message, send_local_email_template_with_delay, clear_followup_emails_queue, \
check_send_message, extract_recipients, one_click_unsubscribe_link, \ check_send_message, extract_recipients, one_click_unsubscribe_link, \
enqueue_welcome_emails enqueue_welcome_emails, handle_push_notification
from zerver.lib.digest import handle_digest_email from zerver.lib.digest import handle_digest_email
from zerver.decorator import JsonableError from zerver.decorator import JsonableError
from zerver.lib.socket import req_redis_key from zerver.lib.socket import req_redis_key
@@ -179,6 +179,11 @@ class MissedMessageWorker(QueueProcessingWorker):
# of messages # of messages
time.sleep(2 * 60) time.sleep(2 * 60)
@assign_queue('missedmessage_mobile_notifications')
class PushNotificationsWorker(QueueProcessingWorker):
def consume(self, data):
handle_push_notification(data['user_profile_id'], data)
def make_feedback_client(): def make_feedback_client():
sys.path.append(os.path.join(os.path.dirname(__file__), '../../api')) sys.path.append(os.path.join(os.path.dirname(__file__), '../../api'))
import zulip import zulip