# Path: autopush/constants.py
# DEFAULT_ROUTER_TIMEOUT = 3
# 
# Path: autopush/exceptions.py
# class RouterException(AutopushException):
#     """Exception if routing has failed, may include a custom status_code and
#     body to write to the response.
# 
#     """
#     def __init__(self, message, status_code=500, response_body="",
#                  router_data=None, headers=None, log_exception=True,
#                  errno=None, logged_status=None, **kwargs):
#         """Create a new RouterException"""
#         super(AutopushException, self).__init__(message)
#         self.status_code = status_code
#         self.headers = {} if headers is None else headers
#         self.log_exception = log_exception
#         self.response_body = response_body or message
#         self.errno = errno
#         self.logged_status = logged_status
#         self.extra = kwargs
# 
# Path: autopush/metrics.py
# def make_tags(base=None, **kwargs):
#     # type: (Sequence[str], **Any) -> Sequence[str]
#     """Generate a list of tag values"""
#     tags = list(base or [])
#     tags.extend('{}:{}'.format(key, val) for key, val in kwargs.iteritems())
#     return tags
# 
# Path: autopush/router/interface.py
# class RouterResponse(object):
#     """Router response if routing has succeeded.
# 
#     If the router data needs to change as a result of this message, either the
#     router got invalidated, or needs updating, then the router_data should be
#     set.
# 
#     """
#     def __init__(self, status_code=200, response_body="", router_data=None,
#                  headers=None, errno=None, logged_status=None):
#         """Create a new RouterResponse"""
#         self.status_code = status_code
#         self.response_body = response_body
#         self.router_data = router_data
#         self.headers = {} if headers is None else headers
#         self.errno = errno
#         self.logged_status = logged_status
# 
# Path: autopush/types.py



import time
import requests
from typing import Any  # noqa
from requests.exceptions import ConnectionError, Timeout
from twisted.internet.threads import deferToThread
from twisted.logger import Logger
from autopush.constants import DEFAULT_ROUTER_TIMEOUT
from autopush.exceptions import RouterException
from autopush.metrics import make_tags
from autopush.router.interface import RouterResponse
from autopush.types import JSONDict  # noqa
        # registration_ids are the ADM instance tokens (specified during
        # registration.
        ttl = min(self.MAX_TTL,
                  max(notification.ttl or 0, self.min_ttl))

        try:
            adm = self.profiles[router_data['creds']['profile']]
            adm.send(
                reg_id=router_data.get("token"),
                payload=data,
                collapseKey=notification.topic,
                ttl=ttl
            )
        except RouterException:
            raise  # pragma nocover
        except Timeout as e:
            self.log.warn("ADM Timeout: %s" % e)
            self.metrics.increment("notification.bridge.error",
                                   tags=make_tags(
                                       self._base_tags,
                                       reason="timeout"))
            raise RouterException("Server error", status_code=502,
                                  errno=902,
                                  log_exception=False)
        except ConnectionError as e:
            self.log.warn("ADM Unavailable: %s" % e)
            self.metrics.increment("notification.bridge.error",
                                   tags=make_tags(
                                       self._base_tags,
                                       reason="connection_unavailable"))

# Path: autopush/constants.py
# DEFAULT_ROUTER_TIMEOUT = 3
# 
# Path: autopush/exceptions.py
# class RouterException(AutopushException):
#     """Exception if routing has failed, may include a custom status_code and
#     body to write to the response.
# 
#     """
#     def __init__(self, message, status_code=500, response_body="",
#                  router_data=None, headers=None, log_exception=True,
#                  errno=None, logged_status=None, **kwargs):
#         """Create a new RouterException"""
#         super(AutopushException, self).__init__(message)
#         self.status_code = status_code
#         self.headers = {} if headers is None else headers
#         self.log_exception = log_exception
#         self.response_body = response_body or message
#         self.errno = errno
#         self.logged_status = logged_status
#         self.extra = kwargs
# 
# Path: autopush/metrics.py
# def make_tags(base=None, **kwargs):
#     # type: (Sequence[str], **Any) -> Sequence[str]
#     """Generate a list of tag values"""
#     tags = list(base or [])
#     tags.extend('{}:{}'.format(key, val) for key, val in kwargs.iteritems())
#     return tags
# 
# Path: autopush/router/interface.py
# class RouterResponse(object):
#     """Router response if routing has succeeded.
# 
#     If the router data needs to change as a result of this message, either the
#     router got invalidated, or needs updating, then the router_data should be
#     set.
# 
#     """
#     def __init__(self, status_code=200, response_body="", router_data=None,
#                  headers=None, errno=None, logged_status=None):
#         """Create a new RouterResponse"""
#         self.status_code = status_code
#         self.response_body = response_body
#         self.router_data = router_data
#         self.headers = {} if headers is None else headers
#         self.errno = errno
#         self.logged_status = logged_status
# 
# Path: autopush/types.py



# Path: autopush/router/adm.py
import time
import requests
from typing import Any  # noqa
from requests.exceptions import ConnectionError, Timeout
from twisted.internet.threads import deferToThread
from twisted.logger import Logger
from autopush.constants import DEFAULT_ROUTER_TIMEOUT
from autopush.exceptions import RouterException
from autopush.metrics import make_tags
from autopush.router.interface import RouterResponse
from autopush.types import JSONDict  # noqa

        # registration_ids are the ADM instance tokens (specified during
        # registration.
        ttl = min(self.MAX_TTL,
                  max(notification.ttl or 0, self.min_ttl))

        try:
            adm = self.profiles[router_data['creds']['profile']]
            adm.send(
                reg_id=router_data.get("token"),
                payload=data,
                collapseKey=notification.topic,
                ttl=ttl
            )
        except RouterException:
            raise  # pragma nocover
        except Timeout as e:
            self.log.warn("ADM Timeout: %s" % e)
            self.metrics.increment("notification.bridge.error",
                                   tags=make_tags(
                                       self._base_tags,
                                       reason="timeout"))
            raise RouterException("Server error", status_code=502,
                                  errno=902,
                                  log_exception=False)
        except ConnectionError as e:
            self.log.warn("ADM Unavailable: %s" % e)
            self.metrics.increment("notification.bridge.error",
                                   tags=make_tags(
                                       self._base_tags,
                                       reason="connection_unavailable"))

            raise RouterException("Server error", status_code=502,