def handle_watch_errors(self, r): self.log.warning( "Error subscribing to Google push notifications", url=r.url, response=r.content, status=r.status_code, ) if r.status_code == 400: reason = r.json()["error"]["errors"][0]["reason"] self.log.warning("Invalid request", status=r.status_code, reason=reason) if reason == "pushNotSupportedForRequestedResource": raise AccessNotEnabledError() elif r.status_code == 401: self.log.warning( "Invalid: could be invalid auth credentials", url=r.url, response=r.content, status=r.status_code, ) elif r.status_code in (500, 503): self.log.warning("Backend error in calendar API", status=r.status_code) elif r.status_code == 403: try: reason = r.json()["error"]["errors"][0]["reason"] except (KeyError, ValueError): self.log.error( "Couldn't parse API error response", response=r.content, status=r.status_code, ) if reason == "userRateLimitExceeded": # Sleep before proceeding (naive backoff) gevent.sleep(30 + random.randrange(0, 60)) self.log.warning("API request was rate-limited") elif reason == "accessNotConfigured": self.log.warning("API not enabled.") raise AccessNotEnabledError() elif r.status_code == 404: # Resource deleted! self.log.warning( "Raising exception for status", status_code=r.status_code, response=r.content, ) r.raise_for_status() else: self.log.warning("Unexpected error", response=r.content, status=r.status_code)
def handle_watch_errors(self, r): self.log.warning( 'Error subscribing to Google push notifications', url=r.url, response=r.content, status=r.status_code) if r.status_code == 401: self.log.warning( 'Invalid: could be invalid auth credentials', url=r.url, response=r.content, status=r.status_code) elif r.status_code in (500, 503): log.warning('Backend error in calendar API; retrying') gevent.sleep(30 + random.randrange(0, 60)) elif r.status_code == 403: try: reason = r.json()['error']['errors'][0]['reason'] except (KeyError, ValueError): log.error("Couldn't parse API error response", response=r.content, status=r.status_code) if reason == 'userRateLimitExceeded': log.warning('API request was rate-limited; retrying') gevent.sleep(30 + random.randrange(0, 60)) elif reason == 'accessNotConfigured': log.warning('API not enabled; returning empty result') raise AccessNotEnabledError() elif r.status_code == 404: # resource deleted! r.raise_for_status() else: self.log.warning('Unexpected error', response=r.content, status=r.status_code)
def handle_watch_errors(self, r): self.log.warning('Error subscribing to Google push notifications', url=r.url, response=r.content, status=r.status_code) if r.status_code == 400: reason = r.json()['error']['errors'][0]['reason'] self.log.warning('Invalid request', status=r.status_code, reason=reason) if reason == 'pushNotSupportedForRequestedResource': raise AccessNotEnabledError() elif r.status_code == 401: self.log.warning('Invalid: could be invalid auth credentials', url=r.url, response=r.content, status=r.status_code) elif r.status_code in (500, 503): self.log.warning('Backend error in calendar API', status=r.status_code) elif r.status_code == 403: try: reason = r.json()['error']['errors'][0]['reason'] except (KeyError, ValueError): self.log.error("Couldn't parse API error response", response=r.content, status=r.status_code) if reason == 'userRateLimitExceeded': # Sleep before proceeding (naive backoff) gevent.sleep(30 + random.randrange(0, 60)) self.log.warning('API request was rate-limited') elif reason == 'accessNotConfigured': self.log.warning('API not enabled.') raise AccessNotEnabledError() elif r.status_code == 404: # Resource deleted! self.log.warning('Raising exception for status', status_code=r.status_code, response=r.content) r.raise_for_status() else: self.log.warning('Unexpected error', response=r.content, status=r.status_code)
def _get_resource_list(self, url, **params): """Handles response pagination.""" token = self._get_access_token() items = [] next_page_token = None params['showDeleted'] = True while True: if next_page_token is not None: params['pageToken'] = next_page_token try: r = requests.get(url, params=params, auth=OAuthRequestsWrapper(token)) r.raise_for_status() data = r.json() items += data['items'] next_page_token = data.get('nextPageToken') if next_page_token is None: return items except requests.exceptions.SSLError: self.log.warning( 'SSLError making Google Calendar API request, retrying.', url=url, exc_info=True) gevent.sleep(30 + random.randrange(0, 60)) continue except requests.HTTPError: self.log.warning( 'HTTP error making Google Calendar API request', url=r.url, response=r.content, status=r.status_code) if r.status_code == 401: self.log.warning( 'Invalid access token; refreshing and retrying', url=r.url, response=r.content, status=r.status_code) token = self._get_access_token(force_refresh=True) continue elif r.status_code in (500, 503): log.warning('Backend error in calendar API; retrying') gevent.sleep(30 + random.randrange(0, 60)) continue elif r.status_code == 403: try: reason = r.json()['error']['errors'][0]['reason'] except (KeyError, ValueError): log.error("Couldn't parse API error response", response=r.content, status=r.status_code) r.raise_for_status() if reason == 'userRateLimitExceeded': log.warning('API request was rate-limited; retrying') gevent.sleep(30 + random.randrange(0, 60)) continue elif reason == 'accessNotConfigured': log.warning('API not enabled; returning empty result') raise AccessNotEnabledError() # Unexpected error; raise. raise