Skip to content
This repository has been archived by the owner on Jul 13, 2023. It is now read-only.

Commit

Permalink
refactor: cleanup some deferred arg bookkeeping
Browse files Browse the repository at this point in the history
- try to isolate it to the deferred definition and avoid passing args
back and forth when not necessary
- also put all_channels call back in a thread

issue #695
  • Loading branch information
pjenvey committed Apr 6, 2017
1 parent 013db1c commit 55e91c5
Show file tree
Hide file tree
Showing 15 changed files with 256 additions and 191 deletions.
9 changes: 4 additions & 5 deletions autopush/db.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,11 +57,11 @@
Set,
TypeVar,
Tuple,
Union,
)

from autopush.exceptions import AutopushException
from autopush.metrics import IMetrics # noqa
from autopush.types import ItemLike # noqa
from autopush.utils import (
generate_hash,
normalize_id,
Expand All @@ -70,7 +70,6 @@

# Typing
T = TypeVar('T') # noqa
ItemLike = Union[Item, Dict[str, Any]]

key_hash = ""
TRACK_DB_CALLS = False
Expand Down Expand Up @@ -679,7 +678,7 @@ def get_uaid(self, uaid):

@track_provisioned
def register_user(self, data):
# type: (ItemLike) -> Tuple[bool, Dict[str, Any], Dict[str, Any]]
# type: (ItemLike) -> Tuple[bool, Dict[str, Any]]
"""Register this user
If a record exists with a newer ``connected_at``, then the user will
Expand Down Expand Up @@ -728,9 +727,9 @@ def register_user(self, data):
# this not work
r[key] = value
result = r
return (True, result, data)
return (True, result)
except ConditionalCheckFailedException:
return (False, {}, data)
return (False, {})

@track_provisioned
def drop_user(self, uaid):
Expand Down
17 changes: 6 additions & 11 deletions autopush/router/apnsrouter.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
"""APNS Router"""
import uuid
from typing import Any # noqa

from hyper.http20.exceptions import ConnectionError, HTTP20Error
from twisted.internet.threads import deferToThread
Expand All @@ -12,6 +13,7 @@
APNS_MAX_CONNECTIONS,
)
from autopush.router.interface import RouterResponse
from autopush.types import JSONDict # noqa


# https://github.com/djacobs/PyAPNs
Expand Down Expand Up @@ -67,21 +69,15 @@ def __init__(self, ap_settings, router_conf, load_connections=True):
self.log.debug("Starting APNS router...")

def register(self, uaid, router_data, app_id, *args, **kwargs):
# type: (str, JSONDict, str, *Any, **Any) -> None
"""Register an endpoint for APNS, on the `app_id` release channel.
This will validate that an APNs instance token is in the
`router_data`,
:param uaid: User Agent Identifier
:type uaid: str
:param router_data: Dict containing router specific configuration info
:type router_data: dict
:param app_id: The release channel identifier for cert info lookup
:type app_id: str
:returns: a modified router_data for the user agent record.
:rtype: dict
"""
if app_id not in self.apns:
Expand All @@ -92,11 +88,10 @@ def register(self, uaid, router_data, app_id, *args, **kwargs):
raise RouterException("No token registered", status_code=400,
response_body="No token registered")
router_data["rel_channel"] = app_id
return router_data

def amend_msg(self, msg, router_data=None):
"""This function is stubbed out for this router"""
return msg
def amend_endpoint_response(self, response, router_data):
# type: (JSONDict, JSONDict) -> None
"""Stubbed out for this router"""

def route_notification(self, notification, uaid_data):
"""Start the APNS notification routing, returns a deferred
Expand Down
11 changes: 6 additions & 5 deletions autopush/router/fcm.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
"""FCM Router"""
from typing import Any # noqa

import pyfcm
from requests.exceptions import ConnectionError
Expand All @@ -7,6 +8,7 @@

from autopush.exceptions import RouterException
from autopush.router.interface import RouterResponse
from autopush.types import JSONDict # noqa


class FCMRouter(object):
Expand Down Expand Up @@ -117,12 +119,12 @@ def __init__(self, ap_settings, router_conf):
self.log.debug("Starting FCM router...")
self.ap_settings = ap_settings

def amend_msg(self, msg, data=None):
if data is not None:
msg["senderid"] = data.get('creds', {}).get('senderID')
return msg
def amend_endpoint_response(self, response, router_data):
# type: (JSONDict, JSONDict) -> None
response["senderid"] = router_data.get('creds', {}).get('senderID')

def register(self, uaid, router_data, app_id, *args, **kwargs):
# type: (str, JSONDict, str, *Any, **Any) -> None
"""Validate that the FCM Instance Token is in the ``router_data``"""
senderid = app_id
# "token" is the GCM registration id token generated by the client.
Expand All @@ -142,7 +144,6 @@ def register(self, uaid, router_data, app_id, *args, **kwargs):
# Assign a senderid
router_data["creds"] = {"senderID": self.senderID,
"auth": self.auth}
return router_data

def route_notification(self, notification, uaid_data):
"""Start the FCM notification routing, returns a deferred"""
Expand Down
11 changes: 6 additions & 5 deletions autopush/router/gcm.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
"""GCM Router"""
from typing import Any # noqa

import gcmclient
from requests.exceptions import ConnectionError
Expand All @@ -7,6 +8,7 @@

from autopush.exceptions import RouterException
from autopush.router.interface import RouterResponse
from autopush.types import JSONDict # noqa


class GCMRouter(object):
Expand Down Expand Up @@ -40,12 +42,12 @@ def __init__(self, ap_settings, router_conf):
self.log.debug("Starting GCM router...")
self.ap_settings = ap_settings

def amend_msg(self, msg, data=None):
if data is not None:
msg["senderid"] = data.get('creds', {}).get('senderID')
return msg
def amend_endpoint_response(self, response, router_data):
# type: (JSONDict, JSONDict) -> None
response["senderid"] = router_data.get('creds', {}).get('senderID')

def register(self, uaid, router_data, app_id, *args, **kwargs):
# type: (str, JSONDict, str, *Any, **Any) -> None
"""Validate that the GCM Instance Token is in the ``router_data``"""
# "token" is the GCM registration id token generated by the client.
if "token" not in router_data:
Expand All @@ -65,7 +67,6 @@ def register(self, uaid, router_data, app_id, *args, **kwargs):
# Assign a senderid
router_data["creds"] = {"senderID": senderid,
"auth": self.senderIDs[senderid]}
return router_data

def route_notification(self, notification, uaid_data):
"""Start the GCM notification routing, returns a deferred"""
Expand Down
29 changes: 16 additions & 13 deletions autopush/router/interface.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
"""Router interface"""
from typing import Any, Optional # noqa
from typing import Any # noqa

from autopush.types import JSONDict # noqa


class RouterResponse(object):
Expand Down Expand Up @@ -28,10 +30,9 @@ def __init__(self, settings, router_conf):
raise NotImplementedError("__init__ must be implemented")

def register(self, uaid, router_data, app_id, *args, **kwargs):
# type: (str, dict, str, *Any, **Any) -> dict
"""Register the uaid with the router_data dict however is preferred
and return a dict that will be stored as router_data for this
user in the future.
# type: (str, JSONDict, str, *Any, **Any) -> None
"""Register the uaid with router_data however is preferred prior to
storing router_data for this user.
:param uaid: User Agent Identifier
:param router_data: Route specific configuration info
Expand All @@ -43,18 +44,20 @@ def register(self, uaid, router_data, app_id, *args, **kwargs):
"""
raise NotImplementedError("register must be implemented")

def amend_msg(self, msg, router_data=None):
# type: (dict, Optional[dict]) -> dict
"""Modify an outbound response message to include router info
def amend_endpoint_response(self, response, router_data):
# type: (JSONDict, JSONDict) -> None
"""Modify an outbound Endpoint registration response to
include router info.
:param msg: A dict of the response data to be sent to the client
:param router_data: a dictionary of router data
:returns: A potentially modified dict to return to the client
Some routers require additional info to be returned to
clients.
Some routers may require additional info to be returned to clients.
:param response: The response data to be sent to the client
:param router_data: Route specific configuration info
"""
raise NotImplementedError("amend_msg must be implemented")
raise NotImplementedError(
"amend_endpoint_response must be implemented")

def route_notification(self, notification, uaid_data):
"""Route a notification
Expand Down
13 changes: 8 additions & 5 deletions autopush/router/simple.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import json
from urllib import urlencode
from StringIO import StringIO
from typing import Any # noqa

import requests
from boto.dynamodb2.exceptions import (
Expand All @@ -32,6 +33,7 @@
from autopush.exceptions import RouterException
from autopush.protocol import IgnoreBody
from autopush.router.interface import RouterResponse
from autopush.types import JSONDict # noqa


class SimpleRouter(object):
Expand All @@ -47,12 +49,13 @@ def __init__(self, ap_settings, router_conf):
self.conf = router_conf
self.waker = None

def register(self, uaid, *args, **kwargs):
"""Return no additional routing data"""
return {}
def register(self, uaid, router_data, app_id, *args, **kwargs):
# type: (str, JSONDict, str, *Any, **Any) -> None
"""No additional routing data"""

def amend_msg(self, msg, router_data=None):
return msg
def amend_endpoint_response(self, response, router_data):
# type: (JSONDict, JSONDict) -> None
"""Stubbed out for this router"""

def stored_response(self, notification):
return RouterResponse(202, "Notification Stored")
Expand Down
3 changes: 0 additions & 3 deletions autopush/router/webpush.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,3 @@ def _save_notification(self, uaid_data, notification):
self.ap_settings.message_tables[month_table].store_message,
notification=notification,
)

def amend_msg(self, msg, router_data=None):
return msg
2 changes: 1 addition & 1 deletion autopush/tests/test_db.py
Original file line number Diff line number Diff line change
Expand Up @@ -501,7 +501,7 @@ def raise_condition(*args, **kwargs):
router_data = dict(uaid=dummy_uaid, node_id="asdf", connected_at=1234,
router_type="simplepush")
result = router.register_user(router_data)
eq_(result, (False, {}, router_data))
eq_(result, (False, {}))

def test_node_clear(self):
r = get_router_table()
Expand Down
38 changes: 38 additions & 0 deletions autopush/tests/test_endpoint.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
create_rotating_message_table,
has_connected_this_month,
)
from autopush.exceptions import RouterException
from autopush.settings import AutopushSettings
from autopush.router.interface import IRouter
from autopush.tests.test_db import make_webpush_notification
Expand Down Expand Up @@ -433,6 +434,28 @@ def restore(*args, **kwargs):
self.reg.post(self._make_req())
return self.finish_deferred

def test_post_bad_router_register(self, *args):
frouter = Mock(spec=IRouter)
self.reg.ap_settings.routers["simplepush"] = frouter
rexc = RouterException("invalid", status_code=402, errno=107)
frouter.register = Mock(side_effect=rexc)

self.reg.request.body = json.dumps(dict(
type="simplepush",
channelID=str(dummy_chid),
data={},
))
self.reg.request.uri = "/v1/xxx/yyy/register"
self.reg.request.headers["Authorization"] = self.auth

def handle_finish(value):
self._check_error(rexc.status_code, rexc.errno, "")

self.finish_deferred.addBoth(handle_finish)
self.reg.post(self._make_req("simplepush", "",
body=self.reg.request.body))
return self.finish_deferred

def test_post_existing_uaid(self, *args):
self.reg.request.body = json.dumps(dict(
channelID=str(dummy_chid),
Expand Down Expand Up @@ -734,6 +757,19 @@ def restore(*args, **kwargs):
self.reg.put(self._make_req(uaid=dummy_uaid.hex))
return self.finish_deferred

def test_put_bad_router_register(self):
frouter = self.reg.ap_settings.routers["test"]
rexc = RouterException("invalid", status_code=402, errno=107)
frouter.register = Mock(side_effect=rexc)

def handle_finish(value):
self._check_error(rexc.status_code, rexc.errno, "")

self.finish_deferred.addCallback(handle_finish)
self.reg.request.headers["Authorization"] = self.auth
self.reg.put(self._make_req(router_type='test', uaid=dummy_uaid.hex))
return self.finish_deferred

def test_delete_bad_chid_value(self):
notif = make_webpush_notification(dummy_uaid.hex, str(dummy_chid))
messages = self.reg.ap_settings.message
Expand Down Expand Up @@ -842,6 +878,8 @@ def test_get(self):
chids = [str(dummy_chid), str(dummy_uaid)]

def handle_finish(value):
self.settings.message.all_channels.assert_called_with(
str(dummy_uaid))
call_args = json.loads(
self.reg.write.call_args[0][0]
)
Expand Down
Loading

0 comments on commit 55e91c5

Please sign in to comment.