mirror of
https://github.com/zulip/zulip.git
synced 2025-11-07 07:23:22 +00:00
push_notifications: Lazily import APNS libraries.
The APNS client libraries (especially the hyper.http20 one) were determined via profiling to take significant time during the import process, so we move them to be lazily imported in order to optimize the overall Zulip import process. This save up to about 100ms in import time. These libraries are only used in certain Django processes inside zulipchat.com, and so are unnecessary both in development as well as for self-hosted Zulip servers.
This commit is contained in:
@@ -12,14 +12,11 @@ import random
|
||||
|
||||
from typing import Any, Dict, List, Optional, SupportsInt, Tuple, Type, Union
|
||||
|
||||
from apns2.client import APNsClient
|
||||
from apns2.payload import Payload as APNsPayload
|
||||
from django.conf import settings
|
||||
from django.db import IntegrityError, transaction
|
||||
from django.utils.timezone import now as timezone_now
|
||||
from django.utils.translation import ugettext as _
|
||||
from gcm import GCM
|
||||
from hyper.http20.exceptions import HTTP20Error
|
||||
import requests
|
||||
import urllib
|
||||
import ujson
|
||||
@@ -55,10 +52,13 @@ def hex_to_b64(data: str) -> bytes:
|
||||
# Sending to APNs, for iOS
|
||||
#
|
||||
|
||||
_apns_client = None # type: Optional[APNsClient]
|
||||
_apns_client = None # type: Optional[Any]
|
||||
_apns_client_initialized = False
|
||||
|
||||
def get_apns_client() -> APNsClient:
|
||||
def get_apns_client() -> Any:
|
||||
# We lazily do this import as part of optimizing Zulip's base
|
||||
# import time.
|
||||
from apns2.client import APNsClient
|
||||
global _apns_client, _apns_client_initialized
|
||||
if not _apns_client_initialized:
|
||||
# NB if called concurrently, this will make excess connections.
|
||||
@@ -104,7 +104,15 @@ APNS_MAX_RETRIES = 3
|
||||
@statsd_increment("apple_push_notification")
|
||||
def send_apple_push_notification(user_id: int, devices: List[DeviceToken],
|
||||
payload_data: Dict[str, Any], remote: bool=False) -> None:
|
||||
client = get_apns_client()
|
||||
# We lazily do the APNS imports as part of optimizing Zulip's base
|
||||
# import time; since these are only needed in the push
|
||||
# notification queue worker, it's best to only import them in the
|
||||
# code that needs them.
|
||||
from apns2.payload import Payload as APNsPayload
|
||||
from apns2.client import APNsClient
|
||||
from hyper.http20.exceptions import HTTP20Error
|
||||
|
||||
client = get_apns_client() # type: APNsClient
|
||||
if client is None:
|
||||
logging.warning("APNs: Dropping a notification because nothing configured. "
|
||||
"Set PUSH_NOTIFICATION_BOUNCER_URL (or APNS_CERT_FILE).")
|
||||
|
||||
@@ -659,7 +659,7 @@ class TestAPNs(PushNotificationTest):
|
||||
import zerver.lib.push_notifications
|
||||
zerver.lib.push_notifications._apns_client_initialized = False
|
||||
with self.settings(APNS_CERT_FILE='/foo.pem'), \
|
||||
mock.patch('zerver.lib.push_notifications.APNsClient') as mock_client:
|
||||
mock.patch('apns2.client.APNsClient') as mock_client:
|
||||
client = get_apns_client()
|
||||
self.assertEqual(mock_client.return_value, client)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user