# 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/gcmclient.py
# class GCMAuthenticationError(Exception):
# class Result(object):
# class JSONMessage(object):
# class GCM(object):
#     def __init__(self, response, message):
#     def parse_response(self, content, code, message):
#     def __init__(self,
#                  registration_ids,
#                  collapse_key,
#                  time_to_live,
#                  dry_run,
#                  data):
#     def __init__(self,
#                  api_key=None,
#                  logger=None,
#                  metrics=None,
#                  endpoint="gcm-http.googleapis.com/gcm/send",
#                  **options):
#     def process(self, response, payload):
#     def error(self, failure):
#     def send(self, payload):
# 
# 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



from typing import Any  # noqa
from twisted.logger import Logger
from twisted.internet.error import ConnectError, TimeoutError
from autopush.constants import DEFAULT_ROUTER_TIMEOUT
from autopush.exceptions import RouterException
from autopush.metrics import make_tags
from autopush.router import gcmclient
from autopush.router.interface import RouterResponse
from autopush.types import JSONDict  # noqa
            self.metrics.increment("notification.bridge.error",
                                   tags=make_tags(self._base_tags,
                                                  reason="failure"))
            self.log.debug("GCM failures: {failed()}",
                           failed=lambda: repr(reply.failed.items()))
            raise RouterException("GCM unable to deliver", status_code=410,
                                  response_body="GCM recipient not available.",
                                  log_exception=False,
                                  )

        # retries:
        if reply.retry_after:
            self.metrics.increment("notification.bridge.error",
                                   tags=make_tags(self._base_tags,
                                                  reason="retry"))
            self.log.warn("GCM retry requested: {failed()}",
                          failed=lambda: repr(reply.failed.items()))
            raise RouterException("GCM failure to deliver, retry",
                                  status_code=503,
                                  headers={"Retry-After": reply.retry_after},
                                  response_body="Please try request "
                                                "in {} seconds.".format(
                                       reply.retry_after
                                  ),
                                  log_exception=False)

        self.metrics.increment("notification.bridge.sent",
                               tags=self._base_tags)
        self.metrics.increment("notification.message_data",
                               notification.data_length,

# 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/gcmclient.py
# class GCMAuthenticationError(Exception):
# class Result(object):
# class JSONMessage(object):
# class GCM(object):
#     def __init__(self, response, message):
#     def parse_response(self, content, code, message):
#     def __init__(self,
#                  registration_ids,
#                  collapse_key,
#                  time_to_live,
#                  dry_run,
#                  data):
#     def __init__(self,
#                  api_key=None,
#                  logger=None,
#                  metrics=None,
#                  endpoint="gcm-http.googleapis.com/gcm/send",
#                  **options):
#     def process(self, response, payload):
#     def error(self, failure):
#     def send(self, payload):
# 
# 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/gcm.py
from typing import Any  # noqa
from twisted.logger import Logger
from twisted.internet.error import ConnectError, TimeoutError
from autopush.constants import DEFAULT_ROUTER_TIMEOUT
from autopush.exceptions import RouterException
from autopush.metrics import make_tags
from autopush.router import gcmclient
from autopush.router.interface import RouterResponse
from autopush.types import JSONDict  # noqa

            self.metrics.increment("notification.bridge.error",
                                   tags=make_tags(self._base_tags,
                                                  reason="failure"))
            self.log.debug("GCM failures: {failed()}",
                           failed=lambda: repr(reply.failed.items()))
            raise RouterException("GCM unable to deliver", status_code=410,
                                  response_body="GCM recipient not available.",
                                  log_exception=False,
                                  )

        # retries:
        if reply.retry_after:
            self.metrics.increment("notification.bridge.error",
                                   tags=make_tags(self._base_tags,
                                                  reason="retry"))
            self.log.warn("GCM retry requested: {failed()}",
                          failed=lambda: repr(reply.failed.items()))
            raise RouterException("GCM failure to deliver, retry",
                                  status_code=503,
                                  headers={"Retry-After": reply.retry_after},
                                  response_body="Please try request "
                                                "in {} seconds.".format(
                                       reply.retry_after
                                  ),
                                  log_exception=False)

        self.metrics.increment("notification.bridge.sent",
                               tags=self._base_tags)
        self.metrics.increment("notification.message_data",
                               notification.data_length,

                               tags=make_tags(self._base_tags,