def _exponential_backoff(self, current_attempt, stop_time): """Sleeps for the appropriate amount of time. Or throws deadline exceeded.""" delay_factor = pow(_MLService.POLL_EXPONENTIAL_BACKOFF_FACTOR, current_attempt) wait_time_seconds = delay_factor * _MLService.POLL_BASE_WAIT_TIME_SECONDS if stop_time is not None: max_seconds_left = (stop_time - datetime.datetime.now()).total_seconds() if max_seconds_left < 1: # allow a bit of time for rpc raise exceptions.DeadlineExceededError('Polling max time exceeded.') wait_time_seconds = min(wait_time_seconds, max_seconds_left - 1) time.sleep(wait_time_seconds)
def handle_googleapiclient_error(error, message=None, code=None, http_response=None): """Constructs a ``FirebaseError`` from the given googleapiclient error. This method is agnostic of the remote service that produced the error, whether it is a GCP service or otherwise. Therefore, this method does not attempt to parse the error response in any way. Args: error: An error raised by the googleapiclient module while making an HTTP call. message: A message to be included in the resulting ``FirebaseError`` (optional). If not specified the string representation of the ``error`` argument is used as the message. code: A GCP error code that will be used to determine the resulting error type (optional). If not specified the HTTP status code on the error response is used to determine a suitable error code. http_response: A requests HTTP response object to associate with the exception (optional). If not specified, one will be created from the ``error``. Returns: FirebaseError: A ``FirebaseError`` that can be raised to the user code. """ if isinstance(error, socket.timeout) or (isinstance(error, socket.error) and 'timed out' in str(error)): return exceptions.DeadlineExceededError( message='Timed out while making an API call: {0}'.format(error), cause=error) elif isinstance(error, httplib2.ServerNotFoundError): return exceptions.UnavailableError( message='Failed to establish a connection: {0}'.format(error), cause=error) elif not isinstance(error, googleapiclient.errors.HttpError): return exceptions.UnknownError( message='Unknown error while making a remote service call: {0}'. format(error), cause=error) if not code: code = _http_status_to_error_code(error.resp.status) if not message: message = str(error) if not http_response: http_response = _http_response_from_googleapiclient_error(error) err_type = _error_code_to_exception_type(code) return err_type(message=message, cause=error, http_response=http_response)
def _poll_app_creation(self, operation_name): """Polls the Long-Running Operation repeatedly until it is done with exponential backoff.""" for current_attempt in range(_ProjectManagementService.MAXIMUM_POLLING_ATTEMPTS): delay_factor = pow( _ProjectManagementService.POLL_EXPONENTIAL_BACKOFF_FACTOR, current_attempt) wait_time_seconds = delay_factor * _ProjectManagementService.POLL_BASE_WAIT_TIME_SECONDS time.sleep(wait_time_seconds) path = '/v1/{0}'.format(operation_name) poll_response, http_response = self._body_and_response('get', path) done = poll_response.get('done') if done: response = poll_response.get('response') if response: return response raise exceptions.UnknownError( 'Polling finished, but the operation terminated in an error.', http_response=http_response) raise exceptions.DeadlineExceededError('Polling deadline exceeded.')
def handle_requests_error(error, message=None, code=None): """Constructs a ``FirebaseError`` from the given requests error. This method is agnostic of the remote service that produced the error, whether it is a GCP service or otherwise. Therefore, this method does not attempt to parse the error response in any way. Args: error: An error raised by the requests module while making an HTTP call. message: A message to be included in the resulting ``FirebaseError`` (optional). If not specified the string representation of the ``error`` argument is used as the message. code: A GCP error code that will be used to determine the resulting error type (optional). If not specified the HTTP status code on the error response is used to determine a suitable error code. Returns: FirebaseError: A ``FirebaseError`` that can be raised to the user code. """ if isinstance(error, requests.exceptions.Timeout): return exceptions.DeadlineExceededError( message='Timed out while making an API call: {0}'.format(error), cause=error) elif isinstance(error, requests.exceptions.ConnectionError): return exceptions.UnavailableError( message='Failed to establish a connection: {0}'.format(error), cause=error) elif error.response is None: return exceptions.UnknownError( message='Unknown error while making a remote service call: {0}'. format(error), cause=error) if not code: code = _http_status_to_error_code(error.response.status_code) if not message: message = str(error) err_type = _error_code_to_exception_type(code) return err_type(message=message, cause=error, http_response=error.response)