push_notifs: Set up plumbing for retrying in case of bouncer error.

We add PushNotificationBouncerRetryLaterError as an exception to signal
an error occurred when trying to communicate with the bouncer and it
should be retried. We use JsonableError as the base class, because this
signal will need to work in two roles:
1. When the push notification was being issued by the queue worker
PushNotificationsWorker, it will signal to the worker to requeue the
event and try again later.
2. The exception will also possibly be raised (this will be added in the
next commit) on codepaths coming from a request to an API endpoint (for
example to add a token, to users/me/apns_device_token). In that case,
it'll be needed to provide a good error to the API user - and basing
this exception on JsonableError will allow that.
This commit is contained in:
Mateusz Mandera
2019-12-02 19:46:11 +01:00
committed by Tim Abbott
parent 717e90dfeb
commit 20b30e1503
5 changed files with 89 additions and 35 deletions

View File

@@ -23,8 +23,8 @@ from zerver.lib.avatar import absolute_avatar_url
from zerver.lib.exceptions import JsonableError
from zerver.lib.message import access_message, \
bulk_access_messages_expect_usermessage, huddle_users
from zerver.lib.queue import retry_event
from zerver.lib.remote_server import send_to_push_bouncer, send_json_to_push_bouncer
from zerver.lib.remote_server import send_to_push_bouncer, send_json_to_push_bouncer, \
PushNotificationBouncerRetryLaterError
from zerver.lib.timestamp import datetime_to_timestamp
from zerver.models import PushDeviceToken, Message, Recipient, \
UserMessage, UserProfile, \
@@ -674,10 +674,8 @@ def handle_remove_push_notification(user_profile_id: int, message_ids: List[int]
gcm_payload,
gcm_options)
except requests.ConnectionError: # nocoverage
def failure_processor(event: Dict[str, Any]) -> None:
logger.warning(
"Maximum retries exceeded for trigger:%s event:push_notification" % (
event['user_profile_id'],))
raise PushNotificationBouncerRetryLaterError(
"ConnectionError while trying to connect to the bouncer")
else:
android_devices = list(PushDeviceToken.objects.filter(
user=user_profile, kind=PushDeviceToken.GCM))
@@ -751,14 +749,10 @@ def handle_push_notification(user_profile_id: int, missed_message: Dict[str, Any
apns_payload,
gcm_payload,
gcm_options)
return
except requests.ConnectionError:
def failure_processor(event: Dict[str, Any]) -> None:
logger.warning(
"Maximum retries exceeded for trigger:%s event:push_notification" % (
event['user_profile_id'],))
retry_event('missedmessage_mobile_notifications', missed_message,
failure_processor)
return
raise PushNotificationBouncerRetryLaterError(
"ConnectionError while trying to connect to the bouncer")
android_devices = list(PushDeviceToken.objects.filter(user=user_profile,
kind=PushDeviceToken.GCM))