push_notifications: Use ignore_conflicts, over catching IntegrityError.

The IntegrityError shows up in the database logs, which looks
unnecessarily concerning.  Use `ON CONFLICT IGNORE` to mark this as
expected, especially since the return value is never used.
This commit is contained in:
Alex Vandiver 2024-04-12 16:34:37 +00:00 committed by Tim Abbott
parent 9e28619727
commit 936c2b54cb
2 changed files with 35 additions and 37 deletions

View File

@ -26,7 +26,7 @@ import gcm
import lxml.html import lxml.html
import orjson import orjson
from django.conf import settings from django.conf import settings
from django.db import IntegrityError, transaction from django.db import transaction
from django.db.models import F, Q from django.db.models import F, Q
from django.utils.timezone import now as timezone_now from django.utils.timezone import now as timezone_now
from django.utils.translation import gettext as _ from django.utils.translation import gettext as _
@ -687,7 +687,7 @@ def send_notifications_to_bouncer(
def add_push_device_token( def add_push_device_token(
user_profile: UserProfile, token_str: str, kind: int, ios_app_id: Optional[str] = None user_profile: UserProfile, token_str: str, kind: int, ios_app_id: Optional[str] = None
) -> PushDeviceToken: ) -> None:
logger.info( logger.info(
"Registering push device: %d %r %d %r", user_profile.id, token_str, kind, ios_app_id "Registering push device: %d %r %d %r", user_profile.id, token_str, kind, ios_app_id
) )
@ -697,45 +697,42 @@ def add_push_device_token(
# These can be used to discern whether the user has any mobile # These can be used to discern whether the user has any mobile
# devices configured, and is also where we will store encryption # devices configured, and is also where we will store encryption
# keys for mobile push notifications. # keys for mobile push notifications.
try: PushDeviceToken.objects.bulk_create(
with transaction.atomic(): [
token = PushDeviceToken.objects.create( PushDeviceToken(
user_id=user_profile.id, user_id=user_profile.id,
kind=kind,
token=token_str, token=token_str,
kind=kind,
ios_app_id=ios_app_id, ios_app_id=ios_app_id,
# last_updated is to be renamed to date_created. # last_updated is to be renamed to date_created.
last_updated=timezone_now(), last_updated=timezone_now(),
) ),
except IntegrityError: ],
token = PushDeviceToken.objects.get( ignore_conflicts=True,
user_id=user_profile.id, )
kind=kind,
token=token_str, if not uses_notification_bouncer():
) return
# If we're sending things to the push notification bouncer # If we're sending things to the push notification bouncer
# register this user with them here # register this user with them here
if uses_notification_bouncer(): post_data = {
post_data = { "server_uuid": settings.ZULIP_ORG_ID,
"server_uuid": settings.ZULIP_ORG_ID, "user_uuid": str(user_profile.uuid),
"user_uuid": str(user_profile.uuid), "realm_uuid": str(user_profile.realm.uuid),
"realm_uuid": str(user_profile.realm.uuid), # user_id is sent so that the bouncer can delete any pre-existing registrations
# user_id is sent so that the bouncer can delete any pre-existing registrations # for this user+device to avoid duplication upon adding the uuid registration.
# for this user+device to avoid duplication upon adding the uuid registration. "user_id": str(user_profile.id),
"user_id": str(user_profile.id), "token": token_str,
"token": token_str, "token_kind": kind,
"token_kind": kind, }
}
if kind == PushDeviceToken.APNS: if kind == PushDeviceToken.APNS:
post_data["ios_app_id"] = ios_app_id post_data["ios_app_id"] = ios_app_id
logger.info("Sending new push device to bouncer: %r", post_data) logger.info("Sending new push device to bouncer: %r", post_data)
# Calls zilencer.views.register_remote_push_device # Calls zilencer.views.register_remote_push_device
send_to_push_bouncer("POST", "push/register", post_data) send_to_push_bouncer("POST", "push/register", post_data)
return token
def remove_push_device_token(user_profile: UserProfile, token_str: str, kind: int) -> None: def remove_push_device_token(user_profile: UserProfile, token_str: str, kind: int) -> None:

View File

@ -260,9 +260,9 @@ def register_remote_push_device(
remote_realm.last_request_datetime = timezone_now() remote_realm.last_request_datetime = timezone_now()
remote_realm.save(update_fields=["last_request_datetime"]) remote_realm.save(update_fields=["last_request_datetime"])
try: RemotePushDeviceToken.objects.bulk_create(
with transaction.atomic(): [
RemotePushDeviceToken.objects.create( RemotePushDeviceToken(
server=server, server=server,
kind=token_kind, kind=token_kind,
token=token, token=token,
@ -270,9 +270,10 @@ def register_remote_push_device(
# last_updated is to be renamed to date_created. # last_updated is to be renamed to date_created.
last_updated=timezone_now(), last_updated=timezone_now(),
**kwargs, **kwargs,
) ),
except IntegrityError: ],
pass ignore_conflicts=True,
)
return json_success(request) return json_success(request)